第一個問題:JS加密如何突破
(1) 熟練掌握Chrome的開發者工具的各個功能,Elements, Network,Source
(2) 認真觀察,善于思考。Network查看加載流程,找可疑的xhr請求,設置xhr斷點,通過Call Stack 回溯js執行過程,邊回溯邊查看上下文代碼。能讀懂js,知道js的相關知識,比如js里面的window變量。
(3) 以上是通過debug js找到js加密解密的代碼,然后通過Python重新實現,這個過程很長,可能耗費你幾天的時間,一旦網站改變一下js算法你的Python實現就不能用了。
(4) 用Selenium可簡單突破,并且網站隨便該都無所謂。唯一遺憾的是,Selenium的運行效率較差。但是,作為一個能用js加密來保護數據的網站,單價的運行效率應該足以滿足網站的訪問頻率限制。這時候,更多的思考是如何增加資源(IP、賬號)來提高抓取效率。
第二個問題、多線程、協程,多進程的選擇
(1)爬蟲是IO密集型任務,大部分時間花在網絡訪問上,所以多進程不適合網絡爬蟲,而多線程、異步IO協程更適合,而異步IO是最適合的,它相比多線程,協程間的切換代價更小,我們提倡使用異步IO而非多線程。異步IO的模塊主要是:aysncio, aiohttp, aiomysql 等。
(2)網頁爬下來后從中提取想要的數據是CPU密集型的,這時候可以用多進程并發提取。
(3)我們推薦的爬蟲策略是,爬蟲只管爬,把爬下來的html保存起來,存到數據庫。然后單獨寫提取數據的提取器,單獨運行提取器。好處是,提取不影響爬取,爬的效率更高,并且提取程序可以隨時修改,有新的提取需求時不需要重新抓取。比如,最初寫爬蟲時只想提取網頁中的兩項數據,運行一段時間后,發現另外3項數據也很有用,如果保存了html,只需改改提取器重新跑一遍就好了。
第三個問題、如果想要保留加粗或者圖片原始位置,只能通過挖掘規律再寫正則表達式來針對性處理嗎?
網頁數據提取主要兩種方法:正則表達式,xpath。通過xpath可以獲得某個html標簽節點。比如,一篇blog網頁,它的主體內容都在某個標簽里面,可能是某個div。用xpath得到這個div,轉換為html,就是包含了格式及其圖片的部分,你保存這段html代碼而非純文本就好了。
第四個問題、爬蟲的增量爬取、斷點續爬、去重等
(1)通過網址池的概念去管理所有的URL
(2)增量爬取就是不重復下載已經下載過的,讓網址池記住那些已經下載過的URL;
(3)斷點續爬,就是上次還沒有爬取的URL這次接著爬,還是讓網址池記住那些還沒被爬取的URL
(4)爬蟲的去重,讓網址池記錄URL的狀態以避免重復爬取。
第五個問題、爬蟲的部署問題,在公司是不是分布式爬蟲系統比較多會涉及部署問題
爬蟲的部署,不一定是分布式的。大規模的爬蟲,突破了目標網站限制的爬蟲才會涉及到分布式,分布式的好處是抓取速度提高,但是管理會比較復雜。
第六個問題、網頁的自動解析?這個話題就包含很多子任務了: 怎么自動抽取文章的內容,如何處理各種各樣的時間格式,怎樣處理翻頁
(1)文章內容的提取,基本的是每種網頁建立一個提取模板(正則表達式),好處是提取精準,壞處是工作量大,一旦稍微改版就失敗。通過算法建立單一提取程序,基本上都可以提取,但是可能會有寫雜質,比如文末的相關閱讀。好處是,一勞永逸,不受改版限制。
(2)時間的提取,除了正則表達式之外似乎沒有特別有效的方法。
(3)翻頁的話,如果只是抓取,把該頁的url提取出來繼續抓;如何在提取內容時要把多頁內容合并成一個網頁,那就要特別處理。
第七個問題、爬新聞類的網站時,如何做好同一新聞,各網站相互轉載,爬取時文本去重
比較著名的算法是,Google的simhash,但具體實踐中比較復雜。網傳百度的做法是把文章的最長一句話(或多句)做hash,這個hash值就是文章的唯一性代表(指紋),這個方法準確率很高,但是召回率比較低,一旦這最長的幾句話改一個字就不能召回;我改進了該方法,對n句最長的話分別做hash,一個文章由n個指紋(如圖人的是個指頭指紋都不一樣)確定唯一性。準確率和召回率都還不錯。
第八個問題、異步爬蟲的設計
(1)一個好的URL管理策略,見猿人學上的網址池相關文章;
網址池是一個“生產者-消費者”模型,爬蟲從中取出url去下載,下載的html中提取新的url放入池中,告訴url池剛才拿出的url是否下載成功;再從池中取出url進行下載。。。url池是核心部件,它記錄url的不同狀態:
(a)下載成功
(b)下載失敗n次
(c)正在下載
每次往池子添加url時都要檢查url在池中的狀態,避免重復下載。