- 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中任务被消费完毕,从机上的爬虫会进入阻塞状态,等待消息队列中补充任务后继续执行