使用Jsoup抓取数据
2016-02-18 16:51
666 查看
问题
最近公司的市场部分布了一个问题,到一个网站截取一下医院的数据。刚好我也被安排做。后来,我发现为何不用脚本去抓取呢?抓取的数据如下:
Jsoup的使用实战代码
结构Created with Raphaël 2.1.0开始创建线程池jsoup读取网页解析Element写入sqlite结束
java代码
public class GetDoctorInfo { public GetDoctorInfo() { ExecutorService threadPool = Executors.newFixedThreadPool(5); //43有问题 //73有问题 for (int i = 1; i <= 100; i++) { String path = "http://so.haodf.com/index/search?type=hospitalfaculty&p=" + i + "&kw=%B8%BE%B2%FA%BF%C6"; threadPool.execute(new GetDoctorRun(path)); } threadPool.shutdown(); } public static void main(String[] arg) { new GetDoctorInfo(); } public static synchronized void printInfo(String sql) { System.out.println(sql); } public static String trans(String input) { String value; value = input.replaceAll("<td>", "").replaceAll("</td>", "").replaceAll(" ", "").replaceAll(" 地址地图:", ""); return value; } /** * 获取医生的线程 */ public class GetDoctorRun implements Runnable { final String mURL; public GetDoctorRun(String mURL) { this.mURL = mURL; } @Override public void run() { try { Document doc = null; try { // doc = (Document) Jsoup.parse(new URL("http://so.haodf.com/index/search?type=hospitalfaculty&p=99&kw=%B8%BE%B2%FA%BF%C6") // , 1000); doc = (Document) Jsoup.parse(new URL(mURL), 3000); } catch (IOException e) { e.printStackTrace(); } //定位到列表 Elements elements = doc.getElementsByClass("list"); Elements childElements = elements.get(0).getAllElements(); Element child = childElements.get(3); //获得所有的超链接的数据 Elements aLinks = child.getElementsByTag("a"); ArrayList<String> name = new ArrayList<>(); ArrayList<String> address = new ArrayList<>(); for (int i = 1; i <= aLinks.size(); i++) { Element e = aLinks.get(i - 1); if (e.attr("target").equals("_blank")) { //排除 科室介绍 //排除 门诊时间 if (!e.text().equals("科室介绍") && !e.text().equals("门诊时间")) { // System.out.println("--" + e.text()); if (i % 2 == 0) { if (e.text().equals("") || e.text() == null) { address.add(""); } else { address.add(e.text()); } } else { if (e.text().equals("") || e.text() == null) { name.add(""); } else { name.add(e.text()); } } } } } //将长连接的内容删除 child.select("a").remove(); child.select("span").remove(); child.select("br").remove(); String tran = trans(child.toString()); // System.out.println(tran); String[] phones = tran.substring(" 电 话:".length(), tran.length() - 1).split("电 话:"); System.out.println(); System.out.println(); System.out.println(); for (int i = 0; i < name.size(); i++) { // System.out.println(phones[i]); // //INSERT INTO info(hospital_name,address,phone) VALUES ('gg','hhh','ddd'); StringBuffer bufferValue = new StringBuffer("INSERT INTO info(hospital_name,address,phone) VALUES ("); //医院名 bufferValue.append("'").append(name.get(i)).append("'"); //医院地址 bufferValue.append(",'").append(address.get(i)).append("'"); //医院的电话 bufferValue.append(",'").append(phones[i].trim()).append("');"); printInfo(bufferValue.toString()); } if (name.size() != 10) { System.out.println("name==" + mURL); } if (address.size() != 10) { System.out.println("address=" + mURL); } if (phones.length != 10) { System.out.println("phone=" + phones.length + " " + mURL); } } catch (Exception e) { e.printStackTrace(); } } } }
Terminal写入sqlte
.open hospital.db
sqlite3 -init sql
总结
jsoup的使用很简单,有点像解析xml。不过结果很好的,因为5,6个人的工作就被这个简单的代码实现了。解析技巧有一个尽量清除不必要的标签。如代码:child.select("a").remove(); child.select("span").remove(); child.select("br").remove();
学会用脚本收集数据
注意多谢线程并发的安全,要检验,要不很易出错
对于多线程的问题关键是要确保你的内容不被竞争弄乱,所以提取出来进行代码块是很重要的。
最后补充一下最终的效果如下图
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树