基於scrapy-redis兩種形式的分散式爬蟲
redis分散式部署
1.scrapy框架是否可以自己實現分散式?
- 不可以。原因有二。
其一:因為多臺機器上部署的scrapy會各自擁有各自的排程器,這樣就使得多臺機器無法分配start_urls列表中的url。(多臺機器無法共享同一個排程器)
其二:多臺機器爬取到的資料無法通過同一個管道對資料進行統一的資料持久出儲存。(多臺機器無法共享同一個管道)
2.基於scrapy-redis元件的分散式爬蟲
- scrapy-redis元件中為我們封裝好了可以被多臺機器共享的排程器和管道,我們可以直接使用並實現分散式資料爬取。
- 實現方式:
1.基於該元件的RedisSpider類
2.基於該元件的RedisCrawlSpider類
3.分散式實現流程:上述兩種不同方式的分散式實現流程是統一的
- 3.1 下載scrapy-redis元件:pip install scrapy-redis
- 3.2 redis配置檔案的配置:
- 註釋該行:bind 127.0.0.1,表示可以讓其他ip訪問redis
- 將yes該為no:protected-mode no,表示可以讓其他ip操作redis
3.3 修改爬蟲檔案中的相關程式碼:
- 將爬蟲類的父類修改成基於RedisSpider或者RedisCrawlSpider。注意:如果原始爬蟲檔案是基於Spider的,則應該將父類修改成RedisSpider,如果原始爬蟲檔案是基於CrawlSpider的,則應該將其父類修改成RedisCrawlSpider。
- 註釋或者刪除start_urls列表,切加入redis_key屬性,屬性值為scrpy-redis元件中排程器佇列的名稱
3.4 在配置檔案中進行相關配置,開啟使用scrapy-redis元件中封裝好的管道
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 400
}
3.5 在配置檔案中進行相關配置,開啟使用scrapy-redis元件中封裝好的排程器
# 使用scrapy-redis元件的去重佇列
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis元件自己的排程器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 是否允許暫停
SCHEDULER_PERSIST = True
3.6 在配置檔案中進行爬蟲程式連結redis的配置:
REDIS_HOST = 'redis服務的ip地址'
REDIS_PORT = 6379
REDIS_ENCODING = ‘utf-8’
REDIS_PARAMS = {‘password’:’123456’}
3.7 開啟redis伺服器:redis-server 配置檔案
3.8 開啟redis客戶端:redis-cli
3.9 執行爬蟲檔案:scrapy runspider SpiderFile
3.10 向排程器佇列中扔入一個起始url(在redis客戶端中操作):lpush redis_key屬性值 起始url
1.基於該元件的RedisSpider類爬蟲程式碼如下
資料:國產器械,資料條數10萬條
1 # -*- coding: utf-8 -*- 2 import scrapy 3 from scrapy_redis.spiders import RedisSpider 4 from redisSpiderPro.items import RedisspiderproItem 5 class RedisspidertestSpider(RedisSpider): 6 name = 'redisSpiderTest' 7 # allowed_domains = ['www.xxx.com'] 8 # start_urls = ['http://www.xxx.com/'] 9 10 #排程器佇列的名稱 11 redis_key='data' 12 url='http://db.pharmcube.com/database/cfda/detail/cfda_cn_instrument/' 13 pageNum=1 14 def parse(self, response): 15 num=response.xpath('/html/body/div/table/tbody/tr[1]/td[2]/text()').extract_first() 16 name=response.xpath('/html/body/div/table/tbody/tr[2]/td[2]/text()').extract_first() 17 18 item=RedisspiderproItem() 19 item['num']=num 20 item['name']=name 21 yield item 22 23 if self.pageNum<=10000: 24 self.pageNum+=1 25 new_url=self.url+str(self.pageNum) 26 yield scrapy.Request(url=new_url,callback=self.parse)爬蟲程式碼
setting配置
1 USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36' 2 3 ROBOTSTXT_OBEY = False 4 5 #管道 6 ITEM_PIPELINES = { 7 'scrapy_redis.pipelines.RedisPipeline': 400 8 } 9 10 # 使用scrapy-redis元件的去重佇列 11 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" 12 # 使用scrapy-redis元件自己的排程器 13 SCHEDULER = "scrapy_redis.scheduler.Scheduler" 14 # 是否允許暫停 15 SCHEDULER_PERSIST = True 16 17 18 #redis連線資料庫的引數 19 REDIS_HOST = '192.168.19.38' 20 REDIS_PORT = 6379 21 #編碼格式 22 # REDIS_ENCODING = ‘utf-8’ 23 #使用者名稱密碼 24 # REDIS_PARAMS = {‘password’:’123456’}setting
2.基於該元件的RedisCrawlSpider類爬蟲程式碼如下
資料 抽屜網:爬取段子
爬蟲程式碼:
1 import scrapy 2 from scrapy.linkextractors import LinkExtractor 3 from scrapy.spiders import CrawlSpider, Rule 4 from redisCrawlSpiderPro.items import RediscrawlspiderproItem 5 from scrapy_redis.spiders import RedisCrawlSpider 6 7 class CrawlspiderSpider(RedisCrawlSpider): 8 name = 'CrawlSpider' 9 # allowed_domains = ['www.xxx.com'] 10 # start_urls = ['http://www.xxx.com/'] 11 12 redis_key='data' 13 link=LinkExtractor(allow=r'/r/scoff/hot/\d+') 14 rules = ( 15 Rule(link, callback='parse_item', follow=True), 16 ) 17 18 def parse_item(self, response): 19 div_list=response.xpath('//div[@id="content-list"]/div') 20 for div in div_list: 21 item=RediscrawlspiderproItem() 22 item['title'] = div.xpath('./div[3]/div/a/text()').extract_first() 23 item['author'] = div.xpath('./div[3]/div[2]/a[4]/b/text()').extract_first() 24 yield item爬蟲程式碼