Python中如何使用scrapy-redis实现POST请求

scrapy 可以通过重写 start_requests 方法实现 post 请求,请问 scrapy-redis 如何实现
Python中如何使用scrapy-redis实现POST请求

5 回复

FormRequest 不起作用吗


在Scrapy中使用scrapy-redis实现POST请求,核心是正确配置请求的methodbody参数,并确保Redis调度器和去重器正常工作。scrapy-redis本身不改变请求的构造方式,它主要负责分布式调度和去重。

下面是一个完整的Spider示例,演示如何发送POST请求:

import scrapy
import json
from scrapy_redis.spiders import RedisSpider

class MyPostSpider(RedisSpider):
    name = 'post_spider'
    redis_key = 'myspider:start_urls'  # 从Redis列表读取起始URL或请求
    
    def make_request_from_data(self, data):
        """
        重写此方法,用于从Redis中读取的数据构造请求。
        data是从redis_key列表中pop出来的字节串。
        这里我们假设data是JSON格式,包含构造POST请求所需的信息。
        """
        item = json.loads(data.decode('utf-8'))
        # 构造FormData格式的POST请求
        return scrapy.FormRequest(
            url=item['url'],
            formdata=item['form_data'],  # 字典形式的表单数据
            callback=self.parse_response
        )
    
    def parse_response(self, response):
        # 处理响应
        yield {
            'url': response.url,
            'status': response.status,
            'body': response.text[:200]  # 只取前200字符示例
        }

# 更常见的做法:在start_requests中直接构造POST请求
class MyPostSpider2(RedisSpider):
    name = 'post_spider2'
    redis_key = 'myspider:start_urls'
    
    def make_request_from_data(self, data):
        """
        另一种方式:发送JSON格式的POST请求
        """
        item = json.loads(data.decode('utf-8'))
        return scrapy.Request(
            url=item['url'],
            method='POST',
            body=json.dumps(item['payload']),  # JSON字符串作为请求体
            headers={'Content-Type': 'application/json'},
            callback=self.parse_response
        )
    
    def parse_response(self, response):
        yield {'result': response.json()}

# 如果你需要固定的POST请求,可以在start_requests中定义:
class MyPostSpider3(RedisSpider):
    name = 'post_spider3'
    
    def start_requests(self):
        # 即使使用scrapy-redis,也可以在这里定义初始请求
        yield scrapy.FormRequest(
            url='https://httpbin.org/post',
            formdata={'key1': 'value1', 'key2': 'value2'},
            callback=self.parse
        )
    
    def parse(self, response):
        yield {'form_data': response.json()['form']}

关键点:

  1. 请求构造:使用scrapy.FormRequest发送表单格式的POST,或使用scrapy.Request并指定method='POST'body参数。
  2. 数据格式:JSON请求需要设置Content-Type: application/json头。
  3. Redis集成make_request_from_data方法让你可以从Redis队列中动态构造请求。
  4. 配置settings.py
# 启用scrapy-redis调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
REDIS_URL = 'redis://localhost:6379/0'

# 保持Redis队列,允许暂停/恢复
SCHEDULER_PERSIST = True

向Redis队列添加任务:

import redis
import json

r = redis.Redis(host='localhost', port=6379, db=0)
# 添加一个POST任务
task = {
    'url': 'https://httpbin.org/post',
    'form_data': {'username': 'test', 'password': 'secret'}
}
r.lpush('myspider:start_urls', json.dumps(task))

总结:构造POST请求的关键在于正确使用FormRequest或Request的body参数。

data = {
‘username’: ‘user’,
‘password’: ‘pwd’
}

req = scrapy.Request(url=url, method=‘POST’,
body=data,
headers=self.headers)

楼主说的是用 scrapy-redis 时,怎么发 POST 请求,最近遇到这个问题,已经解决😊

我也解决了,开心

回到顶部