(2018-05-23.Python從Zero到One)7、(爬蟲)scrapy-Redis實戰(zhàn)__1.7.1源碼自帶項目說明

源碼自帶項目說明:

使用scrapy-redis的example來修改
先從github上拿到scrapy-redis的示例,然后將里面的example-project目錄移到指定的地址:

# clone github scrapy-redis源碼文件
git clone https://github.com/rmax/scrapy-redis.git

# 直接拿官方的項目范例,改名為自己的項目用(針對懶癌患者)
mv scrapy-redis/example-project ~/scrapyredis-project

我們clone到的 scrapy-redis 源碼中有自帶一個example-project項目,這個項目包含3個spider,分別是dmoz, myspider_redis,mycrawler_redis。

一、dmoz (class DmozSpider(CrawlSpider))

這個爬蟲繼承的是CrawlSpider,它是用來說明Redis的持續(xù)性,當我們第一次運行dmoz爬蟲,然后Ctrl + C停掉之后,再運行dmoz爬蟲,之前的爬取記錄是保留在Redis里的。

分析起來,其實這就是一個 scrapy-redis 版CrawlSpider 類,需要設置Rule規(guī)則,以及callback不能寫parse()方法。

執(zhí)行方式:scrapy crawl dmoz

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class DmozSpider(CrawlSpider):
    """Follow categories and extract links."""
    name = 'dmoz'
    allowed_domains = ['dmoz.org']
    start_urls = ['http://www.dmoz.org/']

    rules = [
        Rule(LinkExtractor(
            restrict_css=('.top-cat', '.sub-cat', '.cat-item')
        ), callback='parse_directory', follow=True),
    ]

    def parse_directory(self, response):
        for div in response.css('.title-and-desc'):
            yield {
                'name': div.css('.site-title::text').extract_first(),
                'description': div.css('.site-descr::text').extract_first().strip(),
                'link': div.css('a::attr(href)').extract_first(),
            }

二、myspider_redis (class MySpider(RedisSpider))

這個爬蟲繼承了RedisSpider, 它能夠支持分布式的抓取,采用的是basic spider,需要寫parse函數(shù)。

其次就是不再有start_urls了,取而代之的是redis_key,scrapy-redis將key從Redis里pop出來,成為請求的url地址。

from scrapy_redis.spiders import RedisSpider


class MySpider(RedisSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""
    name = 'myspider_redis'

    # 注意redis-key的格式:
    redis_key = 'myspider:start_urls'

    # 可選:等效于allowd_domains(),__init__方法按規(guī)定格式寫,使用時只需要修改super()里的類名參數(shù)即可
    def __init__(self, *args, **kwargs):
        # Dynamically define the allowed domains list.
        domain = kwargs.pop('domain', '')
        self.allowed_domains = filter(None, domain.split(','))

        # 修改這里的類名為當前類名
        super(MySpider, self).__init__(*args, **kwargs)

    def parse(self, response):
        return {
            'name': response.css('title::text').extract_first(),
            'url': response.url,
        }

注意:

RedisSpider類 不需要寫allowd_domainsstart_urls

scrapy-redis將從在構(gòu)造方法init()里動態(tài)定義爬蟲爬取域范圍,也可以選擇直接寫allowd_domains`。

必須指定redis_key,即啟動爬蟲的命令,參考格式:redis_key = 'myspider:start_urls'

根據(jù)指定的格式,start_urls將在 Master端的 redis-cli 里 lpush 到 Redis數(shù)據(jù)庫里,RedisSpider 將在數(shù)據(jù)庫里獲取start_urls。

執(zhí)行方式:

通過runspider方法執(zhí)行爬蟲的py文件(也可以分次執(zhí)行多條),爬蟲(們)將處于等待準備狀態(tài):

scrapy runspider myspider_redis.py
在Master端的redis-cli輸入push指令,參考格式:

$redis > lpush myspider:start_urls http://www.dmoz.org/
Slaver端爬蟲獲取到請求,開始爬取。

三、mycrawler_redis (class MyCrawler(RedisCrawlSpider))

這個RedisCrawlSpider類爬蟲繼承了RedisCrawlSpider,能夠支持分布式的抓取。因為采用的是crawlSpider,所以需要遵守Rule規(guī)則,以及callback不能寫parse()方法。

同樣也不再有start_urls了,取而代之的是redis_key,scrapy-redis將key從Redis里pop出來,成為請求的url地址。

from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor

from scrapy_redis.spiders import RedisCrawlSpider


class MyCrawler(RedisCrawlSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""
    name = 'mycrawler_redis'
    redis_key = 'mycrawler:start_urls'

    rules = (
        # follow all links
        Rule(LinkExtractor(), callback='parse_page', follow=True),
    )

    # __init__方法必須按規(guī)定寫,使用時只需要修改super()里的類名參數(shù)即可
    def __init__(self, *args, **kwargs):
        # Dynamically define the allowed domains list.
        domain = kwargs.pop('domain', '')
        self.allowed_domains = filter(None, domain.split(','))

        # 修改這里的類名為當前類名
        super(MyCrawler, self).__init__(*args, **kwargs)

    def parse_page(self, response):
        return {
            'name': response.css('title::text').extract_first(),
            'url': response.url,
        }

注意:

同樣的,RedisCrawlSpider類不需要寫allowd_domainsstart_urls

scrapy-redis將從在構(gòu)造方法__init__()里動態(tài)定義爬蟲爬取域范圍,也可以選擇直接寫allowd_domains。

必須指定redis_key,即啟動爬蟲的命令,參考格式:redis_key = 'myspider:start_urls'

根據(jù)指定的格式,start_urls將在 Master端的 redis-cli 里 lpush 到 Redis數(shù)據(jù)庫里,RedisSpider 將在數(shù)據(jù)庫里獲取start_urls。

執(zhí)行方式:

通過runspider方法執(zhí)行爬蟲的py文件(也可以分次執(zhí)行多條),爬蟲(們)將處于等待準備狀態(tài):

scrapy runspider mycrawler_redis.py
在Master端的redis-cli輸入push指令,參考格式:

$redis > lpush mycrawler:start_urls http://www.dmoz.org/
爬蟲獲取url,開始執(zhí)行。

總結(jié):

如果只是用到Redis的去重和保存功能,就選第一種;

如果要寫分布式,則根據(jù)情況,選擇第二種、第三種;

通常情況下,會選擇用第三種方式編寫深度聚焦爬蟲。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容