通常我们在使用 Scrapy-redis 的时候初始请求是 Get 的情况下,我们可以通过重写 start_requests 方法来实现请求需求。但是如果我们要发送的是 post 请求,就不能简单的用上面的方法了。

scrapy-redis 源码阅读

scrapy 发送 POST 肯定没问题(重写 start_requests 方法即可),但 scrapy-redis 不同,scrapy-redis 框架只会从配置好的 redis 数据库中读取起始 url,所以,在 scrapy-redis 中,就算重写 start_requests 方法也没用。怎么办呢?我们看看源码。

我们发现 RedisSpider 继承了 RedisMixin 所以我们跟进 RedisMixin

start_requests 开始分析, 直接把所有任务丢给 next_requests 方法
上面 next_requests 方法中,关键的就是那个 while 循环,每一次循环都调用了一个 make_request_from_data 方法,从函数名可以函数,这个方法就是根据从 redis 中读取从来的数据,实例化一个 request,那不就是我们要找的方法吗?

重写 make_request_from_data

from scrapy import FormRequest
from scrapy_redis.spiders import RedisSpider
 
 
class MeituanSpider(RedisSpider):
    """类似 start_requests""" 
    def make_request_from_data(self, data):
        """
        重写make_request_from_data方法,data是scrapy-redis读取redis中的[url,form_data,meta],然后发送post请求
        :param data: redis中都去的请求数据,是一个list
        :return: 一个FormRequest对象
      """
        data = json.loads(data)
        url = data.get('url')
        form_data = data.get('form_data')
        meta = data.get('meta')
        return FormRequest(url=url, formdata=form_data, meta=meta, callback=self.parse)

    def parse(self, response):
        pass

编写推入redis 程序

import redis
import json

"""decode_responses 写存的数据是字符串形式"""
r = redis.Redis()  # 默认db=0


def push_start_url_data(request_data):
    """
    将一个完整的request_data推送到redis的start_url列表中
    :param request_data: {'url':url, 'form_data':form_data, 'meta':meta}
    :return:
    """
    r.lpush('XX:start_urls', request_data)


if __name__ == '__main__':
    url = 'http://www.xxx.com'
    form_data = {
        "sourceType": "A"
    }
    meta = {
        'search_key': '91650100MA786PE4XT',
        '_id': '5f45b7eaeb898de3b4cafe34'
    }
    request_data = {
        'url': url,
        'form_data': form_data,
        'meta': meta
    }
    push_start_url_data(json.dumps(request_data))

总结

redis-scrapy 开启后会阻塞等待 redis 请求需求推入,然后读取任务爬取, 如果用post的方法, 只需要重写 make_request_from_data 即可
Last modification:September 29, 2020
如果觉得我的文章对你有用,请随意赞赏