• scrapy通过多线程+异步大大提高了爬取效率,但是他本质上还是单进程,还是不够快,而scrapy-redis在scrapy的基础上解决了这个问题,scrapy-redis最核心的目的就是通过多台从机突破了我们的带宽限制,提高了效率,这种类似于多进程的思想,这里的多进程其实是多台电脑,如下图
    -在这里插入图片描述

步骤

一、服务主机的配置
  • 1 修改redis-server配置,允许远程访问以及设置密码,在redis配置文件中修改
bind 0.0.0.0
requirepass 123456 
  • 2 有终端需要向redis发布任务,新建push_task.py文件
import requests
from lxml import etree
from redis.client import Redis
import time,random

page = 0
# 因为这里连接的是本地数据库,而且Redis()有默认参数,所以我们不需要传递参数
# host='localhost', port=6379,db=0, password=None, socket_timeout=None,
redis_server = Redis()

while True:
    url = f"http://wz.sun0769.com/index.php/question/reply?page={page}"
    page += 30
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
    }
    # time.sleep(random.randint(10,30)/10)
    html_str = requests.get(url,headers=headers).content.decode("gbk")
    root = etree.HTML(html_str)
    href_list = root.xpath("//table[2]/tr/td[3]/a[1]/@href")
    for href in href_list:
        redis_server.lpush("sunSpider:start_urls",href)
    print("当前插入任务数量:",page)
    # if page==120:
    #     break
    
二、分布式多个从机的配置
  • 1 scrapy startproject sun 创建scrapy项目
  • 2 修改items.py
class SunItem(scrapy.Item):
   # define the fields for your item here like:
   # name = scrapy.Field()
   title = scrapy.Field()
  • 3创建爬虫模块
 cd sun
 scrapy genspider sunSpider temp
  • 4 修改sunSpider.py(注意redis_key名字不能改)
# -*- coding: utf-8 -*-
import scrapy

from scrapy_redis.spiders import RedisSpider
from ..items import SunItem

class SunspiderSpider(RedisSpider):

   name = 'sunSpider'
   redis_key = "sunSpider:start_urls"

   def parse(self, response):
       item = SunItem()
       try:
           title = response.xpath('//span[@class="niae2_top"]/text()')
           item["title"] = title.extract()[0]
       except Exception as e:
           item["title"] = "异常数据"
       print("投诉标题 :",title)
       yield item

  • 5 在setting.py中修改配置
#主机名
REDIS_HOST = "192.168.14.16"
#端口号
REDIS_PORT = 6379
#参数列表
REDIS_PARAMS = {"password":"",}

#走redis的数据处理管道
ITEM_PIPELINES = {
    'sun.pipelines.SunPipeline': 300,
    #使用mongo存储,不使用scrapy-redis自带的管道组件
   'scrapy_redis.pipelines.RedisPipeline': 400,
}
#去重组件设置
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
#调度器组件设置
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#持久化储存
SCHEDULER_PERSIST = True
#延迟
DOWNLOAD_DELAY = 1
#编码
REDIS_ENCODING = "utf-8"
  • 6 开始测试
    1 从机新建run.py
from scrapy import cmdline

name = "sunSpider"
cmd = "scrapy crawl {0}".format(name)
cmdline.execute(cmd.split())

2 主机启动push_task.py进行发任务,在多个从机上运行run.py消费任务,此时redis相当于一个MQ消息队列,这个流程类似于消费者模型,跟多进程之间使用Queue进行通信也比较类似,当redis中任务被消费完毕,从机上的爬虫会进入阻塞状态,等待消息队列中补充任务后继续执行

三、运行结果

在这里插入图片描述

Logo

鸿蒙生态一站式服务平台。

更多推荐