日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

网页爬虫的设计与实现(Java版)

發布時間:2023/12/2 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网页爬虫的设计与实现(Java版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近為了練手而且對網頁爬蟲也挺感興趣,決定自己寫一個網頁爬蟲程序。
首先看看爬蟲都應該有哪些功能。

內容來自(http://www.ibm.com/developerworks/cn/java/j-lo-dyse1/index.html?ca=drs-)

網頁收集的過程如同圖的遍歷,其中網頁就作為圖中的節點,而網頁中的超鏈接則作為圖中的邊,通過某網頁的超鏈接 得到其他網頁的地址,從而可以進一步的進行網頁收集;圖的遍歷分為廣度優先和深度優先兩種方法,網頁的收集過程也是如此。綜上,Spider 收集網頁的過程如下:從初始 URL 集合獲得目標網頁地址,通過網絡連接接收網頁數據,將獲得的網頁數據添加到網頁庫中并且分析該網頁中的其他 URL 鏈接,放入未訪問 URL 集合用于網頁收集。下圖表示了這個過程:



網頁收集器 Gather

網頁收集器通過一個 URL 來獲取該 URL 對應的網頁數據,其實現主要是利用 Java 中的 URLConnection 類來打開 URL 對應頁面的網絡連接,然后通過 I/O 流讀取其中的數據,BufferedReader 提供讀取數據的緩沖區提高數據讀取的效率以及其下定義的 readLine() 行讀取函數。代碼如下 ( 省略了異常處理部分 ):

URL url = new URL(“http://www.xxx.com”);? URLConnection conn = url.openConnection();? BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));? String line = null; while((line = reader.readLine()) != null)??????????document.append(line + "\n");

網頁處理

收集到的單個網頁,需要進行兩種不同的處理,一種是放入網頁庫,作為后續處理的原始數據;另一種是被分析之后,抽取其中的 URL 連接,放入 URL 池等待對應網頁的收集。

網頁的保存需要按照一定的格式,以便以后數據的批量處理。這里介紹一種存儲數據格式,該格式從北大天網的存儲格式簡化而來:

  • 網頁庫由若干記錄組成,每個記錄包含一條網頁數據信息,記錄的存放為順序添加;
  • 一條記錄由數據頭、數據、空行組成,順序為:頭部 + 空行 + 數據 + 空行;
  • 頭部由若干屬性組成,有:版本號,日期,IP 地址,數據長度,按照屬性名和屬性值的方式排列,中間加冒號,每個屬性占用一行;
  • 數據即為網頁數據。

需要說明的是,添加數據收集日期的原因,由于許多網站的內容都是動態變化的,比如一些大型門戶網站的首頁內容,這就意味著如果不是當天爬取的網頁數據,很可能發生數據過期的問題,所以需要添加日期信息加以識別。

URL 的提取分為兩步,第一步是 URL 識別,第二步再進行 URL 的整理,分兩步走主要是因為有些網站的鏈接是采用相對路徑,如果不整理會產生錯誤。URL 的識別主要是通過正則表達式來匹配,過程首先設定一個字符串作為匹配的字符串模式,然后在 Pattern 中編譯后即可使用 Matcher 類來進行相應字符串的匹配。實現代碼如下:

public ArrayList<URL> urlDetector(String htmlDoc) {? final String patternString = "<[a|A]\\s+href=([^>]*\\s*>)";? Pattern pattern = Pattern.compile(patternString,Pattern.CASE_INSENSITIVE);? ArrayList<URL> allURLs = new ArrayList<URL>();? Matcher matcher = pattern.matcher(htmlDoc);? String tempURL; //初次匹配到的url是形如:<a href="http://bbs.life.xxx.com.cn/" target="_blank">? //為此,需要進行下一步的處理,把真正的url抽取出來,? //可以對于前兩個"之間的部分進行記錄得到url? while(matcher.find()){??????try {??????????tempURL = matcher.group();??????????tempURL = tempURL.substring(tempURL.indexOf("\"")+1);??????????if(!tempURL.contains("\"")) continue;??????????tempURL = tempURL.substring(0, tempURL.indexOf("\""));??????????}???????catch (MalformedURLException e)??????????{ e.printStackTrace(); }???}? return allURLs; }

按照“<[a|A]\\s+href=([^>]*\\s*>)”這個正則表達式可以匹配出 URL 所在的整個標簽,形如“<a href="http://bbs.life.xxx.com.cn/" target="_blank">”,所以在循環獲得整個標簽之后,需要進一步提取出真正的 URL,我們可以通過截取標簽中前兩個引號中間的內容來獲得這段內容。如此之后,我們可以得到一個初步的屬于該網頁的 URL 集合。

接下來我們進行第二步操作,URL 的整理,即對之前獲得的整個頁面中 URL 集合進行篩選和整合。整合主要是針對網頁地址是相對鏈接的部分,由于我們可以很容易的獲得當前網頁的 URL,所以,相對鏈接只需要在當前網頁的 URL 上添加相對鏈接的字段即可組成完整的 URL,從而完成整合。另一方面,在頁面中包含的全面 URL 中,有一些網頁比如廣告網頁是我們不想爬取的,或者不重要的,這里我們主要針對于頁面中的廣告進行一個簡單處理。一般網站的廣告連接都有相應的顯示表達, 比如連接中含有“ad”等表達時,可以將該鏈接的優先級降低,這樣就可以一定程度的避免廣告鏈接的爬取。

經過這兩步操作時候,可以把該網頁的收集到的 URL 放入 URL 池中,接下來我們處理爬蟲的 URL 的派分問題。

Dispatcher 分配器

分配器管理 URL,負責保存著 URL 池并且在 Gather 取得某一個網頁之后派分新的 URL,還要避免網頁的重復收集。分配器采用設計模式中的單例模式編碼,負責提供給 Gather 新的 URL,因為涉及到之后的多線程改寫,所以單例模式顯得尤為重要。

重復收集是指物理上存在的一個網頁,在沒有更新的前提下,被 Gather 重復訪問,造成資源的浪費,主要原因是沒有清楚的記錄已經訪問的 URL 而無法辨別。所以,Dispatcher 維護兩個列表 ,“已訪問表”,和“未訪問表”。每個 URL 對應的頁面被抓取之后,該 URL 放入已訪問表中,而從該頁面提取出來的 URL 則放入未訪問表中;當 Gather 向 Dispatcher 請求 URL 的時候,先驗證該 URL 是否在已訪問表中,然后再給 Gather 進行作業。

Spider 啟動多個 Gather 線程

現在 Internet 中的網頁數量數以億計,而單獨的一個 Gather 來進行網頁收集顯然效率不足,所以我們需要利用多線程的方法來提高效率。Gather 的功能是收集網頁,我們可以通過 Spider 類來開啟多個 Gather 線程,從而達到多線程的目的。代碼如下:

public void start()? {? Dispatcher disp = Dispatcher.getInstance();? for(int i = 0; i < gatherNum; i++) {?????Thread gather = new Thread(new Gather(disp));?????gather.start();? } } 在開啟線程之后,網頁收集器開始作業的運作,并在一個作業完成之后,向 Dispatcher 申請下一個作業,因為有了多線程的 Gather,為了避免線程不安全,需要對 Dispatcher 進行互斥訪問,在其函數之中添加 synchronized 關鍵詞,從而達到線程的安全訪問。

總結

以上是生活随笔為你收集整理的网页爬虫的设计与实现(Java版)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。