要想做反爬蟲,我們首先需要知道如何寫個(gè)簡單的爬蟲。
通常編寫爬蟲需要經(jīng)過這么幾個(gè)過程:
• 分析頁面請求格式
• 創(chuàng)建合適的http請求
• 批量發(fā)送http請求,獲取數(shù)據(jù)
舉個(gè)例子,直接查看攜程生產(chǎn)url。在詳情頁點(diǎn)擊“確定”按鈕,會(huì)加載價(jià)格。假設(shè)價(jià)格是你想要的,那么抓出網(wǎng)絡(luò)請求之后,哪個(gè)請求才是你想要的結(jié)果呢? 你只需要用根據(jù)網(wǎng)絡(luò)傳輸數(shù)據(jù)量進(jìn)行倒序排列即可。因?yàn)槠渌拿曰笮缘膗rl再多再復(fù)雜,開發(fā)人員也不會(huì)舍得加數(shù)據(jù)量給他。
代碼:
import requests
def download_page(url):
headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36'
}
data = requests.get(url,headers=headers)
return data
if __name__ == '__main__':
url = 'https://m.ctrip.com/restapi/soa2/21881/json/HotelSearch?testab=5b9a651b08c1069815c5af78f8b2bf6df9dd42a6129be5784bb096315494619a'
download_page(url)
高級(jí)爬蟲
那么爬蟲進(jìn)階應(yīng)該如何做呢?通常所謂的進(jìn)階有以下幾種:
分布式爬蟲
Python默認(rèn)情況下,我們使用scrapy框架進(jìn)行爬蟲時(shí)使用的是單機(jī)爬蟲,就是說它只能在一臺(tái)電腦上運(yùn)行,因?yàn)榕老x調(diào)度器當(dāng)中的隊(duì)列queue去重和set集合都只能在本機(jī)上創(chuàng)建的,其他電腦無法訪問另外一臺(tái)電腦上的內(nèi)存和內(nèi)容。
分布式爬蟲實(shí)現(xiàn)了多臺(tái)電腦使用一個(gè)共同的爬蟲程序,它可以同時(shí)將爬蟲任務(wù)部署到多臺(tái)電腦上運(yùn)行,這樣可以提高爬蟲速度,實(shí)現(xiàn)分布式爬蟲。
首先就需要配置安裝redis和scrapy-redis,而scrapy-redis是一個(gè)基于redis數(shù)據(jù)庫的scrapy組件,它提供了四種組件,通過它,可以快速實(shí)現(xiàn)簡單分布式爬蟲程序。
四種scrapy-redis組件:
Scheduler(調(diào)度):Scrapy改造了python本來的collection.deque(雙向隊(duì)列)形成了自己Scrapy queue,而scrapy-redis 的解決是把這個(gè)Scrapy queue換成redis數(shù)據(jù)庫,從同一個(gè)redis-server存放要爬取的request,便能讓多個(gè)spider去同一個(gè)數(shù)據(jù)庫里讀取。Scheduler負(fù)責(zé)對新的request進(jìn)行入列操作(加入Scrapy queue),取出下一個(gè)要爬取的request(從Scrapy queue中取出)等操作。
Duplication Filter(去重):Scrapy中用集合實(shí)現(xiàn)這個(gè)request去重功能,Scrapy中把已經(jīng)發(fā)送的request指紋放入到一個(gè)集合中,把下一個(gè)request的指紋拿到集合中比對,如果該指紋存在于集合中,說明這個(gè)request發(fā)送過了,如果沒有則繼續(xù)操作。
Item Pipline(管道):引擎將(Spider返回的)爬取到的Item給Item Pipeline,scrapy-redis 的Item Pipeline將爬取到的 Item 存?redis的 items queue
Base Spider(爬蟲):不再使用scrapy原有的Spider類,重寫的RedisSpider繼承了Spider和RedisMixin這兩個(gè)類,RedisMixin是用來從redis讀取url的類。
工作原理:
1、首先Slaver端從Master端拿任務(wù)(Request、url)進(jìn)行數(shù)據(jù)抓取,Slaver抓取數(shù)據(jù)的同時(shí),產(chǎn)生新任務(wù)的Request便提交給 Master 處理;
2、Master端只有一個(gè)Redis數(shù)據(jù)庫,負(fù)責(zé)將未處理的Request去重和任務(wù)分配,將處理后的Request加入待爬隊(duì)列,并且存儲(chǔ)爬取的數(shù)據(jù)。
模擬JavaScript
模擬javascript,抓取動(dòng)態(tài)網(wǎng)頁,是進(jìn)階技巧。但是其實(shí)這只是個(gè)很簡單的功能。因?yàn)椋绻麑Ψ經(jīng)]有反爬蟲,你完全可以直接抓ajax本身,而無需關(guān)心js怎么處理的。如果對方有反爬蟲,那么javascript必然十分復(fù)雜,重點(diǎn)在于分析,而不僅僅是簡單的模擬。
PhantomJs或者selenium
以上的用來做自動(dòng)測試的,結(jié)果因?yàn)樾Ч芎茫芏嗳四脕碜雠老x。但是這個(gè)東西有個(gè)硬傷,就是:效率。占用資源比較多,但是爬取效果很好。
總結(jié):越是低級(jí)的爬蟲,越容易被封鎖,但是性能好,成本低。越是高級(jí)的爬蟲,越難被封鎖,但是性能低,成本也越高。
當(dāng)成本高到一定程度,我們就可以無需再對爬蟲進(jìn)行封鎖。經(jīng)濟(jì)學(xué)上有個(gè)詞叫邊際效應(yīng)。付出成本高到一定程度,收益就不是很多了。