源碼自帶項目說明:
使用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_domains和start_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_domains和start_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ù)情況,選擇第二種、第三種;
通常情況下,會選擇用第三種方式編寫深度聚焦爬蟲。