如何用Python+Selenium爬取类名与布局动态变化的FanDuel网站数据
解决方案
针对动态DOM结构、动态类名的爬取场景,按稳定性从高到低选择以下方案即可,不需要频繁修改脚本:
方案1:直接抓取后端数据接口(最高稳定性,优先选择)
FanDuel的赛事赔率、比分、计时数据全部通过前端异步接口拉取,返回结构化JSON数据,完全不受前端DOM改版影响:
- 打开浏览器开发者工具,切换到「网络」面板,筛选
Fetch/XHR类型请求,刷新目标页面 - 在请求列表里搜索
spread/moneyline/event这类关键词,就能找到对应赛事的详情接口,返回数据里直接包含需要的所有字段,字段名固定不会随页面版本变动 - 调用接口时只需要携带正常的浏览器User-Agent、页面Referer头即可,部分接口要求携带的临时鉴权token可以直接从页面全局变量中读取,不需要解析DOM
- 拿到JSON响应后直接按字段键值提取数据即可,稳定性远高于DOM解析
方案2:基于语义锚点的相对定位(次选,适合接口反爬严格的场景)
如果接口有严格的签名校验难以直接调用,解析DOM时绝对不要使用全路径XPATH、不要依赖动态类名/固定层级定位,改用以下定位逻辑:
- 首先找页面上永久固定的文本作为锚点:
Spread/Moneyline/主客队队名/节次标识(Q1/Q2/Half等)这类业务文本不会随DOM结构、类名变动 - 用文本匹配定位锚点,对应XPATH示例:
//*[normalize-space(text())="Spread"],该定位方式不依赖任何元素属性、层级位置,只要页面显示Spread文字就能命中 - 从锚点节点出发,按固定相对位置找对应数据节点:比如Spread锚点对应列下的两个让分赔率、队名锚点相邻的比分数字、赛事头部区域带冒号格式的计时节点,这类相对业务位置不会因为外层多嵌套一层弹窗、广告div就失效
- 通用交互元素(比如提到的弹窗关闭按钮)优先匹配ARIA属性定位,比如找带
aria-label="Close"属性的按钮即可,不需要关心它在DOM里的具体位置
方案3:兜底适配逻辑
如果用Playwright/Pyppeteer这类无头浏览器方案爬取,可以补充两层兜底逻辑降低维护成本:
- 动态类名不要做全匹配,只匹配固定不变的属性:比如元素的
role属性(role="gridcell"/role="button"等)、标签名,不依赖随机生成的类名片段 - 对数字类数据(比分、赔率、计时)增加格式校验:比如比分是1-3位的整数、赔率是带正负号的数字/小数、计时符合
MM:SS格式,命中格式规则的节点才判定为有效数据
注意事项
- 不要直接用requests请求静态页面解析,该站点是纯客户端渲染,静态HTML只有空的根节点,没有任何有效数据
- 写完定位逻辑后连续刷新5-10次页面验证命中率,只要是基于语义、相对位置写的定位,基本不会出现刷新失效的问题
- 即使后续前端大版本改版,最多只需要重新确认一次接口地址、或者微调锚点到数据节点的相对层级,维护成本极低
内容的提问来源于stack exchange,提问作者Caminero
相关产品推荐
相关产品推荐

