CrawlSpider的使用

CrawlSpider是爬取那些具有一定規(guī)則網(wǎng)站的常用的爬蟲(chóng)胖眷,它基于Spider并有一些獨(dú)特屬性

  • rules: 是Rule對(duì)象的集合尊惰,用于匹配目標(biāo)網(wǎng)站并排除干擾
  • parse_start_url: 用于爬取起始響應(yīng)臂拓,必須要返回Item蝇率,Request中的一個(gè)著蛙。

rules是Rule對(duì)象的集合

  • rules的參數(shù)

link_extractor, : linkExtractor對(duì)象
callback=None, : 設(shè)置回調(diào)函數(shù)
follow=None, : 設(shè)置是否跟進(jìn)
process_links=None, :可以設(shè)置回調(diào)函數(shù)泌枪,對(duì)所有提取到的url進(jìn)行攔截
process_request=identity : 可以設(shè)置回調(diào)函數(shù),對(duì)request對(duì)象進(jìn)行攔截

其中的link_extractor既可以自己定義螺戳,也可以使用已有LinkExtractor類(lèi)搁宾,主要參數(shù)為:

*   allow:滿(mǎn)足括號(hào)中“正則表達(dá)式”的值會(huì)被提取,如果為空倔幼,則全部匹配盖腿。
*   deny:與這個(gè)正則表達(dá)式(或正則表達(dá)式列表)不匹配的URL一定不提取。
*   allow_domains:會(huì)被提取的鏈接的domains。
*   deny_domains:一定不會(huì)被提取鏈接的domains翩腐。
*   **restrict_xpaths**:使用**xpath**表達(dá)式鸟款,和**allow**共同作用過(guò)濾鏈接。還有一個(gè)類(lèi)似的restrict_css

以Chinaz為例:

# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from china.items import ChinazprojectWebInfoItem

class ChinazSpider(CrawlSpider):
    # 爬蟲(chóng)名稱(chēng)
    name = 'chinaz'
    # 允許爬去的域
    allowed_domains = ['chinaz.com']
    # 起始url地址
    start_urls = ['http://top.chinaz.com/hangyemap.html']
    # 存放定制的獲取鏈接的規(guī)則對(duì)象(可以是一個(gè)列表也可以是元組)
    # 根據(jù)規(guī)則提取到的所有鏈接茂卦,會(huì)由crawlspider構(gòu)建request對(duì)象欠雌,并交給引擎處理
    '''
        LinkExtractor : 設(shè)置提取鏈接的規(guī)則(正則表達(dá)式)
        allow=(), : 設(shè)置允許提取的url
        restrict_xpaths=(), :根據(jù)xpath語(yǔ)法,定位到某一標(biāo)簽下提取鏈接
        restrict_css=(), :根據(jù)css選擇器疙筹,定位到某一標(biāo)簽下提取鏈接
        deny=(), : 設(shè)置不允許提取的url(優(yōu)先級(jí)比allow高)
        allow_domains=(), : 設(shè)置允許提取url的域
        deny_domains=(), :設(shè)置不允許提取url的域(優(yōu)先級(jí)比allow_domains高)
        unique=True, :如果出現(xiàn)多個(gè)相同的url只會(huì)保留一個(gè)
        strip=True :默認(rèn)為T(mén)rue,表示自動(dòng)去除url首尾的空格
    '''
    '''
    rule
        link_extractor, : linkExtractor對(duì)象
        callback=None,  : 設(shè)置回調(diào)函數(shù)  
        follow=None, : 設(shè)置是否跟進(jìn)
        process_links=None, :可以設(shè)置回調(diào)函數(shù),對(duì)所有提取到的url進(jìn)行攔截
        process_request=identity : 可以設(shè)置回調(diào)函數(shù)禁炒,對(duì)request對(duì)象進(jìn)行攔截
    '''
    rules = (
        # 規(guī)則對(duì)象'<a 
        Rule(LinkExtractor(allow=r'http://top.chinaz.com/hangye/index_.*?html',
                           restrict_xpaths='//div[@class="Taright"]'),
             callback='parse_item',
             follow=True),
    )
    # 注意: CrawlSpider中一定不要出現(xiàn)parse回調(diào)方法
    def parse_item(self, response):
        print(response.status, response.url)
        '''
        解析分頁(yè)的網(wǎng)站數(shù)據(jù)而咆,提取后交給item處理
        '''
        webInfos = response.xpath('//ul[@class="listCentent"]/li')
        for webInfo in webInfos:
            web_item = ChinazprojectWebInfoItem()
            # 封面圖片
            web_item['coverImage'] = webInfo.xpath('.//div[@class="leftImg"]/a/img/@src').extract_first('')
            # 標(biāo)題
            web_item['title'] = webInfo.xpath('.//h3[@class="rightTxtHead"]/a/text()').extract_first('')
            # 域名
            web_item['domenis'] = webInfo.xpath('.//h3[@class="rightTxtHead"]/span[@class="col-gray"]/text()').extract_first('')
            # 周排名
            web_item['weekRank'] = webInfo.xpath('.//div[@class="RtCPart clearfix"]/p[1]/a/text()').extract_first('')
            # 反連接數(shù)
            web_item['ulink'] = webInfo.xpath('.//div[@class="RtCPart clearfix"]/p[4]/a/text()').extract_first('')
            # 網(wǎng)站簡(jiǎn)介
            web_item['info'] = webInfo.xpath('.//p[@class="RtCInfo"]/text()').extract_first('')
            # 得分
            web_item['score'] = webInfo.xpath('.//div[@class="RtCRateCent"]/span/text()').re('\d+')[0]
            # 排名
            web_item['rank'] = webInfo.xpath('.//div[@class="RtCRateCent"]/strong/text()').extract_first('')
            print(web_item)
            yield web_item

