網路採集器Demo:Jsoup+Java多執行緒實現[爬蟲](上)
裡面最簡單,但是很常用的一個部分,就是網路爬蟲,從網頁上獲取文字資訊
這裡用到兩個工具,一個就是Java多執行緒(基於Java5 以上的執行緒池模式,區別於過時的Runable),另外一個是一個小工具:Jsoup,用於解析html網頁,獲取其中的內容,關於Jsoup的使用,這是一個技術活,在下面的描述中會介紹一些基礎操作,但主要還是需要師弟們自己去學習:http://www.open-open.com/jsoup/。
demo的功能是,爬取新浪主頁的新聞文字內容。
下面我們一步一步來:
新浪首頁即是我們的種子頁面,首先我們需要獲取新浪首頁上的全部內容連結
1.用Jsoup獲得種子頁面的html程式碼
第7行解釋:連結到要獲取html程式碼的url,設定等待時間,忽略http錯誤,忽略網頁內容編碼格式public class JsoupGetDocument { public static Document getDocumentByJsoupBasic(String url) { try { // 設定連線超時和讀數超時 // 設定忽略過期頁面 return Jsoup.connect(url).timeout(120000).ignoreHttpErrors(true) .ignoreContentType(true).get(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } }
返回的是Jsoup中的Docment物件,內包含html程式碼以及其結構資訊,它可以用作我們進一步對獲取的html程式碼分析。
2.獲得種子頁面上的全部有效連結
第8行獲得頁面Docment物件後,第10行獲得全部帶有連結資訊的元素塊,這裡Elements物件是一個集合,其中每一個Element都是單獨一個含有連結的html子塊,這裡要注意,select方法是Jsoup精髓,傳入的引數是一個匹配html程式碼位置的模式串,關於這個模式串的設計,就是之前說的技術活,學習:http://www.open-open.com/jsoup/selector-syntax.htm。下面的迴圈是對每個子塊中的連結元素進行提取,並加入結果集合。public class FetchLinksFromPage { // 獲得所有的連結 public Set<ExactLinks> getAllUrl(String seedUrl) { Set<ExactLinks> urlSet = new HashSet<ExactLinks>(); try { Document docPage = JsoupGetDocument .getDocumentByJsoupBasic(seedUrl); Elements eleLinks = docPage.select("a[href]"); for (Element eleLink : eleLinks) { String url = eleLink.attr("abs:href"); String urlMD5 = new TransMD5().getMD5Code(url); urlSet.add(new ExactLinks(url, urlMD5)); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return urlSet; } // 過濾出有用的url public Set<ExactLinks> filterUrl(String seedUrl) { Set<ExactLinks> urlSet = this.getAllUrl(seedUrl); Set<ExactLinks> filterLinks = new HashSet<ExactLinks>(); for (String urlModel : CrawlUnitParam.SINA_URL_MODEL) { for (ExactLinks links : urlSet) { if (links.getUrl().contains(urlModel)) { filterLinks.add(links); } } } return filterLinks; } }
getAllUrl返回的是種子頁面上全部錨鏈接的集合,注意這個集合用的是HashSet,可以自動排除重複的連結,可以自己設計一個ExactLinks類,需要重寫hashCode和equals函式。但是,到這一步並沒有結束,filterUrl方法是為了過濾無用的連結,CrawlUnitParam.SINA_URL_MODEL中儲存的是有用連結的模式集合,可以自己設計,匹配成功才加入最終的集合,並返回。我的模式集合是:
public class CrawlUnitParam {
public static List<String> SINA_URL_MODEL = new ArrayList<String>();
static {
SINA_URL_MODEL.add(".shtml");
SINA_URL_MODEL.add(".html");
}
}
可以自己列印一下解析出來的全部連結。
3.解析獲得每個連結中的文字內容
我們將上面的每個連結傳入函式getParagraphContent,返回該頁中有效的文字內容
public class FetchPaContentFromPage {
public String getParagraphContent(String pageUrl) {
String paragraphContent = "";
try {
Document docPage = JsoupGetDocument
.getDocumentByJsoupBasic(pageUrl);
Elements eleParagraphs = docPage.select("p");
for (Element eleParagraph : eleParagraphs) {
String content = eleParagraph.text();
paragraphContent += content;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
return paragraphContent;
}
}
同樣在第8行獲得頁面的Docment物件之後,下面就是對包含有效文字的html子塊進行抽取,還是使用select方法,至於什麼是有效的文字資訊,這些內容包含在具有什麼特點的html子塊中,需要我們分析網站頁面的html程式碼,新浪新聞的有效資訊就包含在<p></p>子塊中,於是我們如上進行抽取。
下面迴圈中的text方法是獲得html程式碼子塊中包含的文字資訊,對所有這樣的文字資訊進行拼接,返回。
好了,經過以上的步驟,相信師弟們自己完成一個序列的採集器沒有問題了吧,但是我並沒有那樣實現,下一節將描述一個並行實現的採集器,這樣我們會獲得更高的效率。