Scrapy-redis组件,实现分布式爬虫

安装包

pip install -U scrapy-redis

settings.py

##### Scrapy-Redis  #####
### Scrapy指定Redis 配置  ###
# 其他默认配置在scrapy_redis.default.py中。
# 指定redis类对象,如果你的是redis集群就要改一下。
# REDIS_CLS = redis.RedisCluster

# 看了一下源码,发现要通过这种方式才能指定redis集群的各个IP
# 当然了,你只指定集群中任意一个HOST、PORT也行(这时候就只要REDIS_HOST和REDIS_PORT即可,这点你看看源码就知道了..),因为集群会自动找响应的主机。

# 定义redis集群的Node节点信息
# 注意不一定要全部集群的节点信息都放在这里,因为RedisCluster只要求集群中其中一个节点即可!
# REDIS_CLUSTER_NODES = [
#     {"host": "192.168.2.6", "port": 6379},
#     {"host": "192.168.2.6", "port": 6380},
#     {"host": "192.168.2.6", "port": 6381},
#     {"host": "192.168.2.6", "port": 6382},
#     {"host": "192.168.2.6", "port": 6383},
#     {"host": "192.168.2.6", "port": 6384},
# ]
# nodes = []
# for node in REDIS_CLUSTER_NODES:
#     nodes.append(ClusterNode(node["host"], node["port"]))
#
# REDIS_PARAMS = {
#     'startup_nodes': nodes,
# }
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# REDIS_URL = "redis://127.0.0.1:6379"  # 用这种方式也行.
# REDIS_DECODE_RESPONSES = True
# REDIS_DB
# REDIS_ENCODING

# 启用Rides调度存储请求队列
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# 不清除Redis队列、这样可以暂停/恢复 爬取
SCHEDULER_PERSIST = True

# 如果为True,则使用redis的'spop'进行操作。
# 如果需要避免起始网址列表出现重复,这个选项非常有用。开启此选项urls必须通过sadd添加,否则会出现类型错误。
REDIS_START_URLS_AS_SET = False

# 定义指纹去重过滤的类
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# scrapy-redis对于请求的处理的调度有各种队列,如先进先出,后进先出,优先级队列(默认)
# 使用优先级调度请求队列 ["scrapy_redis.queue.SpiderQueue" 此项是先入先出队列]
# SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"

爬虫类:(一般只需要将继承类修改为Scrapy-redis提供的爬虫类即可)

import time

import scrapy
from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy_redis.spiders import RedisCrawlSpider

from zolwallpaper.items import Bang123Item
from scrapy_redis.dupefilter import RFPDupeFilter

# 将继承的类修改为RedisCrawlSpider、或者RedisSpider(看你的业务需求)
# class Bang123Spider(CrawlSpider):
**class Bang123Spider(RedisCrawlSpider):**
    name = "bang123"
    allowed_domains = ["bang123.cn"]
    **# 使用scrapy-redis后就不需要指定start_urls,而是定义redis_key,在这个key里面将url地址push进去列表中,让多台机器tongshidu
    # start_urls = ["https://www.bang123.cn/"]**

    # 定义在redis启动的urls的key名,如果不设置,则默认为爬虫的名字+:start_urls,
    # 比如Bang123Spider爬虫类的这里的name="bang123",那么也会组成bang123:start_urls,这些可以自己看源码。
    # redis_key = "bang123:start_urls"

    rules = (
        # 翻页
        Rule(LinkExtractor(allow=r"https://www.bang123.cn/index_\d+.html"), follow=True),
        # 详情页
        Rule(LinkExtractor(allow=r"https://www.bang123.cn/gongshi/\d+.html"), callback="parse_item", follow=False),
    )

    def parse_item(self, response: HtmlResponse):

        bang_item = Bang123Item()

        selector = response.xpath('//div[@class="article_content layui-field-box"]')[0]
        title = selector.xpath('./h1/text()').get()

        main = response.xpath('//div[@class="content tindent of_table"]/p').getall()

        bang_item["title"] = title
        bang_item["main"] = main

        print(f"【{title=}】")
        print(f"{main=}")
        print("-"*150)

        yield bang_item

启动爬虫:

scrapy crawl bang123

手动添加start_urls:

redis-cli>
# 这里key名字是你在爬虫类中定义的redis_key的值
redis-cli>lpush bang123:start_urls https://www.bang123.cn/

为什么需要手动添加呢?

1、因为我们这个是CrawlSpider,是根据Rule自动找链接的,所以我们需要先手动给他一个链接。

这个在官方文档也有写:https://github.com/rmax/scrapy-redis/wiki/Feeding-a-Spider-from-Redis

当然了,你也可以写两个爬虫,一个爬虫负责获取分页中每个项目的url,并发送到redis-key对应的start_urls中。
另外一个爬虫则负责爬取详情页,这种方法也可以。
posted @ 2023-07-17 11:40  蕝戀  阅读(30)  评论(0编辑  收藏  举报