
本文详解使用selenium替代requests+beautifulsoup抓取fbref英超联赛页面时出现的链接重复、混入非英超球队等典型问题,提供可复用的css选择器方案与健壮代码实现。
本文详解使用selenium替代requests+beautifulsoup抓取fbref英超联赛页面时出现的链接重复、混入非英超球队等典型问题,提供可复用的css选择器方案与健壮代码实现。
FBref(https://www.php.cn/link/862fa6721efe7dbf1c49a905fbab240b DataTables或React组件)在浏览器中异步加载并注入DOM。因此,requests + BeautifulSoup仅能解析初始静态HTML,而该HTML中往往包含大量占位符、冗余导航链接(如全球各联赛、女足、青训队等),导致你观察到的两大问题:
✅ 重复链接:因表格被多次渲染(如分页、排序重绘、响应式切换),同一<a></a>标签可能被多次插入DOM;
✅ 无关球队:页面全局存在大量/squads/路径的链接(如切尔西女足、皇马、河床、浦和红钻等),它们并非来自当前英超表格,而是侧边栏、页脚或广告模块的遗留链接。
✅ 正确解法:用Selenium精准定位动态表格中的目标链接
Selenium模拟真实浏览器行为,等待JavaScript完全执行后提取最终渲染的DOM结构,并支持精确的CSS选择器定位。关键在于不遍历全页所有<a></a>标签,而是聚焦于联赛表格主体内的球队列单元格。
以下为推荐实践代码(已适配2024/25赛季结构):
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 启用无头模式(后台运行,不弹窗)
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
URL = "https://fbref.com/en/comps/9/Premier-League-Stats"
with webdriver.Chrome(options=chrome_options) as driver:
driver.get(URL)
wait = WebDriverWait(driver, 15) # 最长等待15秒
# 精准定位:英超表格中<tbody>内每一行的"team"列中的<a>标签
# selector说明:
# #results2024-202591_overall → 表格ID(含赛季年份,可能随赛季更新,需检查)
# tbody tr → 表格主体行
# td[data-stat='team'] → 标记为team字段的单元格(FBref语义化属性)
# a → 该单元格内的链接
selector = "#results2024-202591_overall tbody tr td[data-stat='team'] a"
team_links = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, selector)))
# 提取并去重(虽通常无需,但加一层保险)
urls = list(set(a.get_attribute("href") for a in team_links if a.get_attribute("href")))
urls.sort() # 可选:按字母序排列便于验证
print(f"成功提取 {len(urls)} 支英超球队链接:")
for url in urls:
print(url)? 关键技巧与注意事项
-
动态ID识别:FBref表格ID形如
#results2024-202591_overall,其中2024-2025为赛季,91为联赛ID(英超固定为9)。建议首次运行时用浏览器开发者工具(F12 → Elements → 搜索stats_table)确认当前ID,或改用更鲁棒的选择器:table[id^="results"][id*="91"] tbody tr td[data-stat='team'] a
(匹配以
results开头、含91的ID) 避免XPath陷阱:虽然XPath也可用,但CSS选择器在Selenium中性能更优、可读性更强,且
data-stat属性是FBref明确设计的语义化钩子,比依赖<td>位置(如<code>td[2])更稳定。反爬友好提示:FBref未设严格反爬机制,但仍建议添加合理延迟(如
time.sleep(1))、设置User-Agent(通过chrome_options.add_argument("--user-agent=...")),并在生产环境加入异常处理与重试逻辑。扩展性建议:若需抓取多赛季或多个联赛,可封装为函数,传入
comp_id(如9)和season(如2024-2025),动态构造URL与选择器。
通过此方法,你将获得唯一、准确、上下文正确的20支英超球队官方统计页链接,彻底规避requests方案下无法绕过的HTML静态局限性。记住:对JS渲染站点,DOM定位优先于全文本匹配——这是高质量网络抓取的核心原则。

















