===============================================================Scrapy-Redis分布式爬虫框架===============================================================1.Scrapy-Rdis-project: example  (Scrapy-Redis分布式爬虫框架----范例说明(Dmoz网站)  )---------------------------------------------------------------------------------------------------------------------------------------------------------------------|                               |  1.创建项目--- scrapy startproject example|          example/|          ├── scrapy.cfg|          └── example|              ├── __init__.py|              ├── items.py|              ├── middlewares.py|              ├── pipelines.py|              ├── settings.py|              └── spiders|                  ├── __init__.py|                  └── my_crawlspider.py/my_redisspider.py/my_rediscrawlspider.py  # 3中类型的Scrap-Redis爬虫|                               |  2.明确目标--- vim items.py|      vim items.py|          import scrapy|                               |          class ExampleItem(scrapy.Item):|              name = scrapy.Field()|              description = scrapy.Field()|              link = scrapy.Field()|              crawled = scrapy.Field()|              spider = scrapy.Field()|              url = scrapy.Field()|                               |  3.编写自定义pipeline--- vim pipelines.py|      vim pipelins.py|          from datetime import datetime|          class ExampPipeline(object):|              def process_item(self,item,spider):|                  item['crawled'] = datetime.utcnow()  # 调用datetime.utcnow()方法获取爬虫执行时的UTC时间|                  item['spider'] = spider.name         # 调用spider.name属性获取当前爬虫名(因为可能同时有多个爬虫在爬取,这样可以看到谁爬了哪些网页)|                  return item|                               |  4.注册自定义pipeline及Scrapy-Redis分布式爬虫相关设置--- vim settings.py|      vim settings.py|          #-----------Scrapy-Redis分布式爬虫相关设置如下-------------|          DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"   # 使用Scrapy-Redis的去重组件,不再使用scrapy的去重组件|          SCHEDULER = "scrapy_redis.scheduler.Scheduler"               # 使用Scrapy-Redis的调度器,不再使用scrapy的调度器|          SCHEDULER_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"   # 使用Scrapy-Redis的从请求集合中取出请求的方式,三种方式择其一即可:|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderQueue"          # 分别按(1)请求的优先级/(2)队列FIFO/(3)栈FILO 取出请求|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderStack"|          SCHEDULER_PERSIST = True          # 允许暂停,redis请求记录不会丢失(重启爬虫不会重头爬取已爬过的页面)|                               |          REDIS_HOST = "200.200.200.200"    # 这两项是Redis连接设置,如果注释或不写会默认将数据存放到本机的Redis中|          REDIS_PORT = 6379                 # 注意:master端的Redis需要允许远程连接--配置中注释掉bind 127.0.0.1|                               |          #----------注册RedisPipeline/自定义pipeline------------------|          ITEM_PIPELINES = {|                  "example.pipelines.ExampPipeline":300,        # 自定义pipeline视情况选择性注册(可选)|                  "scrapy_redis.pipelines.RedisPipeline":400    # 将RedisPipeline注册到pipeline组件中(这样才能将数据存入Redis)|              }   # 注意:自定义pipeline的优先级需高于Redispipeline,因为RedisPipeline不会返回item,所以如果RedisPipeline优先级高于自定义pipeline,那么自定义pipeline无法获取到item|                               |  5.制作爬虫(三种Scrapy-Redis爬虫--- CrawlSpider/RedisSpider/RedisCrawlSpider)|                               |                               |      类型一:基于CrawlSpider类的Scrapy-Redis分布式爬虫 (无需任何修改)|      =================================================================================|          (1)生成爬虫--- scrapy genspider -t crawl my_crawlspider "dmoz.org"|          (2)设置爬虫--- vim my_crawlspider.py|          vim my_crawlspider.py|              from scrapy.linkextractor import LinkExtractor|              from scrapy.Spiders import CrawlSpider,Rule|                               |              class My_crawlspider(CrawlSpider):|                  name = "my_crawlspider"|                  allowed_domains = ["dmoz.org"]|                  start_urls = ["http://www.dmoz.org/"]|                  links = LinkExtractor(restrict_css('.top-cat','.sub-cat','.cat-item'))|                  rules = [|                      Rule(links,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(),    # 直接将name/description/link存入Redis数据库|                                  'link':div.css('.a::attr(href)').extract(),|                              }|          (3)执行爬虫方法--- scrapy crawl my_crawlspider (与正常scrapy一样,无需redis_key,比较鸡肋并不是真正的多机器爬虫)|                               |                               |                               |      类型二:基于RedisSpider类的Scrapy-Redis分布式爬虫 (需要部分删改)|      =================================================================================|          (1)生成爬虫--- scrapy genspider my_redisspider "dmoz.org"|          (2)设置爬虫--- vim my_redisspider.py    |          vim my_redisspider.py|              from scrapy_redis.Spiders import RedisSpider                        # 变化1:从scrapy_redis.Spiders中引入RedisSpider|                               |              class My_redisspiderSpider(RedisSpider):                            # 变化2:爬虫类所继承的父类变为RedisSpider类|                  name = 'my_redisspider'|                  redis_key = "my_redisspider:start_urls"                         # 变化3:多了一个对所有爬虫发号施令的redis_key,少了allowed_domain和start_urls|                               |                  def __init__(self,*args,**kwargs):                              # 变化4:重写__init__方法:动态获取限制域|                      domain = kwargs.pop('domain','')|                      self.allowed_domain = filter(None,domain,split(','))|                      super(My_redisspiderSpider,self).__init__(*args,**kwargs)   # 注意super()里面的参数因爬虫类名不同而不同|                               |                  def parse(self,response):|                      return {    'name':response.css('.site-title::text').extract_first(),|                                  'url':respons.url,                              # 直接将name/url存入Redis数据库|                          }|          (3)执行爬虫方法                                                         # 变化5:爬虫执行方法变化|              <1>将项目代码复制到给台slave上(可更改爬虫名)并启动爬虫--- scrapy runspider my_redisspider.py|              <2>在master端redis上发号施令--- lpush my_redisspider:start_urls http://www.dmoz.org/|                               |                               |                               |      类型三:基于RedisCrawlSpider类飞Scrapy-Redis分布式爬虫 (需要部分删改)|      =================================================================================|          (1)生成爬虫--- scrapy genspider -t crawl my_rediscrawlspider "dmoz.org"|          (2)设置爬虫--- vim my_rediscrawlspider.py|          vim my_rediscrawlspider.py|              from scrapy.linkextractor import LinkExtractor|              from scrapy.Spiders import CrawlSpider,Rule|              from scrapy_redis.Spiders import RedisCrawlSpider                             # 变化1:从scrapy_redis.Spiders中引入RedisCrawlSpider|                               |              class My_rediscrawlspiderSpider(RedisCrawlSpider):                            # 变化2:爬虫类所继承的父类变为RedisCrawlSpider类|                  name = 'my_rediscrawlspider'                  |                  redis_key = 'my_rediscrawlspider:start_urls'                              # 变化3:多了一个对所有爬虫发号施令的redis_key,少了allowed_domain和start_urls|                               |                  rules =[    Rule(LinkExtractor(),callback='parse_page',follow=True),    ]|                               |                  def __init__(self,*args,**kwargs):                                        # 变化4:重写__init__方法:动态获取限制域|                      domain = kwargs.pop('domain','')|                      self.allowed_domain = filter(None,domain,split(','))|                      super(My_rediscrawlspiderSpider,self).__init__(*args,**kwargs)        # 注意super()里面的参数因爬虫类名不同而不同|                               |                  def parse_page(self,response):|                      return {    'name':response.css('.site-title::text').extract_first(),|                                  'url':respons.url,                                        # 直接将name/url存入Redis数据库|                          }|          (3)执行爬虫方法                                                                   # 变化5:爬虫执行方法变化|              <1>将项目代码复制到给台slave上(可更改爬虫名)并启动爬虫--- scrapy runspider my_rediscrawlspider.py|              <2>在master端redis上发号施令--- lpush my_rediscrawlspider:start_urls http://www.dmoz.org/|                               |  小结:                             |      如果只想使用Redis的去重和保存功能 ---- 使用类型一|      如果写分布式 ---- 根据情况选择类型二/类型三|      如果写聚焦爬虫 ---- 选择类型三|                               ---------------------------------------------------------------------------------------------------------------------------------------------------------------------2.Scrapy-Rdis-project: youyuan  (Scrapy-Redis分布式爬虫框架进阶1----有缘网:非分布式基于CrawlSpider的scrapy项目  )---------------------------------------------------------------------------------------------------------------------------------------------------------------------|                               |  1.创建项目--- scrapy startproject youyuan|          youyuan/|          ├── scrapy.cfg|          └── youyuan|              ├── __init__.py|              ├── items.py|              ├── middlewares.py|              ├── pipelines.py|              ├── settings.py|              └── spiders|                  ├── __init__.py|                  └── yy.py|                               |  2.明确目标--- vim items.py|      vim items .py|          improt scrapy                             |                               |          class YouyuanItem(scrapy.Item):|              username = scrapy.Field()       # 用户名|              age = scrapy.Field()            # 年龄|              header_url = scrapy.Field()     # 头像地址|              image_url = scrapy.Field()      # 相册个图片地址|              content = scrapy.Field()        # 内心独白|              place_from = scrapy.Field()     # 籍贯|              education = scrapy.Field()      # 教育|              hobby = scrapy.Field()          # 爱好|              source_url = scrapy.Field()     # 个人主页|              source = scrapy.Field()         # 数据来源网站|                               |  3.制作爬虫  |      (1)生成爬虫--- scrapy genspider -t crawl yy "youyuan.com"|      (2)设置爬虫--- vim yy.py|      vim  yy.py|          import scrapy|          from scrapy.linkextractor import LinkExtractor|          from scrapy.Spiders import CrawlSpider,Rule|          from youyuan.items import YouyuanItem|          import re|                               |          class YySpider(CrawlSpider):|              name = "yy"|              allowed_domains = ['youyuan.com']|              start_urls = ["http://www.youyuan.com/find/beijing/mm18-25/advance-0-0-0-0-0-0-0/p1/"]|  |              page_links = LinkExtractor(allow=(r'youyuan.com/find/beijing/mm18-25/advance-0-0-0-0-0-0-0/p\d+/')) # 获取每个显示页的连接|              person_links = LinkExtractor(allow =(r'youyuan.com/\d+-profile/'))                                  # 获取个人主页|              rules = ( |                      Rule(page_links),                                 # 没有callback/没有follow,默认follow=True继续跟进|                      Rule(person_links,callback='parse_item'),         # 有callback/没有follow,默认follow=False不继续跟进|                  )|              def parse_item(self,response):|                  item = YouyuanItem()|                  item['username'] = self.get_username()|                  item['age'] = self.get_age()|                  item['header_url'] = self.get_header_url()|                  item['image_url'] = self.get_image_url()|                  item['content'] = self.get_content()|                  item['place_from'] = self.get_place_from()|                  item['education'] = self.get_education()|                  item['hobby'] = self.get_hobby()|                  item['source_url'] = self.get_source_url()|                  item['source'] = self.get_source()|                               |              #-----所谓不再使用土枪土炮,看起来高大上的方法----------|              def get_username(self.response):|                  username = response.xpath('//dl[@class="person_cen"]//div[@class="main"]/strong/text()').extract()|                  if len(username):|                      username = username[0]|                  else:|                      username = "Null"|                  return username.strip()|              def get_age(self,response):|                  age = response.xpath('//dl/[@class="person_cen"]//dd/p/text()').extract()|                  if len(age):|                      age = re.find_all(u"\d+岁",age[0])[0]|                  else:|                      age = "Null"|                  return age.strip()|              def get_header_url(self,response):|                  header_url = response.xpath('//dl[@class="person_cen"]//dt/img/@src').extract()|                  if len (header_url):|                      header_url = header_url[0]|                  else:|                      header_url = "Null"|                  return header_url.strip()|              def get_image_url(self,response):|                  image_url = response.xpath('//div[@class="ph_show"]/ul/li/a/img/@src').extract()|                  if len(image_url):|                      image_url = "|".join(image_url)  # 这样生成这种形式:xxxx|xxxx|xxxx||                  else:|                      image_url = "Null"|                  return image_url|              def get_content(self,response):|                  content = response.xpath('//div[@class="pre_data"]/ul/li[2]//ol[1]/span/text()').extract()|                  if len(content):|                      content = content[0]|                  else:|                      content = "Null"|                  return content.strip()|              def get_place_from(self,response):|                  place_from = response.xpath('//div[@class="pre_data"]/ul/li[2]//ol[2]/li[1]/span/text()').extract()|                  if len(place_from):|                      place_from = place_from[0]|                  else:|                      place_from = "Null"|                  return place_from.strip()|              def get_education(self,response):|                  education = response.xpath('//div[@class="pre_data"]/ul/li[3]//ol[2]//li[2]/span/text()').extract()|                  if len(education):|                      education = education[0]|                  else:|                      education = "Null"|                  return education.strip()|              def get_hobby(self,response):|                  hobby = response.xpath('//dl[@class="person_cen"]//ol/li/text()').extract()|                  if len(hobby):|                      hobby = ",".join(hobby).replace(" ","")|                  else:|                      hobby = "Null"|                  return hobby.strip()|                               |  4.编写item pipeline--- vim pipelines.py|      vim pipelines.py|          import json                             |                               |          class YouyuanJsonPipeline(obeject):|              def __init__(self):|                  self.f = open("youyuan.json","w")|              def process_item(self,item,spider):|                  text = json.dumps(dict(item),ensure_ascii=False) + ",\n"|                  self.f.write(item)|              def close_spider(self,spider):|                  self.f.close()|                               |  5.启动上述pipeline---  vim settings.py|      vim settings.py|          ITEM_PIPELINES = {"youyuan.pipelines.YouyuanJsonPipeline":300}|                               |  6.执行爬虫--- scrapy crawl yy|                               ---------------------------------------------------------------------------------------------------------------------------------------------------------------------3.Scrapy-Rdis-project: youyuan  (Scrapy-Redis分布式爬虫框架进阶2----有缘网:非分布式基于CrawlSpider的scrapy项目的数据存入本机Redis  )---------------------------------------------------------------------------------------------------------------------------------------------------------------------|                               |      说明:仅仅实在上述scrapy项目的基础上进行settings.py文件的点滴修改,增加一个RedisPipeline而已 <----并不属于Scrapy-Redis分布式|          youyaun/|          ├── scrapy.cfg|          └── youyaun|              ├── __init__.py|              ├── items.py|              ├── middlewares.py|              ├── pipelines.py|              ├── settings.py     <----仅对settings.py文件做部分添加修改|              └── spiders|                  ├── __init__.py|                  └── yy.py|                               |  5.settings.py添加部分信息--- 启用Scrapy-Redis的去重组件/调度器/取出请求方式,以及注册RedisPipeline组件(让数据存入Redis)|      vim settings.py|          DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"  # 使用Scrapy-Redis的去重组件,不再使用scrapy的去重组件|          SCHEDULER = "scrapy_redis.scheduler.Scheduler"              # 使用Scrapy-Redis的调度器,不再使用scrapy的调度器|          SCHEDULER_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"  # 使用Scrapy-Redis的从请求集合中取出请求的方式,三种方式择其一即可:|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderQueue"         # 分别按(1)请求的优先级/(2)队列FIFO/(3)栈FILO 取出请求|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderStack"|          SCHEDULER_PERSIST = True                                    # 允许暂停,redis请求记录不会丢失(重启爬虫不会重头爬取已爬过的页面)|                               |          #REDIS_HOST = "200.200.200.200"                             # 这两项是Redis连接设置,注释或不写默认将数据存放到本机的Redis中|          #REDIS_PORT = 6379              |                               |          #----------注册RedisPipeline/自定义pipeline------------------|          ITEM_PIPELINES = {|                  "youyuan.pipelines.YouyuanJsonPipeline":300,        # 自定义pipeline视情况选择性注册(可选)|                  "scrapy_redis.pipelines.RedisPipeline":400          # 将RedisPipeline注册到pipeline组件中(这样才能将数据存入Redis)|              }    # 注意:自定义pipeline的优先级需高于Redispipeline,因为RedisPipeline不会返回item,所以如果RedisPipeline优先级高于自定义pipeline,那么自定义pipeline无法获取到item|                               |  6.执行爬虫--- scrapy crawl yy|  |      # 注意: 在原始scrapy项目的基础上,在settings.py文件中添加上述几行设置,就可以将scrapy爬取的数据存放到本机redis中|      # 注意: 上述要想成功保存到本机Redis,有两个前提:本机必须(pip install scrapy-redis) 和本机redis必须启动(redis-server /etc/redis.conf)|                               ---------------------------------------------------------------------------------------------------------------------------------------------------------------------4.Scrapy-Rdis-project: youyuan  (Scrapy-Redis分布式爬虫框架进阶3----有缘网:非分布式基于CrawlSpider的scrapy项目 ----> 改写为:RedisCrawlSpider类的Scrapy-Redis分布式爬虫项目 )---------------------------------------------------------------------------------------------------------------------------------------------------------------------|                               |      说明:仅仅实在原始scrapy项目的基础上对settings.py/yy.py文件进行的点滴修改即可|          youyaun/|          ├── scrapy.cfg|          └── youyaun|              ├── __init__.py|              ├── items.py|              ├── middlewares.py|              ├── pipelines.py|              ├── settings.py     <----对settings.py文件做部分添加修改(使用Scrapy-Redis的去重组件/调度器/取出请求策略/允许暂停/指明远程Redis主机,并注册RedisPipeline组件)|              └── spiders|                  ├── __init__.py|                  └── yy.py       <----对爬虫文件进行部分修改(引入RedisCrawlSpider爬虫类/去掉allowed_domain/去掉start_urls/增加redis_key/改写init方法动态获取限制域)|                               |  1.修改设置文件--- vim settings.py   |      vim settings.py|          DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"  # 使用Scrapy-Redis的去重组件,不再使用scrapy的去重组件|          SCHEDULER = "scrapy_redis.scheduler.Scheduler"              # 使用Scrapy-Redis的调度器,不再使用scrapy的调度器|          SCHEDULER_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"  # 使用Scrapy-Redis的从请求集合中取出请求的方式,三种方式择其一即可:|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderQueue"         # 分别按(1)请求的优先级/(2)队列FIFO/(3)栈FILO 取出请求|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderStack"|          SCHEDULER_PERSIST = True                                    # 允许暂停,redis请求记录不会丢失(重启爬虫不会重头爬取已爬过的页面)|  |          REDIS_HOST = "200.200.200.200"                              # 这两项是Redis连接设置,如果注释或不写会默认将数据存放到本机的Redis中|          REDIS_PORT = 6379                                           # 注意:master端的Redis需要允许远程连接--配置中注释掉bind 127.0.0.1         |                               |          #----------注册RedisPipeline/自定义pipeline------------------|          ITEM_PIPELINES = {|                  "youyuan.pipelines.YouyuanJsonPipeline":300,        # 自定义pipeline视情况选择性注册(可选)|                  "scrapy_redis.pipelines.RedisPipeline":400          # 将RedisPipeline注册到pipeline组件中(这样才能将数据存入Redis)|              }    # 注意:自定义pipeline的优先级需高于Redispipeline,因为RedisPipeline不会返回item,所以如果RedisPipeline优先级高于自定义pipeline,那么自定义pipeline无法获取到item|                               |  2.修改爬虫文件--- vim yy.py|      vim yy.py|          import scrapy|          from scrapy linkextractor import LinkExtractor|          from scrapy.Spiders import CrawlSpider,Rule|          from youyuan.items import YouyuanItem|          import re|          from scrapy_redis.Spiders import RedisCrawlSpider           # 变化1:从scrapy_redis.Spiders中引入RedisCrawlSpider|                               |          class YySpider(RedisCrawlSpider):                           # 变化2:爬虫类所继承的父类变为RedisCrawlSpider类|              name = "yy"|              redis_key = "yyspider:start_urls"                       # 变化3:多了一个对所有爬虫发号施令的redis_key,少了allowed_domain和start_urls|                               |              def __init__(self,*args,**kwargs):                      # 变化4:重写__init__方法:动态获取限制域|                  domain = kwargs.pop('domain','')|                  self.allowed_domain = filter(None,domain,split(','))|                  super(YySpider,self).__init__(*args,**kwargs)       # 注意super()里面的参数因爬虫类名不同而不同|                               |              page_links = LinkExtractor(allow=(r'youyuan.com/find/beijing/mm18-25/advance-0-0-0-0-0-0-0/p\d+/')) |              person_links = LinkExtractor(allow =(r'youyuan.com/\d+-profile/'))  |              .......|              .......      # 后面的代码都相同|                               |  3.爬虫的执行方式改变|          <1>将项目代码复制到给台slave上(可更改爬虫名)并启动爬虫--- scrapy runspider yy.py|          <2>在master端redis上发号施令--- lpush yyspider:start_urls http://www.youyuan.com/find/beijing/mm18-25/advance-0-0-0-0-0-0-0/p1/    |                                   ---------------------------------------------------------------------------------------------------------------------------------------------------------------------5.Scrapy-Rdis-project: sina2  (Scrapy-Redis分布式爬虫框架----新浪分类资讯:非分布式基于scrapy.Spider的scrapy项目 ----> 改写为:RedisSpider类的Scrapy-Redis分布式爬虫项目 )                              ---------------------------------------------------------------------------------------------------------------------------------------------------------------------|      改写该项目注意:由于改写后数据存放到Redis,所以需要去掉"目录存储路径"相关的代码|                               |  1.创建项目--- scrapy startproject sina2|          sina2/|          ├── scrapy.cfg|          └── sina2|              ├── __init__.py|              ├── items.py|              ├── middlewares.py|              ├── pipelines.py|              ├── settings.py     <----对settings.py文件做部分添加修改(使用Scrapy-Redis的去重组件/调度器/取出请求策略/允许暂停/指明远程Redis主机,并注册RedisPipeline组件)|              └── spiders|                  ├── __init__.py|                  └── xinlang.py  <----对爬虫文件进行部分修改(引入RedisCrawlSpider爬虫类/去掉allowed_domain/去掉start_urls/增加redis_key/改写init方法动态获取限制域)|                               |  2.明确目标--- vim items.py |      vim items.py|          import scrapy|  |          class SinaItem(scrapy.Item):|              parent_title = scrap.Field()       # 大类标题|              parent_url = scrap.Field()         # 大类URL|              sub_title = scrap.Field()          # 小类标题|              sub_url = scrap.Field()            # 小类URL|              #sub_filename = scrapy.Field()     # 小类目录存储路径(数据存放到Redis,不在需要这块代码)|              son_url = scrap.Field()            # 小类的子链接|              article_title = scrap.Field()      # 文章标题|              article_content = scrap.Field()    # 文章内容|                               |  3.制作爬虫|      (1)生成爬虫--- scrapy genspider xinlang "sina.com.cn"|      (2)设置爬虫--- vim xinlang.py|      vim xinlang.py|          import scrapy|          import os|          from sina.items import SinaItem|          import sys|          from scrapy_redis.Spiders import RedisSpider                 ###<-----变化1:从scrapy_redis.Spiders中引入RedisSpider|                               |          reload(sys)|          sys.setdefaultencoding('utf-8')|                               |          class XinlangSpider(RedisSpider):                            ###<-----变化2:爬虫类所继承的父类变为RedisSpider类|              name = 'xinlang'|              redis_key = "xinlangspider:start_urls"                   ###<-----变化3:多了一个对所有爬虫发号施令的redis_key,少了allowed_domain和start_urls|                               |              def __init__(self,*args,**kwargs):                       ###<-----变化4:重写__init__方法:动态获取限制域|                  domain = kwargs.pop('domain','')|                  self.allowed_domain = filter(None,domain,split(','))|                  super(XinlangSpider,self).__init__(*args,**kwargs)   # 注意super()里面的参数因爬虫类名不同而不同     |                                                   |              def parse(self,response):|                  items = []|                  parent_title_list = response.xpath('//div[@id=\"tab01\"]/div/h3/a/text()').extract()|                  parent_url_list = response.xpath('//div[@id=\"tab01\"]/div/h3/a/@href').extract()|                  sub_title_list = response.xpath('//div[@id=\"tab01\"]/div/ul/li/a/text()').extract()|                  sub_url_list = response.xpath('//div[@id=\"tab01\"]/div/ul/li/a/@href').extract()|                               |                  for i in range(0,len(parent_title_list)):   |                      #parent_filename = "./Data/" + parent_title_list[i]   # 创建大类的存放目录(若存在则不创建,若不存在则重新创建)|                      #if(not os.path.exists(parent_filename)):             # (数据存放到Redis,不在需要这块代码)|                      #   os.makedirs(parent_filename) |                               |                      for j in range(0,len(sub_url_list)):                          # 实例化SinaItem()并保存大类的URL和标题|                          item = SinaItem()|                          item['parent_title'] = parent_title_list[i]|                          item['parent_url'] = parent_url_list[i]|                          if_belong = sub_url_list[i].startwith(item['parent_url']) # 判断小类URL是否以大类URL开头(即判断小类是否属于大类)|                          if (if_belong):                                             |                              #sub_filename = parent_filename + "/" + sub_title_list[j]   # 如果属于该大类,则判断小类存放目录是否存在,不存在则新建该目录|                              #if (not os.path.exists(sub_filename)):                     # (数据存放到Redis,不在需要这块代码)|                              #   os.makedirs(sub_filename)|                              item['sub_title'] = sub_title_list[j]       # 保存小类的标题/URL/存放目录,并将目前所获取item信息追加到items列表中保存|                              item['sub_url'] = sub_url_list[j]|                              item['sub_filename'] = sub_filename|                              items.append(item)|                  for item in items:              # 逐一取出子类的url,并附带上meta信息(即item),将其加入请求队列,使用second_parse()函数处理其返回的响应|                      yield scrapy.Request(url=item['sub_url'],meta={'meta_1':item},callback=self.second_parse)|                               |              def second_parse(self,response):|                  meta_1 = response.meta['meta_1']                      # 将meta对应的item信息赋值给meta_1(即,meta_1 = item)|                  son_url_list = response.xpath('//a/@href').extract()  # 匹配获取返回的孙类的URL列表|                  items = []|                  for i in range(0,len(son_url_list)):    # 循环取出孙类URL判断其是否属于某个大类(以大类的URL开头)和是否是文章(以.shml结尾),如果属于则将该孙类URL保存起来|                      if_belong = son_url_list[i].endwith('.shtml') and sub_url_list[i].startwith(meta_1['parent_url'])|                      if (if_belong):|                          item = SinaItem()|                          item['parent_title'] = meta_1['parent_title']|                          item['parent_url'] = meta_1['parent_url']|                          item['sub_title'] = meta_1['sub_title']|                          item['sub_url'] = meta_1['sub_url']|                          #item['sub_filename'] = meta_1['sub_filename']  # (数据存放到Redis,不在需要这块代码)|                          item['son_url'] = son_url_list[i]|                          items.append(item)|                  for item in items:              # 逐一取出孙类的url,并附带上meta信息(即第二次的item),将其加入请求队列,使用third_parse()函数处理其返回的响应|                      yield scrapy.Request(url=item['son_url'],meta={'meta_2':item},callback=self.third_parse)|                               |              def third_parse(self,response):|                  item = response.meta['meta_2']  # 将meta对应的(第二次获取更新的item信息)赋值给这里的item(即,item = item)|                  article_content = ""            # 从孙类URL返回响应中匹配出文章标题和文章内容并保存进item|                  article_title_list = response.xpath('//hi[@id=\"main_title\"]/text()').extract()|                  article_content_list = response.xpath('//div[@id=\"artibody\"]/p/text()').extract()|                  for content_part in article_content_list:|                      article_content += content_part               # 通过循环拼接成完整的文章内容|                  item['article_title'] = article_title_list[0]|                  item['article_content'] = article_content|                  yield item                                        # 将数据收集完整的item传递给pipeline处理|                               |  4.编写item pipelines--- vim pipelines.py (忽略)  # (数据存放到Redis,不再需要这块代码,不需要自定义pipeline保存数据到本地)|                               |  5.启用上述pipeline组件--- vim settings.py|      vim settings.py|          DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"  # 使用Scrapy-Redis的去重组件,不再使用scrapy的去重组件|          SCHEDULER = "scrapy_redis.scheduler.Scheduler"              # 使用Scrapy-Redis的调度器,不再使用scrapy的调度器|          SCHEDULER_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"  # 使用Scrapy-Redis的从请求集合中取出请求的方式,三种方式择其一即可:|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderQueue"         # 分别按(1)请求的优先级/(2)队列FIFO/(3)栈FILO 取出请求|          #SCHEDULER_CLASS = "scrapy_redis.queue.SpiderStack"|          SCHEDULER_PERSIST = True                                    # 允许暂停,redis请求记录不会丢失(重启爬虫不会重头爬取已爬过的页面)|                               |          REDIS_HOST = "200.200.200.200"                              # 这两项是Redis连接设置,如果注释或不写会默认将数据存放到本机的Redis中|          REDIS_PORT = 6379                                           # 注意:master端的Redis需要允许远程连接--配置中注释掉bind 127.0.0.1         |                               |          ITEM_PIPELINES = {  #"sina.pipelines.SinaSavePipeline":300,     # (数据存放到Redis,不再需要这块代码,不需要自定义pipeline保存数据到本地)|                              "scrapy_redis.pipelines.RedisPipeline":400  # 将RedisPipeline注册到pipeline组件中(这样才能将数据存入Redis)|                          }|                               |  6.爬虫的执行方式改变|          <1>将项目代码复制到给台slave上(可更改爬虫名)并启动爬虫--- scrapy runspider xinlang.py|          <2>在master端redis上发号施令--- lpush yyspider:start_urls http://news.sina.com.cn/guide/   |                               ---------------------------------------------------------------------------------------------------------------------------------------------------------------------6.Scrapy-Rdis-project: youyuan  (Scrapy-Redis分布式爬虫框架----将Redis中数据持久化存储到MongoDB/MySQL中----> 将有缘网分布式爬取到Redis中的数据转存到MongoDB/MySQL中)---------------------------------------------------------------------------------------------------------------------------------------------------------------------|                               |  要将Scrapy-Redis项目爬取到Redis中的数据转存到Mongodb/MySQL中,只需要在项目一级目录下创建两个转存的脚本文件即可|                               |  有缘网Scrapy-Redis项目树形图|          youyuan/|          ├── scrapy.cfg|          ├── process_item_for_mongodb.py     <----项目一级目录下创建将Redis数据转存到mongodb的python脚本|          ├── process_item_for_mysql.py       <----项目一级目录下创建将Redis数据转存到mysql的python脚本|          └── youyuan|              ├── __init__.py|              ├── items.py|              ├── middlewares.py|              ├── pipelines.py|              ├── settings.py |              └── spiders|                  ├── __init__.py|                  └── yy.py   |                               |                               |  1.将Redis数据转存到mongodb中 ----- vim process_item_for_mongodb.py|      vim process_item_for_mongodb.py|          #!/usr/bin/env python|          #coding:utf-8|                               |          import redis|          import pymongo|          import json|          def process_item():|              rediscli = redis.Redis(host='200.200.200.200',port=6379,db=0)       # 创建Redis连接对象|              mongocli = pymongo.MongoClient(host='200.200.200.202',port=27017)   # 创建MongoDB连接对象|              db_name = mongocli['youyuan']                                       # 利用MongoDB连接对象在MongoDB中创建名为youyuan的数据库对象|              sheet_name = db_name['beijing18-24']                                # 利用该数据库对象在youyuan数据库中创建名为beijing18-24的表对象|              count = 0 |              while True:|                  source,data = rediscli.blpop("yy:items")                        # 使用循环通过redis连接对象的blpop()方法,不断取出redis中的数据(blpop即FIFO,rlpop即FILO)|                  data = json.loads(data)                                         # 将取出的json字符串类型的数据转化为python类型的对象|                  sheet_name.insert(data)                                         # 利用mongodb的表对象的insert()方法,向表中插入(刚才转化的python对象)|                  count += 1|                  print "已经成功从redis转移" + str(count) + "条数据到mongodb"|                               |          if __name__ == "__main__":|              process_item()|  |  注意:MongoDB中可以自动创建键,所以直接执行该脚本就可转移数据|                               |                               |  2.将Redis数据转存到mysql中 ----- vim process_item_for_mysql.py|      vim process_item_for_mysql.py|          import redis|          import MySQLdb|          import json|          def process_item():|              rediscli = redis.Redis(host='200.200.200.200',port=6379,db=0)                                               # 创建Redis连接对象|              mysqlcli = MySQLdb.connect(host='200.200.200.204',port 3306,db='youyuan',user='zhangsan',password='123456') # 创建MySQL连接对象|              count = 0|              while True:|                  source,data = rediscli.blpop('yy:items')            # 使用循环通过redis连接对象的blpop()方法,不断取出redis中的数据(blpop即FIFO,rlpop即FILO)|                  data = json.loads(data)                             # 将取出的json字符串类型的数据转化为python类型的对象|                  try:|                      cursor = mysqlcli.cursor()                      # 利用mysql连接对象创建cursor操作游标,并使用该操作游标向Mysql表中插入数据,数据通过python对象获取其值|                      cursor.execute("insert into beijing18-24 (username,age,spider,crawled) values(%s,%s,%s,%s)",[data['username'],data['age'],data['spider'],data['crawled']])|                      mysqlcli.commit()                               # 插入完成后需提交事务|                      cursor.close()                                  # 关闭操作游标|                      count += 1|                      print "已经成功从redis转移" + str(count) + "条数据到mongodb"|                  except:|                      pass|                               |          if __name__ == "__main__":|              process_item()|  |  注意:MySQL中不能自动创建字段,所以在执行该脚本前,需要自行在数据库中创建好响应的数据库/表/字段,然后才能执行该脚本,转移数据到MySQL中|  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------