CrawlSpider如何工作的?

因?yàn)镃rawlSpider繼承了Spider幕袱,所以具有Spider的所有函數(shù)暴备。
首先由start_requests對(duì)start_urls中的每一個(gè)url發(fā)起請(qǐng)求(make_requests_from_url),這個(gè)請(qǐng)求會(huì)被parse接收们豌。在Spider里面的parse需要我們定義涯捻,但CrawlSpider定義parse去解析響應(yīng)(self._parse_response(response, self.parse_start_url, cb_kwargs={}, follow=True)
_parse_response根據(jù)有無(wú)callback,followself.follow_links執(zhí)行不同的操作

eg:

    def _parse_response(self, response, callback, cb_kwargs, follow=True):
    ##如果傳入了callback,使用這個(gè)callback解析頁(yè)面并獲取解析得到的reques或item
        if callback:
            cb_res = callback(response, **cb_kwargs) or ()
            cb_res = self.process_results(response, cb_res)
            for requests_or_item in iterate_spider_output(cb_res):
                yield requests_or_item
    ## 其次判斷有無(wú)follow望迎,用_requests_to_follow解析響應(yīng)是否有符合要求的link障癌。
        if follow and self._follow_links:
            for request_or_item in self._requests_to_follow(response):
                yield request_or_item

其中_requests_to_follow又會(huì)獲取link_extractor(這個(gè)是我們傳入的LinkExtractor)解析頁(yè)面得到的link(link_extractor.extract_links(response)),對(duì)url進(jìn)行加工(process_links,需要自定義)辩尊,對(duì)符合的link發(fā)起Request涛浙。使用.process_request(需要自定義)處理響應(yīng)。

CrawlSpider如何獲取rules摄欲?

CrawlSpider類(lèi)會(huì)在__init__方法中調(diào)用_compile_rules方法轿亮,然后在其中淺拷貝rules中的各個(gè)Rule獲取要用于回調(diào)(callback),要進(jìn)行處理的鏈接(process_links)和要進(jìn)行的處理請(qǐng)求(process_request)

eg:

    def _compile_rules(self):
        def get_method(method):
            if callable(method):
                return method
            elif isinstance(method, six.string_types):
                return getattr(self, method, None)

        self._rules = [copy.copy(r) for r in self.rules]
        for rule in self._rules:
            rule.callback = get_method(rule.callback)
            rule.process_links = get_method(rule.process_links)
            rule.process_request = get_method(rule.process_request)

Rule是怎么樣定義的

    class Rule(object):

        def __init__(self, link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=identity):
            self.link_extractor = link_extractor
            self.callback = callback
            self.cb_kwargs = cb_kwargs or {}
            self.process_links = process_links
            self.process_request = process_request
            if follow is None:
                self.follow = False if callback else True
            else:
                self.follow = follow

因此LinkExtractor會(huì)傳給link_extractor胸墙。

有callback的是由指定的函數(shù)處理我注,如果沒(méi)有callback的由哪個(gè)函數(shù)處理?

`_parse_response`會(huì)處理有`callback`的(響應(yīng))respons迟隅。
cb_res = callback(response, **cb_kwargs) or ()
而`_requests_to_follow`會(huì)將`self._response_downloaded`傳給`callback`用于對(duì)頁(yè)面中匹配的url發(fā)起請(qǐng)求(request)但骨。
r = Request(url=link.url, callback=self._response_downloaded)

如何在CrawlSpider進(jìn)行模擬登陸

CrawlSpider和Spider一樣,都要使用start_requests發(fā)起請(qǐng)求

以知乎為例:

##替換原來(lái)的start_requests玻淑,callback為
def start_requests(self):
    return [Request("http://www.zhihu.com/#signin", meta = {'cookiejar' : 1}, callback = self.post_login)]
def post_login(self, response):
    print 'Preparing login'
    #下面這句話用于抓取請(qǐng)求網(wǎng)頁(yè)后返回網(wǎng)頁(yè)中的_xsrf字段的文字, 用于成功提交表單
    xsrf = Selector(response).xpath('//input[@name="_xsrf"]/@value').extract()[0]
    print xsrf
    #FormRequeset.from_response是Scrapy提供的一個(gè)函數(shù), 用于post表單
    #登陸成功后, 會(huì)調(diào)用after_login回調(diào)函數(shù)
    return [FormRequest.from_response(response,   #"http://www.zhihu.com/login",
                        meta = {'cookiejar' : response.meta['cookiejar']},
                        headers = self.headers,
                        formdata = {
                        '_xsrf': xsrf,
                        'email': 'z1996914@outlook.com',
                        'password': '********'
                        },
                        callback = self.after_login,
                        dont_filter = True
                        )]
#make_requests_from_url會(huì)調(diào)用parse嗽冒,就可以與CrawlSpider的parse進(jìn)行銜接了
def after_login(self, response) :
    for url in self.start_urls :
        yield self.make_requests_from_url(url)

僅為個(gè)人學(xué)習(xí)小結(jié),若有錯(cuò)處补履,歡迎指正~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末添坊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子箫锤,更是在濱河造成了極大的恐慌贬蛙,老刑警劉巖雨女,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異阳准,居然都是意外死亡氛堕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)野蝇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)讼稚,“玉大人,你說(shuō)我怎么就攤上這事绕沈∪裣耄” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵乍狐,是天一觀的道長(zhǎng)赠摇。 經(jīng)常有香客問(wèn)我,道長(zhǎng)浅蚪,這世上最難降的妖魔是什么藕帜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮惜傲,結(jié)果婚禮上洽故,老公的妹妹穿的比我還像新娘。我一直安慰自己盗誊,他們只是感情好收津,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著浊伙,像睡著了一般撞秋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嚣鄙,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天吻贿,我揣著相機(jī)與錄音,去河邊找鬼哑子。 笑死舅列,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卧蜓。 我是一名探鬼主播帐要,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼弥奸!你這毒婦竟也來(lái)了榨惠?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赠橙,沒(méi)想到半個(gè)月后耽装,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡期揪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年掉奄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凤薛。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姓建,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缤苫,到底是詐尸還是另有隱情引瀑,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布榨馁,位于F島的核電站,受9級(jí)特大地震影響帜矾,放射性物質(zhì)發(fā)生泄漏翼虫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一屡萤、第九天 我趴在偏房一處隱蔽的房頂上張望珍剑。 院中可真熱鬧,春花似錦死陆、人聲如沸招拙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)别凤。三九已至,卻和暖如春领虹,著一層夾襖步出監(jiān)牢的瞬間规哪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工塌衰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诉稍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓最疆,卻偏偏與公主長(zhǎng)得像杯巨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子努酸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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