問題的由來
前幾天,在微信公眾號(Python爬蟲及算法)上有個人問了筆者一個問題,如何利用爬蟲來實現如下的需求,需要爬取的網頁如下(網址為:https://www.wikidata.org/w/index.php?title=Special:WhatLinksHere/Q5&limit=500&from=0):
我們的需求為爬取紅色框框內的名人(有500條記錄,圖片只展示了一部分)的 名字以及其介紹,關於其介紹,點擊該名人的名字即可,如下圖:
這就意味着我們需要爬取500個這樣的頁面,即500個HTTP請求(暫且這么認為吧),然后需要提取這些網頁中的名字和描述,當然有些不是名人,也沒有描述,我們可以跳過。最后,這些網頁的網址在第一頁中的名人后面可以找到,如George Washington的網頁后綴為Q23.
爬蟲的需求大概就是這樣。
爬蟲的4種姿勢
首先,分析來爬蟲的思路:先在第一個網頁(https://www.wikidata.org/w/index.php?title=Special:WhatLinksHere/Q5&limit=500&from=0)中得到500個名人所在的網址,接下來就爬取這500個網頁中的名人的名字及描述,如無描述,則跳過。
接下來,我們將介紹實現這個爬蟲的4種方法,並分析它們各自的優缺點,希望能讓讀者對爬蟲有更多的體會。實現爬蟲的方法為:
- 一般方法(同步,requests+BeautifulSoup)
- 並發(使用concurrent.futures模塊以及requests+BeautifulSoup)
- 異步(使用aiohttp+asyncio+requests+BeautifulSoup)
- 使用框架Scrapy
一般方法
一般方法即為同步方法,主要使用requests+BeautifulSoup,按順序執行。完整的Python代碼如下:
輸出的結果如下(省略中間的輸出,以…代替):
使用同步方法,總耗時約725秒,即12分鍾多。
一般方法雖然思路簡單,容易實現,但效率不高,耗時長。那么,使用並發試試看。
並發方法
並發方法使用多線程來加速一般方法,我們使用的並發模塊為concurrent.futures模塊,設置多線程的個數為20個(實際不一定能達到,視計算機而定)。完整的Python代碼如下:
輸出的結果如下(省略中間的輸出,以…代替):
使用多線程並發后的爬蟲執行時間約為227秒,大概是一般方法的三分之一的時間,速度有了明顯的提升啊!多線程在速度上有明顯提升,但執行的網頁順序是無序的,在線程的切換上開銷也比較大,線程越多,開銷越大。
關於多線程與一般方法在速度上的比較,可以參考文章:Python爬蟲之多線程下載豆瓣Top250電影圖片。
異步方法
異步方法在爬蟲中是有效的速度提升手段,使用aiohttp可以異步地處理HTTP請求,使用asyncio可以實現異步IO,需要注意的是,aiohttp只支持3.5.3以后的Python版本。使用異步方法實現該爬蟲的完整Python代碼如下:
輸出結果如下(省略中間的輸出,以…代替):
顯然,異步方法使用了異步和並發兩種提速方法,自然在速度有明顯提升,大約為一般方法的六分之一。異步方法雖然效率高,但需要掌握異步編程,這需要學習一段時間。
關於異步方法與一般方法在速度上的比較,可以參考文章:利用aiohttp實現異步爬蟲。
如果有人覺得127秒的爬蟲速度還是慢,可以嘗試一下異步代碼(與之前的異步代碼的區別在於:僅僅使用了正則表達式代替BeautifulSoup來解析網頁,以提取網頁中的內容):
輸出的結果如下(省略中間的輸出,以…代替):
16.5秒,僅僅為一般方法的43分之一,速度如此之快,令人咋舌(感謝某人提供的嘗試)。筆者雖然自己實現了異步方法,但用的是BeautifulSoup來解析網頁,耗時127秒,沒想到使用正則表達式就取得了如此驚人的效果。可見,BeautifulSoup解析網頁雖然快,但在異步方法中,還是限制了速度。但這種方法的缺點為,當你需要爬取的內容比較復雜時,一般的正則表達式就難以勝任了,需要另想辦法。
爬蟲框架Scrapy
最后,我們使用著名的Python爬蟲框架Scrapy來解決這個爬蟲。我們創建的爬蟲項目為wikiDataScrapy,項目結構如下:
在settings.py中設置“ROBOTSTXT_OBEY = False”. 修改items.py,代碼如下:
然后,在spiders文件夾下新建wikiSpider.py,代碼如下:
輸出結果如下(只包含最后的Scrapy信息總結部分):
可以看到,已成功爬取500個網頁,耗時31秒,速度也相當OK。再來看一下生成的wiki.csv文件,它包含了所有的輸出的name和description,如下圖:
可以看到,輸出的CSV文件的列並不是有序的。至於如何解決Scrapy輸出的CSV文件有換行的問題,請參考stackoverflow上的回答:https://stackoverflow.com/questions/39477662/scrapy-csv-file-has-uniform-empty-rows/43394566#43394566 。
Scrapy來制作爬蟲的優勢在於它是一個成熟的爬蟲框架,支持異步,並發,容錯性較好(比如本代碼中就沒有處理找不到name和description的情形),但如果需要頻繁地修改中間件,則還是自己寫個爬蟲比較好,而且它在速度上沒有超過我們自己寫的異步爬蟲,至於能自動導出CSV文件這個功能,還是相當實在的。
總結
本文內容較多,比較了4種爬蟲方法,每種方法都有自己的利弊,已在之前的陳述中給出,當然,在實際的問題中,並不是用的工具或方法越高級就越好,具體問題具體分析嘛~
本文到此結束,感謝閱讀哦~
此文轉載文,著作權歸作者所有,如有侵權聯系小編刪除!
原文地址:https://blog.csdn.net/jclian91/article/details/83095306
需要源代碼或者想了解更多點擊這里下載