来源:https://www.cnblogs.com/psv-fuyang/articles/7891897.html

[235]scrapy分布式爬虫scrapy-redis(二)相关推荐

  1. Scrapy分布式爬虫打造搜索引擎 - (三)知乎网问题和答案爬取

    Python分布式爬虫打造搜索引擎 基于Scrapy.Redis.elasticsearch和django打造一个完整的搜索引擎网站 推荐前往我的个人博客进行阅读:http://blog.mtiany ...

  2. scrapy分布式爬虫案例

    关于 Redis Redis 是目前公认的速度最快的基于内存的键值对数据库 Redis 作为临时数据的缓存区,可以充分利用内存的高速读写能力大大提高爬虫爬取效率. 关于 scrapy-redis sc ...

  3. python分布式爬虫框架_python之简单Scrapy分布式爬虫的实现

    分布式爬虫:爬虫共用同一个爬虫程序,即把同一个爬虫程序同时部署到多台电脑上运行,这样可以提高爬虫速度. 在默认情况下,scrapy爬虫是单机爬虫,只能在一台电脑上运行,因为爬虫调度器当中的队列queu ...

  4. scrapy 分布式爬虫- RedisSpider

    scrapy 分布式爬虫- RedisSpider 爬去当当书籍信息 多台机器同时爬取,共用一个redis记录 scrapy_redis 带爬取的request对象储存在redis中,每台机器读取re ...

  5. scrapy分布式爬虫原理(scrapy_redis)

    scrapy分布式爬虫及scrapy_redis 分布式原理 scrapy--redis实现分布式 scrapy_redis源码 分布式原理 在学习完scrapy基本知识后,大多数爬虫应用了scrap ...

  6. Python面试必备—分布式爬虫scrapy+redis解析

    传智播客博学谷 微信号:boxuegu- get最新最全的IT技能 免费领取各种视频资料 注意:文末送书 很多小伙伴留言,最近准备跳槽,但是面试的机会比较少,好不容易得到面试机会,由于技术点的匮乏,面 ...

  7. scrapy分布式爬虫爬取淘车网

    一.master主机配置 1.开启redis服务器 2.city.py#文件 # 城市编码 CITY_CODE = ['shijiazhuang', 'tangshan', 'qinhuangdao' ...

  8. 基于Scrapy分布式爬虫的开发与设计

    个人博客请访问http://blog.xhzyxed.cn 这个项目也是初窥python爬虫的一个项目,也是我的毕业设计,当时选题的时候,发现大多数人选择的都是网站类,实在是普通不过了,都是一些简单的 ...

  9. python爬虫-初步使用Scrapy分布式爬虫(爬取mcbbs整合包保存名称及主要mod),大爱MC

    首先介绍一下scrapy. Scrapy一个开源和协作的框架,是为了页面抓取所设计的,使用它可以快速.简单.可扩展(通过中间件)的方式从网站中提取所需的数据. 工作流程如下 Scrapy Engine ...

