筛选操作不更新URL时的网页爬取与ID提取方案咨询
动态筛选页面爬取实现方案
URL提交筛选后不更新,是因为站点用POST方式传递筛选参数,参数放在请求体里而非URL后缀,不需要构造带参URL,按下面两种方案实现即可。
方案1:直接模拟表单POST请求(效率最高,优先选用)
不需要启动浏览器,速度快资源占用低,适合大规模爬取:
- 打开浏览器开发者工具,切换到Network面板,手动执行一遍完整筛选操作,找到点击
Apply Search时发送到search.php的POST请求 - 从请求的Form Data里提取所有提交参数,只需要修改两个筛选相关的字段:
- Saint选项对应的参数:选中Saint时记录对应键值对即可
- 出生/埋葬区域参数:从你贴的源码可以确认,下拉框name为
form[item_89],Gaul and Frankish kingdoms对应的value是Gaul,直接给该字段传Gaul
- 注意要把表单里的隐藏字段(比如csrf校验值、提交按钮字段)一并带上,请求头里补全和浏览器一致的
User-Agent、Referer,绕过基础的来源校验 - 拿到返回的HTML后用解析库提取蓝色字体的ID即可,这类ID一般是带样式的a标签,筛选E开头的文本就能拿到目标值
参考实现代码:
import requests from bs4 import BeautifulSoup target_url = "http://csla.history.ox.ac.uk/search.php" # 替换为从开发者工具中复制的完整表单参数 form_payload = { # 补全Saint选项对应的键值对 "form[item_89]": "Gaul", # 补全所有隐藏表单字段 "submit": "Apply Search" } request_headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", "Referer": "http://csla.history.ox.ac.uk/search.php" } response = requests.post(target_url, data=form_payload, headers=request_headers) response.encoding = response.apparent_encoding soup = BeautifulSoup(response.text, "html.parser") # 根据实际页面结构调整选择器,匹配蓝色字体的ID链接 id_elements = soup.select("a[style*='color: blue']") result_ids = [elem.get_text(strip=True) for elem in id_elements if elem.get_text(strip=True).startswith("E")] print(result_ids)
方案2:浏览器自动化模拟操作(适配复杂校验场景)
如果POST请求带动态加密参数、有严格的人机校验,逆向成本高,直接用自动化工具模拟人工操作即可,逻辑和手动筛选完全一致,不需要分析请求参数:
- 优先选Playwright作为自动化工具,自动适配浏览器驱动,API封装更简洁
- 操作步骤和手动操作完全对齐:打开页面→点选Saint→下拉框选Gaul→点Apply Search→等结果加载→提取ID
- 缺点是爬取速度比直接发POST慢,适合数据量不大的场景
参考实现代码:
from playwright.sync_api import sync_playwright with sync_playwright() as p: # headless=False可以打开浏览器看到操作过程,调试时用 browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto("http://csla.history.ox.ac.uk/search.php") # 点选Saint选项,根据实际元素属性调整选择器 page.get_by_text("Saint").click() # 区域下拉框选择Gaul选项 page.select_option("#text-nine", value="Gaul") # 点击提交按钮 page.get_by_text("Apply Search").click() # 等待结果列表加载完成 page.wait_for_selector("text=E06478") # 提取所有E开头的ID result_ids = page.locator("a").filter(has_text=lambda txt: txt and txt.startswith("E")).all_text_contents() print(result_ids) browser.close()
注意:如果结果列表有多页,两种方案都需要额外处理分页:POST方案直接在表单参数里传页码,自动化方案模拟点击下一页即可,直到没有新的结果返回。
内容的提问来源于stack exchange,提问作者natalieee
相关产品推荐
相关产品推荐

