BeautifulSoup爬取Baseball Reference隐藏链接异常解决方案
问题根源
爬取失效由两个核心问题导致:
- 新赛季联赛的球队链接未直接放在可解析的DOM节点中,而是被包裹在HTML注释标签(
<!-- -->)内。BeautifulSoup默认会将注释识别为特殊Comment对象,不会解析内部元素,因此直接调用find_all('a', href=True)无法提取到这部分链接。已完赛的历史联赛数据直接渲染在DOM树中,所以原有逻辑可以正常运行。 - 现有字符串切片逻辑存在边界bug:第一次提取链接并做字符串替换后,剩余文本中已不存在
title匹配字段,此时orig_ind.find('title')会返回-1,切片结果为空字符串,拼接后自然只能得到站点根域名。
修复方案
采用HTML注释清洗+DOM规则匹配的方案,替代硬编码字符串切片逻辑,同时兼容新旧赛季页面,鲁棒性更强:
import requests from bs4 import BeautifulSoup # 模拟浏览器请求头,避免被反爬拦截 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36' } target_url = 'https://www.baseball-reference.com/register/league.cgi?id=c346199a' resp = requests.get(target_url, headers=headers) # 核心处理:移除HTML注释标签,将注释内的隐藏内容暴露给解析器 clean_html = resp.text.replace('<!--', '').replace('-->', '') soup = BeautifulSoup(clean_html, features='html.parser') team_links = [] for a_tag in soup.find_all('a', href=True): href = a_tag['href'] # 匹配球队页面链接规则,自动去重 if href.startswith('/register/team.cgi?id=') and href not in team_links: full_link = 'https://www.baseball-reference.com' + href team_links.append(full_link) print(team_links)
运行代码可直接提取到页面内全部有效球队链接,与页面实际展示的球队数量完全匹配。
爬取注意事项
- 后续爬取球队页球员数据时,若再次出现标签无法匹配的问题,优先检查目标内容是否被HTML注释包裹,复用上述注释清洗逻辑即可
- 控制请求频率,建议每次请求间隔1-3秒,避免短时间请求量过大导致IP被封禁
- 不要使用requests默认请求头爬取,默认UA会被站点反爬策略直接识别拦截
内容的提问来源于stack exchange,提问作者Jensen Holm
相关产品推荐
相关产品推荐

