You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scrapy POST爬取多页 不同serial参数批量爬取实现方法

全量数据爬取实现方法

整体流程分为两个阶段,先拿全所有有效serial参数,再批量构造详情页请求:

  • 第一阶段:访问列表页,逐页提取页面中嵌入的所有详情页对应serial值,处理完所有列表分页
  • 第二阶段:遍历去重后的serial集合,逐个构造POST请求抓取详情页内容

具体代码修改

  1. 初始请求不要直接写死参数请求详情接口,改为先访问列表页,由浏览器自动维护有效Cookie,避免硬编码Cookie过期失效
  2. 新增列表页解析逻辑,从页面DOM中提取serial:这类站点的serial一般存放在详情提交按钮所在表单的隐藏域、按钮自定义属性或者跳转链接参数中,根据实际DOM结构写XPath提取即可
  3. 处理列表分页逻辑,抓全所有分页的serial后再批量发起详情请求
  4. 用urlencode构造POST请求体,避免手动拼接字符串出现编码错误

改完的完整参考代码如下:

import scrapy
from urllib.parse import urlencode
from scrapy_selenium import SeleniumRequest


class TestSpider(scrapy.Spider):
    name = 'test'
    list_url = "https://www.benrishi-navi.com/english/english1_2.php"
    detail_url = "https://www.benrishi-navi.com/english/english1_3.php"
    
    # 存储已爬取的serial,避免重复请求
    seen_serial = set()

    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8,pt;q=0.7',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Origin': 'https://www.benrishi-navi.com',
        'Referer': 'https://www.benrishi-navi.com/english/english1_2.php',
        'Sec-Fetch-Dest': 'document',
        'Sec-Fetch-Mode': 'navigate',
        'Sec-Fetch-Site': 'same-origin',
        'Sec-Fetch-User': '?1',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
        'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"'
    }

    def start_requests(self):
        # 先访问列表页,自动获取站点下发的有效Cookie
        yield SeleniumRequest(
            url=self.list_url,
            wait_time=2,
            headers=self.headers,
            callback=self.parse_list,
            dont_filter=True,
        )

    def parse_list(self, response):
        # 提取当前页所有serial,示例XPath针对serial存于表单隐藏域的场景,可根据实际DOM结构调整
        serial_list = response.xpath("//form[contains(@action,'english1_3.php')]//input[@name='serial']/@value").getall()
        for serial in serial_list:
            if serial not in self.seen_serial:
                self.seen_serial.add(serial)
                # 构造详情页POST请求
                payload = urlencode({
                    'serial': serial,
                    'office_serial': '',
                    'submit2': 'Details'
                })
                yield SeleniumRequest(
                    url=self.detail_url,
                    method='POST',
                    body=payload,
                    wait_time=2,
                    headers=self.headers,
                    callback=self.parse_detail,
                    dont_filter=True,
                )
        
        # 处理列表分页,提取下一页地址,存在则继续爬取下一页内容
        next_page = response.xpath("//a[contains(text(),'Next')]/@href").get()
        if next_page:
            yield SeleniumRequest(
                url=response.urljoin(next_page),
                wait_time=2,
                headers=self.headers,
                callback=self.parse_list,
                dont_filter=True,
            )

    def parse_detail(self, response):
        # 解析详情页数据
        item = {}
        item['title'] = response.xpath("//td[@class='kiso']//text()").getall()
        # 其余字段按业务需求补充提取逻辑
        yield item

注意事项

  • 提取serial的XPath需要和实际页面对应,如果Details按钮是通过onclick事件传参跳转,对应调整XPath从onclick属性值中提取serial数值即可
  • 如果站点对请求频率有限制,可以适当调大SeleniumRequest的wait_time参数,或者在配置中设置DOWNLOAD_DELAY降低并发,避免被拦截
  • 不需要硬编码Cookie值,Selenium启动浏览器访问列表页时会自动生成并携带站点下发的有效Cookie,写死的Cookie过有效期后会直接导致请求失败

内容的提问来源于stack exchange,提问作者Amen Aziz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:09:38