你的爬蟲被后臺(tái)檢測(cè)到了御板?這么做才能隱藏爬蟲

前言

我們?cè)趯懸粋€(gè)簡(jiǎn)單的爬蟲時(shí),爬蟲代碼很容易就會(huì)被后臺(tái)檢測(cè)到進(jìn)而封掉牛郑。那么怎么樣才能避免這些事發(fā)生呢怠肋?這一這篇文章我們一起來學(xué)習(xí),如何健壯我們的爬蟲代碼淹朋。


目錄

Spider

Middleware

瞎比比

Spider

當(dāng) start_urls 未被指定笙各,會(huì)調(diào)用 start_requests() ,該方法可以用于在爬取數(shù)據(jù)之前,先進(jìn)行模擬登陸础芍。

import scrapy

from scrapy.http import Request

from scrapy.selector import Selector

from urllib.parse import urljoin

from doubanTop250.items import Doubantop250Item

class DoubanTop250Spider(scrapy.spiders.Spider):

# 此處為上面留下的小坑

name = "douban"

# 設(shè)置允許爬取的域名

allowed_domains = ["douban.com"]

# header信息

my_header = {

'Host': 'www.douban.com',

'Referer': 'https://movie.douban.com',

}

# 表單需要提交的數(shù)據(jù)

form_data = {'user': 'zone', 'pass': 'zone7'}

# 自定義信息杈抢,向下層響應(yīng)(response)傳遞下去

customer_data = {'key1': 'value1', 'key2': 'value2'}

def start_requests(self):

return [scrapy.FormRequest("https://movie.douban.com/login",

formdata=self.form_data, # 表單提交的數(shù)據(jù)

headers=self.my_header,

method='POST', # GET or POST

meta=self.customer_data, # 自定義,向response傳遞數(shù)據(jù)

errback=self.error_handle,

callback=self.logged_in,

# 如果需要多次提交表單仑性,且url一樣惶楼,那么就必須加此參數(shù) dont_filter,防止被當(dāng)成重復(fù)網(wǎng)頁過濾掉了

dont_filter=True

)]

def logged_in(self, response):

# 解析模擬登陸數(shù)據(jù)

pass

def parse(self, response):

# 默認(rèn)回調(diào)函數(shù)

pass

def close(self,reson):

# 關(guān)閉時(shí)調(diào)用

pass

scrapy.FormRequest 部分參數(shù)解析

parse(self, response)

當(dāng) start_requests 沒有指定回調(diào)函數(shù)時(shí)诊杆,默認(rèn)回調(diào) parse(self,response) 方法歼捐。parse 負(fù)責(zé)處理 response 并返回處理的數(shù)據(jù)以及(/或)跟進(jìn)的 URL。

該方法及其他的 Request 回調(diào)函數(shù)必須返回一個(gè)包含 Request晨汹、dict 或 Item 的可迭代的對(duì)象豹储。簡(jiǎn)單的來說,所謂的回調(diào)函數(shù)淘这,其實(shí)就是告訴spider剥扣,在拿到了網(wǎng)站的 response 以后,交給誰來進(jìn)行處理后面的頁面的解析工作铝穷。這個(gè)看上一篇文章的代碼就可以知道朦乏。

Middleware

這里說一下,關(guān)于自定義 middleware 需要重寫的幾個(gè)方法氧骤,可能你看完這一段長(zhǎng)篇大論之后呻疹,還是懵逼的,沒關(guān)系,我也是這樣刽锤。不過镊尺,當(dāng)你繼續(xù)往下看,看一個(gè)實(shí)例之后并思,你就會(huì)明白庐氮。

process_request(request, spider)

當(dāng)每個(gè)request通過下載中間件時(shí),該方法被調(diào)用宋彼。

process_request() 必須返回其中之一: 返回 None 弄砍、返回一個(gè) Response 對(duì)象、返回一個(gè) Request 對(duì)象或 raise IgnoreRequest 输涕。

如果其返回 None 音婶,Scrapy將繼續(xù)處理該request,執(zhí)行其他的中間件的相應(yīng)方法莱坎,直到合適的下載器處理函數(shù)(download handler)被調(diào)用衣式, 該request被執(zhí)行(其response被下載)。

