天天看點

關于Scrapy crawlspider rules的規則——翻頁

最近在學習爬蟲,對于crawlspider rules的運作機制有點疑問,于是自己研究了一下,總結出以下幾點:

1、rules裡的Rule規則運作是有順序的,按照由上往下執行;

2、request url的擷取是Rule定位到的容器裡,所有a标簽裡的href連結,比如用xpath定位

rules = (

        Rule(LinkExtractor(restrict_xpaths=("//div/ul")),callback='parse_item'),

    )

則在ul容器下的所有a标簽的連結全都會被擷取到,并且侍自動發送請求,不用自己手動發送請求;

3、響應頁面是Rule請求的連結的頁面内容,也就是你定位容器ul裡的a标簽的連結,然後你用滑鼠點選該連結所看到的頁面内容,在callback函數裡提取資料也是在這個頁面裡提取,parse_item(self,response),這個函數的response對象就是這個頁面内容,千萬不要搞錯對象了;

4、follow,這個參數開始把我搞得有點暈,follow就是跟進的意思,如果follow=True,那麼,在你擷取到的響應頁面裡,是以符合Rule規則的href連結都會被擷取到,而且它還會自動跟進,進入到擷取到的連結響應頁面,在該頁面又一次比對Rule規則,看看有沒有符合的,如果有又繼續跟進,一直到比對不到規則為止。舉個例子:

rules = (

        Rule(LinkExtractor(restrict_xpaths=("//div/ul")),follow=True),

    )

那麼首先,該規則會擷取目前頁面符合Rule規則的所有a連結,目前頁面就是start_urls頁面,比如擷取到的連結為

<a class='dd_first ' href="http://book.dangdang.com/textbook?biaoti" target="_blank" rel="external nofollow" target="_blank" title="教材"    nname="book-65152-9163_1-468598_2"  ddt-src="http://book.dangdang.com/textbook?biaoti">教材</a>

它會繼續進入這個href連結的頁面,然後繼續再比對Rule規則,看看還有沒有符合的連結,就相當于你在響應頁面的elements裡面查找到符合規則的a标簽url之後,再點選這個url,再在這個頁面的elements裡查找還有沒有符合Rule規則的href連結,如此循環,直到找不到符合Rule規則為止;

5、如果Rule規則裡有callback="parse_item",follow=True,那麼情況就會比較複雜,你可以想像擷取到一個響應頁面符合Rule規則的連結,然後調用函數,在這個頁面再去follow其它的目标連結,再調用函數,用xpath定位會相對好一點,如果用allow=(r'')正規表達式比對,會相對混亂點,适當的情況下也會這樣子用,但是比較少吧,可以自己測試體驗一下。

6、翻頁,翻頁有兩種情況

第一種情況(start_url的響應頁面下方有翻頁連結):

在rules裡定義兩條Rule規則,一條是擷取響應頁面規則,一條是擷取翻頁連結規則,翻頁的規則跟在擷取響應頁面規則下面,順序不要搞錯了,如下:

  rules = (

        Rule(LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm'), callback='parse_item'),

        Rule(LinkExtractor(allow=r'http://bxjg.circ.gov.cn/web/site0/tab5240/module14430/page\d\.htm'),follow=True),

    )

第二種情況(start_url的響應頁面下方沒有翻頁連結,要進入a 标簽連結才有翻頁連結):

這種情況下,就不能在rules定義翻頁規則了,因為即使定義了翻頁規則,也找不到,因為rules裡面的所有規則,第一次擷取響應頁面都是對應start_url位址的内容,在這個頁面上沒有符合Rule規則的,就找不到了,這裡我也不多說了,直接去源碼吧!

class TestSpider(CrawlSpider):
    name = 'test'
    allowed_domains = ['dangdang.com']
    start_urls = ['http://book.dangdang.com/']
    rules = (
        Rule(LinkExtractor(restrict_xpaths=("//div[@class='conflq_body']/div[@name='m403752_pid5438_t10274']//div/dl[@ddt-area='5358']/dd")), callback='parse_item'),

    )

    def parse_item(self, response):
        item={}
        item['cate_0']=''
        item['cate_1'] = ''
        item['cate_2'] = ''
        item['cate_3'] = ''
        breadcrum=response.xpath("//div[@class='crumbs_fb_left']/div[@class='select_frame']/a[@name='breadcrumb-category']/text()").getall()
        for i in range(len(breadcrum)):
            item['cate_{}'.format(i)]=breadcrum[i]
        book_li=response.xpath("//div[@id='search_nature_rg']/ul/li")
        for li in book_li:
            item['book_title']=li.xpath(".//p[@class='name']/a/@title").get()
            item['book_price']=li.xpath(".//p[@class='price']/span/text()").get()
            item['book_url']=li.xpath(".//p[@class='name']/a/@href").get()
            book_search=li.xpath(".//p[@class='search_book_author']/span")
            item['book_author']=book_search[0].xpath(".//a/@title").get()
            item['public_date']=book_search[1].xpath(".//text()").get()
            item['public_date']=re.sub("/",'',item['public_date']) if item['public_date'] else None
            item['public_company']=book_search[2].xpath(".//a/@title").get()

            yield item

        next_page_url=response.xpath("//div[@class='paging']//li[@class='next']/a/@href").get()
        next_page="http://category.dangdang.com"+next_page_url
        yield scrapy.Request(next_page,callback=self.parse_item)
           

這種情況下的翻頁要在函數裡面進行,在parse_item()函數的最後三行,是翻頁語句!自己可以測試一下,我也不知道rules規則能不能有其它方法可以做到,反正我現在沒發現,如果有朋友知道的可以告訴一下!

以上是我自己的個人觀點,如有錯漏煩請指出!