使用Jsoup抓取資料
阿新 • • 發佈:2019-02-03
問題
最近公司的市場部分佈了一個問題,到一個網站擷取一下醫院的資料。剛好我也被安排做。後來,我發現為何不用指令碼去抓取呢?
抓取的資料如下:
Jsoup的使用實戰程式碼
結構
- 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();
- 學會用指令碼收集資料
- 注意多謝執行緒併發的安全,要檢驗,要不很易出錯
- 對於多執行緒的問題關鍵是要確保你的內容不被競爭弄亂,所以提取出來進行程式碼塊是很重要的。
最後補充一下最終的效果如下圖