You need to enable JavaScript to run this app. 如何使用Scrapy应用筛选条件过滤爬取的搜索结果?
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Scrapy应用筛选条件过滤爬取的搜索结果?

核心问题根因

这个站点基于JSF + PrimeFaces组件库开发,目前筛选条件不生效的原因有三个:

  • 硬编码的j_idtxxx类组件id是页面每次加载时随机生成的动态值,刷新页面id就会变化,提交的参数名根本匹配不上真实的表单元素,后端无法识别对应的筛选字段
  • PrimeFaces的交互逻辑和普通HTML表单存在差异,仅传递输入框的_input值无法通过框架校验规则,加上缺少JSF强制要求的视图状态隐藏参数,请求会被后端判定为非法,不会返回带筛选条件的结果
  • 爬取数据时仅选择了.ui-datatable-odd类的奇数行,即便筛选生效,也会漏掉一半的表格数据
正确实现思路
  1. 彻底放弃硬编码动态组件id,通过元素固定的id后缀(比如date1_input、powerPlant_input这类固定写在组件里的后缀)从响应中匹配真实的元素id,作为FormRequest的参数键,适配每次页面的动态id变化
  2. 提交请求时不要剔除FormRequest.from_response自动携带的JSF隐藏字段(比如视图状态参数),保证请求能通过后端的会话校验
  3. 必须把查询按钮的标识参数一并提交,告诉后端要执行查询逻辑、刷新表格区域——PrimeFaces的表单不会自动根据输入值变化触发查询,必须收到按钮点击的信号才会处理筛选
参考修正后的代码
from scrapy.http import FormRequest
from ..items import EpiasscrapingItem

class EpiasSpider(scrapy.Spider):
    name = 'epias'
    start_urls =[
        'https://seffaflik.epias.com.tr/transparency/uretim/gerceklesen-uretim/gercek-zamanli-uretim.xhtml'
    ]

    def parse(self, response):
        # 动态提取固定后缀的真实组件id,替代硬编码的动态j_idt值
        date1_input_id = response.xpath('//input[contains(@id, "date1_input")]/@id').get()
        date2_input_id = response.xpath('//input[contains(@id, "date2_input")]/@id').get()
        plant_input_id = response.xpath('//input[contains(@id, "powerPlant_input")]/@id').get()
        # 定位查询按钮的真实id
        search_btn_id = response.xpath('//button[contains(@id, "search") or contains(normalize-space(.), "查询")]/@id').get()

        # 构造筛选参数,键全部用动态提取的真实元素id
        formdata = {
            date1_input_id: '20.03.2021',
            date2_input_id: '20.03.2021',
            plant_input_id: '2614',
            search_btn_id: search_btn_id  # 显式触发查询按钮动作
        }

        return FormRequest.from_response(
            response,
            formdata=formdata,
            callback=self.start_scraping,
            headers={
                'X-Requested-With': 'XMLHttpRequest' # 匹配PrimeFaces AJAX请求的特征
            }
        )

    def start_scraping(self,response):
        items = EpiasscrapingItem()
        # 修正选择器:抓取所有表格行,不再只抓奇数行
        table_epias = response.css('.ui-datatable tbody tr')

        for epias in table_epias:
            # 跳过空的表头/占位行
            if len(epias.css('td')) < 15:
                continue
            date = epias.css('td:nth-child(1)::text').get().strip()
            time = epias.css('td:nth-child(2)::text').get().strip()
            biogas = epias.css('td:nth-child(15)::text').get().strip()

            items['date'] = date 
            items['time'] = time 
            items['biogas'] = biogas 

            yield items
补充排查技巧
  • 如果提交后还是没生效,就在浏览器里手动操作一次完整的筛选流程,打开开发者工具的网络面板,找到筛选时发出的POST请求,对照真实请求的参数列表,把PrimeFaces要求的专属参数(比如指定刷新区域的javax.faces.partial.render参数)补充到formdata里
  • 电厂选择组件是带自动补全的下拉控件,如果传的电厂ID值和前端存储的选项值不匹配,也会导致筛选失效,可以对照网络请求里的电厂字段真实值调整参数

内容的提问来源于stack exchange,提问作者Fatma A.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 13:24:03