起因
有個朋友叫我幫忙寫個爬蟲,爬取javbus5上面所有的詳情頁鏈接,也就是所有的https://www.javbus5.com/SRS-055這種鏈接,
我一看,嘿呀,這是司機的活兒啊,我絕對不能辱沒我老司機的名聲(被敗壞了可不好),於是開始着手寫了
構思
- 爬蟲調度啟動程序crawler.py
- 頁面下載程序downloader.py
- 頁面解析程序pageparser.py
- 數據庫入庫與去重管理程序controler.py
爬取入口為第一頁,當頁面中存在下一頁的超鏈接繼續往下爬,這是個死循環,跳出條件為沒有了下一頁的鏈接
在某一頁中解析頁面,返回所有的詳情頁鏈接,利用迭代器返回,然后在主程序中調用解析程序對頁面信息進行解析並包裝成字典返回,其中用詳情頁網址作為數據庫主鍵,其他信息依次寫入數據庫
當這一頁所有的子鏈接爬取完成后,繼續爬取下一頁。
將數據存入數據庫,用的是sqllite3,失敗的網址頁存入一個fail_url.txt。
對於增量爬取,我是這么做的,當爬取到相同的網址時結束程序,這么做也有漏洞,才疏學淺,我沒想到太好的辦法,希望有好辦法的給我說一聲(布隆過濾正在研究之中),如果用數據庫查詢去重,那么勢必導致二次爬取,我們都知道,爬蟲更多的時間是花在網絡等待上
問題
在寫爬蟲的過程中遇到了一些問題
-
在牆內爬不動,爬取幾個之后就失敗,這個解決方案只需要全局翻牆爬取就可以了
-
本來之前加了多線程並發爬取,但是發現爬取一段時間后會封ip導致整體無法運行,本來想搞個代理池進行並發,結果網上免費的代理太慢太慢,根本打不開網頁,於是就改回了單線程
-
就是我的那個不完善的增量爬取,導致了你一次爬取就需要爬取完成,不然數據庫里面存在你之前爬到的,爬取到你已有的會直接停止
-
存在反扒策略
詳情頁中的磁力鏈接是ajax動態加載的,通過分析抓包,可以在XHR中找到是一個get請求,至於參數,我開始不知道怎么得來的,后來在html代碼中找到了,我放幾張圖大家就明白了
我們通過對響應內容的查看可以發現磁力的加載訪問了類似於這樣一個網址
https://www.javbus5.com/ajax/uncledatoolsbyajax.php?gid=30100637207&lang=zh&img=https://pics.javbus.info/cover/59pc_b.jpg&uc=0&floor=921
那么這些get參數是從哪里來呢,這就是通過經驗與基本功去發現了
通過對html源文件的搜索,我們即可直接發現答案
通過分析發現,后面的floor是個隨機數參數,一般這種參數可以去除無影響,事實也是這樣我利用HttpRequest模擬發包,對這個請求直接get,發現所有數據隱藏
那么肯定是有反扒的策略,偽造請求頭,反扒也就那么幾種,通過分析發現是同源策略,對Referer請求頭偽造成來源網址就可以直接獲取到內容了
-
常見的Python2.x編碼問題,全部轉換為unicode字節流就可以了
這個問題在我博客中已經記錄了http://www.53xiaoshuo.com/Python/77.html
有興趣的童鞋可以看看 -
遇到的最鬧心問題是詳情頁的項目抓取,有的詳情頁的類別不同,我開始只分析了一個頁面,導致寫的規則在有的頁面上頻頻出錯
導致后面對抓取規則進行了大改,重寫了分析規則,用了個笨辦法,畢竟那小塊的html寫的十分不規范,正則規則有三種,挺煩人
比如上圖的兩個就不同,html代碼更是稀爛,需要判斷有沒有這個項,沒有就設置空字節入庫在這其中糾結了一個問題
就是對於這兩種的比較,我想上面這種變成下面這種,畢竟第一種的話,soup.find要執行兩次,但是下面這種又要比上面那個多一行,丑一點
最后我選擇了第二種,所有的信息分析代碼就不貼了,具體想看的直接看我的代碼文件就好了
小Tips
-
對於動態加載的內容的爬取,能不用selenium去模擬瀏覽器爬取就不用,耗費資源,更好的是自己分析網絡請求,然后構造
-
對於頁面信息的解析,要多看幾個頁面,看是否相同,別到時候做多事情
-
多看別人的博客學習思路
注意
爬蟲依賴的第三方庫有Requests,BeautifulSoup,使用前請先pip install這兩個第三方庫
測試展與地址
代碼地址:
- coding.net javbus_crawler
- github.com javbus_crawler
司機的名聲總算是沒有辱沒,秋名山依舊,嘿嘿
轉載請注明來源作者
- 博客:akkuman.cnblogs.com | hacktech.cn
- 作者:Akkuman