1.運行過程概述
是一個基于的網絡爬蟲框架,它讀取對指定域名的網頁請求,截取對應域名的返回體,開發者可以編寫解析函數,從返回體中抓取自己需要的數據,并對數據進行清洗處理或存入數據庫。
工程的爬蟲全部存放于工程二級目錄下的文件夾中,使用命令可以構建新的爬蟲腳本,使用crawl命令可以使指定爬蟲腳本運行。下面簡述爬蟲代碼的運行過程。
實際上,有一個被提前定義好的方法(self)。在沒有被重構的情況下,該方法會讀取列表中的url字符串,默認使用get請求方式訪問這些url,并默認回調解析函數parse。parse函數以請求得到的返回體為參數,進行對應的解析數據操作。采用命令生成的爬蟲初始狀態如下:
2.的使用技巧和注意事項
2.1 對多個數據源進行不同的解析處理
顯然,方法和parse方法都是可以被重構的。重構parse方法,就可以更改對網頁返回體的處理方式。解析函數并不是唯一的,可以自行定義多個解析函數,也并不是必須命名為parse,重構函數就能指定使用哪個函數對數據進行處理,實例如下:
如圖所示,重構方法后,對于帶有baidu字符的url,指向第一個解析函數,否則指向第二個解析函數,也就是說,中定義的兩個url,會在爬蟲執行的過程中經過不同的處理方式,這就是對多個不同的數據源采用不同解析方式的實現方法。
2.2 數據元素的定位
找到正確的網頁元素位置是爬蟲獲取數據的關鍵。對于結構單一的靜態網頁,只需要采用(快捷鍵F12)自帶的元素檢查功能,就能定位到元素所在的位置,根據其采用的網頁設計樣式,使用自帶的進行篩選,常用的篩選器有xpath和css,這是爬蟲曾經常用的傳統方法。
但實際操作中,并非所有網頁元素都可以通過元素檢查功能進行正確定位,一些錯誤的理解會導致數據無法真正的定位。下面舉一個例子:
如圖所見,如果使用的元素檢查功能定位“總計費用”字段的80.00數值,可以發現,數值80.00被放在了標簽為“em”的網頁樣式中。如果單純地認為數據已經被正確定位到html中的某個標簽下,那么就大錯特錯了,我們打開網頁源碼,查找一下80.00字符串:
可以看到,80.00在網頁源碼中并不存在。
這是為什么呢?實際上,元素檢查功能會將靜態頁面下的網頁版式和所有動態生成的數據展示為一個“頁面”。這個頁面上的源碼實際上是多個不同的網頁格式和網頁腳本共同生成的,它的代碼并不是真正的網頁源碼。這種不存在于html網頁的數據,實際上就是一種“動態數據”。
時下比較常用的存儲動態數據的方式,一般是通過腳本生成,或使用ajax異步加載。在已知數據加載類型的前提下,使用的過濾器進行元素檢查是更好的方式。
如果數據通過ajax異步加載,則過濾器設置為XHR,如果數據采用腳本直接生成,則過濾器設置為JS。還有一個比較常用的過濾器是DOC,它是用來選擇靜態頁面的。一些數據量較小的網站可能會將頁面數據直接寫在html中,DOC過濾器主要應對這種小型的網站。
而我們要查找的80.00字段,它實際上是通過ajax異步加載的數據,既然是異步加載的數據,就可以通過異步請求得到,因此,反復點擊頁面的一些按鈕,如果整個頁面沒有被刷新靜態網頁的爬取思路,只有一部分刷新,那么這些刷新出來的數據就可以通過設置過濾器為XHR找到。
經過查找可以發現,80.00這個數據是一個異步請求的返回體中攜帶的兩個數據20和60的加和,如圖所示:
它的返回體是一個json,并不是網頁標簽包含下的數據靜態網頁的爬取思路,因此處理方式不能使用,而是需要引用json庫,按包含鍵值對的字典操作進行處理。而它的url也不是原網頁html,而是下圖中紅框圈出的 URL:
用戶瀏覽網頁時,被加載的網頁會自動向其它url中獲取數據,因此可以得到來自很多不同的url的數據。但是爬蟲不能享受這樣的待遇,因此爬蟲的撰寫者需要額外費一番心思查找數據,依靠反復搜索,甚至需要結合html編碼的經驗才行。2.3 的并發性與程序邏輯
是并行爬取框架,在默認的情況下不能用來做指定時序的爬蟲。
會瞬間將列表內的數個url放入爬取隊列中,爬取隊列最多同時處理8個url的請求,哪個url的請求最先得到回應,哪個url的parse方法就最先被執行,(多個parse方法不會交叉執行)。在多個url的頁面結構相近的前提下,哪個頁面最先返回,幾乎是隨機的。因此,在中定義的列表順序某種意義上是無效的。如果一定想要順序爬取,該怎么辦呢?實際上這是一個并不常見的需求,如下幾個思路可以考慮一下:
思路一,可以在.py中指定并發上限,默認值為8,如果設置為1,則變為順序爬蟲,按列表內各個url的排布順序爬取,失去并發性。其效果如下圖所示:
圖一是并發上限為8的情況下,反復多次對5個新聞標題的爬取結果,圖二是并發上限為調整為1之后的結果,可以看到,并發上限設置為1時,新聞的多個標題爬取順序是固定的,和的列表順序一致。
這種方法雖然能讓爬蟲按照程序內的邏輯順序執行爬取,但會使爬蟲的效率降低。首先,并不擅長單頁面的爬取。其次,如果將請求并發數置為1,一旦其中的某個頁面由于各種原因被阻塞,則整個爬蟲都會受到影響,效率大大降低。另外,.py是一個全局設置,更改了.py會使整個工程所有的爬蟲發生變化。
思路二,可以手動定義多個解析函數,令這些解析函數互相顯式調用。這種方法過于笨重,不推薦使用。思路三,引入其他能瞬時發出請求的庫(如),在解析函數中進行爬取邏輯設計。這種方法雖然看起來有點“犯規”,但不失為一種很有效的解決方式。只要不破壞框架本身的結構,進行這樣的設計是完全沒有問題的。
這些設計思路都是為了解決按順序爬取多個數據源的問題,但是這也必然會引發“單通道阻塞”的傳統問題。這是一個邏輯問題,與框架結構無關,因此不可避免。需要注意的是,依然是以多線程并行處理能力見長的爬蟲框架,設計爬蟲時要盡可能揚長避短。
了解新鈦云服
新鈦云服出品的部分精品技術干貨