最新文章

  1. 关于素数常用结论--威尔逊定理、欧拉定理、费马小定理、米勒罗宾算法
  2. 人脸识别争议再起 实际应用利弊几何?
  3. 记录一下添加查询场地坐标功能中修改判断条件和画点的大小
  4. 关于程序员能做什么副业,相关文章用机器学习算法分析
  5. Android中的复制粘贴
  6. epoll哪些触发模式_网络编程:epoll
  7. 应届生是这辈子最大的一次优势,也是最后一次!
  8. 项目中用到的语音识别方案 硬件/软件相关介绍
  9. 福建师范大学计算机组成原理期末试卷,福建师范大学2020年8月课程考试《计算机组成原理》作业考核试题...
  10. 字节面试官:如何实现Ajax并发请求控制
  11. python教学视频r_R Tutorial
  12. 非985,计算机专业的大学生该如何自学编程?
  13. Linux使用 tar命令-g参数进行增量+差异备份、还原文件
  14. Python|十五个超级炫酷的代码
  15. 电商项目5:商品模块
  16. 数据库完整性详细解释
  17. 让老照片重现光彩(三):完整论文的中文译文
  18. 我的世界服务器防挂机系统指令,我的世界反作弊和防飞行指令分享
  19. 解决方案:macOS Mojave下Pycharm运行pygame无法加载外星人游戏图片以及无法修改颜色
  20. 马克思逝世140周年纪念|朋友一生一起走!马克思与恩格斯之间的感情有多深?...

热门文章

  1. WPF 第三方控件主题库
  2. 小程序 · 手机号码中间四位隐藏
  3. 程序员长见识需要关注的牛人
  4. 抽奖程序(python)
  5. iOS】AVPlayer 播放音视频
  6. android 使用volley下载文件和加载gif图片
  7. exec 和 exec_
  8. injectcheck php_PHP安全最大化
  9. airpods版本号_airpods蓝牙版本是多少,苹果AirPods正式版使用评测
  10. Spring Boot (Filter)过滤器的实现以及使用场景