1. 程式人生 > >Scrapy研究探索(六)——自動爬取網頁之II(CrawlSpider)

Scrapy研究探索(六)——自動爬取網頁之II(CrawlSpider)

.目的。

pipelines.py中實現獲得資料的過濾以及儲存。

但是以上述方法只能爬取start_url列表中的網頁,而網路爬蟲如google等搜尋引擎爬蟲實現的就是對整個網際網路的爬取,所以在本教程中研究使用scrapy自動實現多網頁爬取功能。

.熱身。

1.CrawlSpider

1)概念與作用:

它是Spider的派生類,首先在說下Spider,它是所有爬蟲的基類,對於它的設計原則是隻爬取start_url列表中的網頁,而從爬取的網頁中獲取link並繼續爬取的工作CrawlSpider類更適合。

2)使用

它與Spider類的最大不同是多了一個rules引數,其作用是定義提取動作。在

rules中包含一個或多個Rule物件,Rule類與CrawlSpider類都位於scrapy.contrib.spiders模組中。

class scrapy.contrib.spiders.Rule (
link_extractor, callback=None,cb_kwargs=None,follow=None,process_links=None,process_request=None )

                     其中:

link_extractorLinkExtractor,用於定義需要提取的連結。

callback引數:當link_extractor獲取到連結時引數所指定的值作為回撥函式。

                      callback引數使用注意:

當編寫爬蟲規則時,請避免使用parse作為回撥函式。於使用parse方法來實現其邏輯,如果您覆蓋了parse方法,crawlspider將會執行失敗。

follow:指定了根據該規則從response提取的連結是否需要跟進。當callbackNone,預設值為true

process_links:主要用來過濾由link_extractor獲取到的連結。

process_request:主要用來過濾在rule中提取到的request

2.LinkExtractor

(1)概念:

顧名思義,連結提取器。

(2) 作用:

response物件中獲取連結,並且該連結會被接下來爬取。

(3) 使用:

通過SmglLinkExtractor提取希望獲取的連結。

classscrapy.contrib.linkextractors.sgml.SgmlLinkExtractor(
allow=(),deny=(),allow_domains=(),deny_domains=(),deny_extensions=None,restrict_xpaths=(),tags=('a','area'),attrs=('href'),canonicalize=True,unique=True,process_value=None)

主要引數:

allow:滿足括號中“正則表示式”的值會被提取,如果為空,則全部匹配。

deny與這個正則表示式(或正則表示式列表)不匹配的URL一定不提取

allow_domains會被提取的連結的domains

deny_domains:一定不會被提取連結的domains

restrict_xpaths:使用xpath表示式,和allow共同作用過濾連結。

.RUN!

  1. shell中驗證

    開始編寫程式碼之前,使用scrapyshell檢視使用SmglLinkExtractor在網頁中獲取到的連結:

    scrapy shell http://blog.csdn.net/u012150179/article/details/11749017

    繼續import相關模組:
    fromscrapy.contrib.linkextractors.sgml import SgmlLinkExtractor

    現在使用SgmlLinkExtractor檢視在當前網頁中獲得的連結:
    item=SgmlLinkExtractor(allow=('/u012150179/article/details')).extract_links(response)

    其中item為包含Link()物件的列表,現在顯示其中的text元素(就是獲取到的文章連結對應的文章標題):
    for i in item:
        print i.text

    部分結果截圖:

    對照網頁可以得到此時獲取的是當前網頁中所有滿足allow條件的連結,不僅包含“下一篇”的連結,還有網頁側邊欄“閱讀排行“、”評論排行“中的文章連結。為了只獲得”下一篇“文章連結,這就要進行所有連結的篩選,引入引數restrict_xpaths,繼續:

    item= SgmlLinkExtractor(allow=('/u012150179/article/details'),restrict_xpaths=('//li[@class="next_article"]')).extract_links(response)

    這是在如上檢視結果,便提取出了“下一篇”文章連結。

    注意:在shell中並不對提取到的link進行跟進。

    在這裡不得不提的就是scrapy shell是對除錯、驗證很有用的互動工具。應該掌握。

    shell中進行了驗證後進入寫程式碼階段。

編寫程式碼

1items.pypipelines.py以及settings.py與之前教程類似,不詳細描述。

2)爬蟲編寫。

上碼:

# -*- coding:utf-8 -*-

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import Selector
from CSDNBlogCrawlSpider.items import CsdnblogcrawlspiderItem


class CSDNBlogCrawlSpider(CrawlSpider):

    """繼承自CrawlSpider,實現自動爬取的爬蟲。"""

    name = "CSDNBlogCrawlSpider"
    #設定下載延時
    download_delay = 2
    allowed_domains = ['blog.csdn.net']
    #第一篇文章地址
    start_urls = ['http://blog.csdn.net/u012150179/article/details/11749017']

    #rules編寫法一,官方文件方式
    #rules = [
    #    #提取“下一篇”的連結並**跟進**,若不使用restrict_xpaths引數限制,會將頁面中所有
    #    #符合allow連結全部抓取
    #    Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),
    #                          restrict_xpaths=('//li[@class="next_article"]')),
    #         follow=True)
    #
    #    #提取“下一篇”連結並執行**處理**
    #    #Rule(SgmlLinkExtractor(allow=('/u012150179/article/details')),
    #    #     callback='parse_item',
    #    #     follow=False),
    #]

    #rules編寫法二,更推薦的方式(自己測驗,使用法一時經常出現爬到中間就finish情況,並且無錯誤碼)
    rules = [
        Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),
                              restrict_xpaths=('//li[@class="next_article"]')),
             callback='parse_item',
             follow=True)
    ]

    def parse_item(self, response):

        #print "parse_item>>>>>>"
        item = CsdnblogcrawlspiderItem()
        sel = Selector(response)
        blog_url = str(response.url)
        blog_name = sel.xpath('//div[@id="article_details"]/div/h1/span/a/text()').extract()

        item['blog_name'] = [n.encode('utf-8') for n in blog_name]
        item['blog_url'] = blog_url.encode('utf-8')

        yield item

執行:

scrapy crawl CSDNBlogCrawlSpider

得到的效果如教程(五)一致。

其中指出和教程(五)所編寫爬蟲方法的差異:

首先,基類CrawlSpider提供了更完善的自動多網頁爬取機制,只需要我們配置的就是rules,通過Rule物件實現連結的提取與跟進,恩,對,沒了。。。就這樣。詳細的註釋也都在程式中。

進行到這裡,就將本篇文章主題講述完畢,核心是CrawlSpider,主要方法是rules。

關於scrapy的使用可參見之前文章: