python网络爬虫-采集整个网站
? ? ? 上一篇文章中,實現了在一個網站上隨機地從一個鏈接跳掉另一個鏈接。但是,如果需要系統地把整個網站按目錄分類,或者要搜索網站上的每一個頁面,就得采集整個網站,那是一種非常耗費內存資源的過程,尤其處理大型網站時,最合適的工具就是用一個數據庫來儲存采集的資源。
?1. 深網和暗網
? ? ?你可能聽說過深網(deep Web)、暗網(dark Web)或者隱藏網絡(hidden Web)之類的術語,尤其在最近的媒體中。它們是什么意思呢?深網是網絡的一部分,與淺網(surface Web)對立。淺網是互聯網上搜索引擎可以抓到的那部分網絡。據不完全統計,互聯網中其實約90%網絡都是深網。因為谷歌不能做像表單提交這類事情,也找不到那些沒有直接鏈接到頂層域名上的網頁,或者因為有robots.txt禁止而不能查看網站,所以淺網的數量相對深網還是比較少的。
? ? ?暗網,也被稱為Darknet或者dark Internet,完全是另一種“怪獸”。它們也建立在已有的網絡基礎上,但是使用Tor客戶端,帶有運行在HTTP之上的新協議,提供了一個信息交換的安全隧道。這類暗網頁面也是可以采集的,就像你采集其他網站一樣,不過這些內容超出了本章的討論范圍。
? ? ?和暗網不同,深網相對容易采集。可以讓你采集那些Google爬蟲機器人不能獲取的深網信息。
2. 遍歷整個網站的網絡數據采集有許多好處:
? (1)生成網站地圖
? ? ? ?使用爬蟲采集整個網站,收集所有的鏈接,再把所有的頁面整理成網站實際的形式。
? (2)收集數據
? ? ? 創建一個專業垂直領域的搜索平臺,想收集一些文章(博客,新聞、故事等)。雖然這些網站采集不費勁,但是它們需要爬蟲有足夠的深度(我們有意猴急數據的網站不多)。于是創建一個爬蟲遞歸地遍歷每個網站,只收集那些網站頁面上的數據。一個常用的費時的網站采集方法就是從頂級頁面開始(比如主頁),然后搜索頁面上的所有鏈接,形成列表。再去采集這些鏈接的每一個頁面,然后把每個頁面上找到的鏈接形成新的列表,重復執行下一輪采集。
? ? ? 很明顯,這是一個復雜度增長很快的情形。假如每個頁面有10個鏈接,網站上有5個頁面深度(一個中等規模的主流深度),那么如果你要采集整個網站,一共得采集的網頁數量就是10^5,即100000個頁面。不過,雖然“5個頁面深度,每頁10個鏈接”是網站的主流配置,但其實很少的網站真有100000甚至更多的頁面,這是因為很大一部分內鏈都是重復的。
? ? ?為了避免一個頁面被采集兩次,鏈接去重是非常重要的。在代碼運行時,把已發現的所有鏈接放到一起,并保存在方便查詢的列表里(下文示例指Python的集合set類型)。只有新的鏈接才會被采集,之后再從頁面中搜索其他鏈接。
from urllib.request import urlopen from bs4 import BeautifulSoup import repages=set() def getLinks(pageUrl):global pageshtml=urlopen("https://en.wikipedia.org"+pageUrl)bsObj=BeautifulSoup(html,"html.parser")for link in bsObj.findAll("a",href=re.compile("^(/wiki/)")):if 'href' in link.attrs:if link.attrs["href"] not in pages:print(newPage)newPage=link.attrs["href"]pages.add(newPage)getLinks(newPage)getLinks("") ? ? ? 為了全面地展示這個網絡數據采集示例是如何工作的,我去除了“只尋找內鏈”的標準。不再限制爬蟲采集的頁面范圍,只要遇到頁面就查找所有以/wiki/開頭的鏈接,也不考慮鏈接是不是包含分號。? ? ?一開始,用getLinks處理一個空URL,其實是維基百科的主頁,因為在函數里空URL就是https://en.wikipedia.org。然后遍歷首頁上每一個鏈接,并檢查是否已經在全局變量pages集合中。如果不在,則打印到屏幕,并添加到pages集合中,再用getLinks遞歸地處理這個鏈接。這邊需要注意一點,python默認的遞歸限制是1000次,程序到達遞歸限制后就會自動停止。
3. 收集整個網站數據
? ? ?當然,如果只從一個頁面跳轉到另一個頁面,那么網絡爬蟲是非常無聊的。為了有效地使用它們,在用爬蟲的時候我們需要在頁面上做些事情。讓我們看看如何創建一個爬蟲來收集頁面標題,正文的第一個段落,以及編輯頁面的鏈接(如果有的話)這些信息。
? ? ?和往常一樣,決定如何做好這些事情的第一步就是先觀察網站上的一些頁面,然后擬定一個采集模式。通過觀察幾個維基百科頁面,包括詞條頁面和非詞條頁面,比如隱私策略之類的頁面,就會得到下面的規則:
? ? ?(1)所有的標題(所有頁面上,不論是詞條頁面,編輯歷史頁面還是其他頁面)都是在h1-span標簽里,而且頁面上只有一個h1標簽;
? ? ?(2)前面提到過,所有正文文字都在div#bodyContent標簽里。但是,如果我們想要進一步獲取第一段文字,可能用div#mw-contet-text->p更好(只選擇第一段的標簽)。這個規則對所有頁面都適用,除了文件頁面,頁面不包含內容文字(content text)的部分內容
? ? ? (3)編輯鏈接只出現在詞條頁面上,如果有編輯鏈接,都位于li#ca-edit->span->a里面。
? ?完整的程序代碼如下:
from urllib.request import urlopen from bs4 import BeautifulSoup import repages=set() def getLinks(pageUrl):global pageshtml=urlopen("https://en.wikipedia.org"+pageUrl)bsObj=BeautifulSoup(html,"html.parser")try:print(bsObj.h1.get_text())print(bsObj.find(id="mw-content-text").findAll("p")[0])print(bsObj.find(id="ca-edit").find("span").find("a").attrs['href'])except AttributeError:print("頁面缺少一些屬性,Don't worry")for link in bsObj.findAll("a",href=re.compile("^(/wiki/)")):if 'href' in link.attrs:if link.attrs["href"] not in pages:print("---------\n"+newPage)newPage=link.attrs["href"]pages.add(newPage)getLinks(newPage)getLinks("") 因為我們不可能確保每一頁上都有所有類型的數據,所以每個打印語句都是按照數據在頁面上出現的可能性從高到低排列的。也就是說,<h1>標題標簽會出現在每一頁上,所以我們首先嘗試獲取它的數據。正文內容會出現在大多數頁面上(除了文件頁面),因此是第二個獲取的數據。“編輯”按鈕只出現在標題個正文內容都已經獲取的頁面上,不是所有頁面都有,因此放在最后。總結
以上是生活随笔為你收集整理的python网络爬虫-采集整个网站的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OFFICE2003/2007/2010
- 下一篇: 材料工程赋