如果其返回 Response 對(duì)象檐什,Scrapy將不會(huì)調(diào)用 任何 其他的 process_request() 或 process_exception() 方法碴卧,或相應(yīng)地下載函數(shù); 其將返回該 response乃正。 已安裝的中間件的 process_response() 方法則會(huì)在每個(gè) response 返回時(shí)被調(diào)用住册。

如果其返回 Request 對(duì)象,Scrapy則停止調(diào)用 process_request方法并重新調(diào)度返回的 request瓮具。當(dāng)新返回的 request 被執(zhí)行后荧飞, 相應(yīng)地中間件鏈將會(huì)根據(jù)下載的 response 被調(diào)用。

如果其 raise 一個(gè) IgnoreRequest 異常搭综,則安裝的下載中間件的 process_exception() 方法會(huì)被調(diào)用。如果沒有任何一個(gè)方法處理該異常划栓, 則 request 的errback(Request.errback) 方法會(huì)被調(diào)用兑巾。如果沒有代碼處理拋出的異常, 則該異常被忽略且不記錄(不同于其他異常那樣)忠荞。

參數(shù):

request(Request 對(duì)象)–處理的 request

spider(Spider 對(duì)象)–該 request 對(duì)應(yīng)的 spider

process_response(request, response, spider)

process_request() 必須返回以下之一: 返回一個(gè) Response 對(duì)象蒋歌、 返回一個(gè) Request 對(duì)象或 raise 一個(gè) IgnoreRequest 異常。

如果其返回一個(gè) Response (可以與傳入的response相同委煤,也可以是全新的對(duì)象)堂油, 該response會(huì)被在鏈中的其他中間件的 process_response() 方法處理。

如果其返回一個(gè) Request 對(duì)象碧绞,則中間件鏈停止府框, 返回的request會(huì)被重新調(diào)度下載。處理類似于 process_request() 返回request所做的那樣讥邻。

如果其拋出一個(gè) IgnoreRequest 異常迫靖,則調(diào)用 request 的 errback( Request.errback)院峡。 如果沒有代碼處理拋出的異常,則該異常被忽略且不記錄(不同于其他異常那樣)系宜。

參數(shù):

request (Request 對(duì)象) – response 所對(duì)應(yīng)的 request

response (Response 對(duì)象) – 被處理的 response

spider (Spider 對(duì)象) – response 所對(duì)應(yīng)的 spider

process_exception(request, exception, spider)

當(dāng)下載處理器(download handler)或 process_request() (下載中間件)拋出異常(包括IgnoreRequest異常)時(shí)照激,Scrapy調(diào)用 process_exception() 。

process_exception() 應(yīng)該返回以下之一: 返回 None 盹牧、 一個(gè) Response 對(duì)象俩垃、或者一個(gè) Request 對(duì)象。

如果其返回 None 汰寓,Scrapy將會(huì)繼續(xù)處理該異常口柳,接著調(diào)用已安裝的其他中間件的 process_exception() 方法,直到所有中間件都被調(diào)用完畢踩寇,則調(diào)用默認(rèn)的異常處理啄清。

如果其返回一個(gè) Response 對(duì)象,則已安裝的中間件鏈的 process_response() 方法被調(diào)用俺孙。Scrapy將不會(huì)調(diào)用任何其他中間件的 process_exception() 方法辣卒。

如果其返回一個(gè) Request 對(duì)象, 則返回的request將會(huì)被重新調(diào)用下載睛榄。這將停止中間件的 process_exception() 方法執(zhí)行荣茫,就如返回一個(gè)response的那樣。

參數(shù):

request (是 Request 對(duì)象) – 產(chǎn)生異常的request

exception (Exception 對(duì)象) – 拋出的異常

spider (Spider 對(duì)象) – request對(duì)應(yīng)的spider

UserAgentMiddleware

多數(shù)情況下场靴,網(wǎng)站都會(huì)通過 user-agent 來識(shí)別訪問的用戶是否為一臺(tái)機(jī)器啡莉,就像爬取豆瓣一樣,如果你沒有設(shè)置 user-agent 的話旨剥,就會(huì)被拒絕訪問咧欣。因此,我們只使用一個(gè) user-agent 顯然是不夠的轨帜,因此魄咕,我們要想個(gè)辦法來設(shè)置隨機(jī)的 user-agent。于是蚌父,我們便可以自定義 UserAgentMiddleware 來解決這個(gè)問題哮兰。

首先,在 setting.py 中添加 user-agent 苟弛,如下:

MY_USER_AGENT = [

'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',

'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)',

'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)',

'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)',

'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)',

'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6',

'Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5',

'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',

'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',

'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',

'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',

'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',

'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',

'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)',

'Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)',

'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20',

'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6',

'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',

'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',

'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1',

'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)',

'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12',

'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)',

'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1',

'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)'

]

然后在 middlewares.py 中添加如下代碼:

class MyUserAgentMiddleware(UserAgentMiddleware):

def __init__(self, user_agent):

self.user_agent = user_agent

@classmethod

def from_crawler(cls, crawler):

return cls(

user_agent=crawler.settings.get('MY_USER_AGENT')

)

def process_request(self, request, spider):

agent = random.choice(self.user_agent)

request.headers['User-Agent'] = agent

最后啟用這個(gè) middleware 喝滞,在 setting.py 中修改 MyUserAgentMiddleware 的優(yōu)先級(jí),如下:

DOWNLOADER_MIDDLEWARES = {

# 首先禁止其原有的 UserAgentMiddleware

'scrapy.downloadermiddleware.useragent.UserAgentMiddleware': None,

'doubanTop250.middlewares.MyUserAgentMiddleware': 300,

'doubanTop250.middlewares.ProxyMiddleware': 543,

}

ProxyMiddleware

除了要更改 user-agent 之外膏秫,我們還要使用 ip 代理來健壯我們的爬蟲程序右遭。那么,在 scrapy 中如何來設(shè)置我們的 ip 代理呢?

首先狸演,在 setting.py 中添加如下代碼言蛇,為代理 ip:

PROXIES = [

"194.186.20.62:21231"

, "66.153.222.162:54684"

, "219.234.5.128:3128"

, "117.114.149.66:53281"

, "117.114.149.66:53281"

]

ip 來自西刺代理,不過好像好多沒用的代理宵距。

然后在 middlewares.py 中添加如下代碼:

from scrapy import signals

import random

class ProxyMiddleware(object):

def __init__(self, ip):

self.ip = ip

@classmethod

def from_crawler(cls, crawler):

return cls(ip=crawler.settings.get('PROXIES'))

def process_request(self, request, spider):

ip = random.choice(self.ip)

request.meta['proxy'] = ip

最后啟用這個(gè) middleware 腊尚,在 setting.py 中修改 ProxyMiddleware 的優(yōu)先級(jí),如下:

DOWNLOADER_MIDDLEWARES = {

# 首先禁止其原有的 UserAgentMiddleware

'scrapy.downloadermiddleware.useragent.UserAgentMiddleware': None,

'doubanTop250.middlewares.MyUserAgentMiddleware': 300,

'doubanTop250.middlewares.ProxyMiddleware': 543,

}

瞎比比

經(jīng)過這些操作之后满哪,你的代碼等級(jí)就提升了一個(gè)高度了婿斥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市哨鸭,隨后出現(xiàn)的幾起案子民宿,更是在濱河造成了極大的恐慌,老刑警劉巖像鸡,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件活鹰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡只估,警方通過查閱死者的電腦和手機(jī)志群,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蛔钙,“玉大人锌云,你說我怎么就攤上這事∮跬眩” “怎么了桑涎?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)兼贡。 經(jīng)常有香客問我攻冷,道長(zhǎng),這世上最難降的妖魔是什么遍希? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任等曼,我火速辦了婚禮,結(jié)果婚禮上孵班,老公的妹妹穿的比我還像新娘涉兽。我一直安慰自己招驴,他們只是感情好篙程,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著别厘,像睡著了一般虱饿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天氮发,我揣著相機(jī)與錄音渴肉,去河邊找鬼。 笑死爽冕,一個(gè)胖子當(dāng)著我的面吹牛仇祭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播颈畸,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼乌奇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了眯娱?” 一聲冷哼從身側(cè)響起礁苗,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徙缴,沒想到半個(gè)月后试伙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡于样,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年疏叨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片百宇。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡考廉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出携御,到底是詐尸還是另有隱情昌粤,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布啄刹,位于F島的核電站涮坐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏誓军。R本人自食惡果不足惜袱讹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昵时。 院中可真熱鬧捷雕,春花似錦、人聲如沸壹甥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽句柠。三九已至浦译,卻和暖如春棒假,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背精盅。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國打工帽哑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叹俏。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓妻枕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親粘驰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子佳头,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容