您的位置:首页 > Web前端 > JavaScript

使用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 jsoup