Python网络爬虫(scrapy-redis两种形式的分布式爬虫)
一、scrapy框架不能自己实现分布式爬虫的原因
其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls列表中的url。(多台机器无法共享同一个调度器)
其二:多台机器爬取到的数据无法通过同一个管道对数据进行统一的数据持久出存储。(多台机器无法共享同一个管道)
二、基于scrapy-redis组件作用
其一:给原生的scrapy提供了可以被共享的调度器和管道
其二:分布爬取的数据必须存储到redis中
三、scrapy-redis安装
# 安装scrapy-redis分布式爬虫组件 pip install scrapy-redis
四、基于scrapy-redis组件的分布式爬虫
scrapy-redis组件中为我们封装好了可以被多台机器共享的调度器和管道,我们可以直接使用并实现分布式数据爬取。
将爬虫类的父类修改成基于RedisSpider或者RedisCrawlSpider。
注意:如果原始爬虫文件是基于Spider的,则应该将父类修改成RedisSpider,如果原始爬虫文件是基于CrawlSpider的,则应该将其父类修改成RedisCrawlSpider。
- 注释或者删除start_urls列表,切加入redis_key属性,属性值为scrpy-redis组件中调度器队列的名称
实现方式:
1.基于该组件的RedisSpider类配置:爬虫文件
# -*- coding: utf-8 -*- import scrapy from ..items import WangyiproItem from selenium import webdriver # 配置scrapy-redis分布式 # 给原生的scrapy提供了可以被共享的调度器和管道 from scrapy_redis.spiders import RedisSpider # 继承分布式爬虫类(RedisSpider) class WangyiSpider(RedisSpider): name = 'wangyi' # allowed_domains = ['www.xx.com'] # 在分布式爬虫中,不再需要指定起始url # start_urls = ['http://www.xx.com/'] # 指定被共享的调度器队列的名称 redis_key = "sunQueue" # 数据解析 def parse(self, response): pass
2.基于该组件的RedisCrawlSpider类配置:爬虫文件
# -*- coding: utf-8 -*- import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from fbssunPro.items import FbssunproItem # 配置scrapy-redis分布式 # 给原生的scrapy提供了可以被共享的调度器和管道 from scrapy_redis.spiders import RedisCrawlSpider # 继承分布式爬虫类(RedisCrawlSpider) class SunSpider(RedisCrawlSpider): name = 'sun' # allowed_domains = ['www.xx.com'] # 在分布式爬虫中,不再需要指定起始url # start_urls = ['http://www.xx.com/'] # 指定被共享的调度器队列的名称 redis_key = "sunQueue" # 规则解析器 rules = ( Rule(LinkExtractor(allow=r'正则表达式'), callback='parse_item', follow=True), ) # 数据解析 def parse_item(self, response): pass
3.爬虫配置文件settings.py
#在配置文件中进行相关配置,开启使用scrapy-redis组件中封装好的调度器 # 使用scrapy-redis组件的去重队列 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 使用scrapy-redis组件自己的调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 是否允许暂停 SCHEDULER_PERSIST = True #在配置文件中进行爬虫程序链接redis的配置: REDIS_HOST = 'redis服务的ip地址' REDIS_PORT = 6379 REDIS_ENCODING = ‘utf-8’ REDIS_PARAMS = {‘password’:’123456’}
五、基于scrapy-redis组件的redis数据库配置
注意:scrapy-redis爬虫组件是基于redis数据库做数据持久化,不能是别的数据库
修改redis启动配置文件:redis.windows.conf
# redis.windows.conf配置: - 注释该行:bind 127.0.0.1,表示可以让其他ip访问redis - 将yes该为no:protected-mode no,表示可以让其他ip操作redis ———————————————数据库操作———————----—————— # 启动redis数据库服务端(当前文件下启动) redis-server ./redis.windows.conf # 启动redis客户端 redis-cli # 向数据中添加调度器 队列名称 # 调度器的队列名称就是redis_key值 # 爬虫文件定义的redis_key = "sunQueue" # 自定义队列名 lpush sunQueue www.xxx.com # 添加爬虫起始url
五、基于scrapy-redis分布式爬虫启动步骤
# 开启redis数据库 开启redis服务器:redis-server 配置文件 开启redis客户端:redis-cli # 运行爬虫文件,监听起始请求对象 进入爬虫文件目录:cd ./spiders 运行爬虫文件:scrapy runspider SpiderFile # 调度器队列中等待请求对象 向调度器队列中扔入一个起始url(在redis客户端中操作):lpush redis_key属性值 起始url
六、基于scrapy-redis分布式爬虫实例(东莞阳光网)
需求:通过分布式爬虫(scrapy-redis)获取网站文章标题信息,url:http://wz.sun0769.com/index.php/question/questionType?type=4&page=
爬虫文件:sun.py
# -*- coding: utf-8 -*- import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from fbssunPro.items import FbssunproItem # 配置scrapy-redis分布式 # 给原生的scrapy提供了可以被共享的调度器和管道 from scrapy_redis.spiders import RedisCrawlSpider # 继承分布式爬虫类(RedisCrawlSpider) class SunSpider(RedisCrawlSpider): name = 'sun' # allowed_domains = ['www.xx.com'] # 在分布式爬虫中,不再需要指定起始url # start_urls = ['http://www.xx.com/'] # 指定被共享的调度器队列的名称 redis_key = "sunQueue" # 规则解析器 rules = ( Rule(LinkExtractor(allow=r'type=4&page=\d+'), callback='parse_item', follow=True), ) # 数据解析 def parse_item(self, response): tr_list = response.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr') for tr in tr_list: # 获取所有的文章标题 title = tr.xpath('./td[2]/a[2]/text()').extract_first() item = FbssunproItem() item['title'] = title # 提交数据到管道 yield item
Item对象类文件:items.py
import scrapy class FbssunproItem(scrapy.Item): # define the fields for your item here like: title = scrapy.Field()
管道文件类文件:pipelines.py
class FbssunproPipeline(object): # 持久化存储 def process_item(self, item, spider): # item对象结果是一个字典 print(item) return item
爬虫配置文件:settings.py
BOT_NAME = 'fbssunPro' SPIDER_MODULES = ['fbssunPro.spiders'] NEWSPIDER_MODULE = 'fbssunPro.spiders' # Obey robots.txt rules ROBOTSTXT_OBEY = True # 开启管道 ITEM_PIPELINES = { 'fbssunPro.pipelines.FbssunproPipeline': 300, } # 配置调度器 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" SCHEDULER = "scrapy_redis.scheduler.Scheduler" SCHEDULER_PERSIST = True # 指定数据库 REDIS_HOST = '192.168.1.102' REDIS_PORT = 6379
完成!!!