使用Python的BS4爬取baseball-reference.com嵌套表格遇阻求助
解决Baseball-Reference比赛页面表格爬取问题
我太懂这个痛点了!Baseball-Reference的比赛数据页面确实有点鸡贼——它把你要的打击数据表格(包含At-Bats、RBIs、HRs这些字段的)藏在了HTML注释里,这就是你直接用find/find_all或者Pandas默认读取找不到的原因。下面给你两种靠谱的解决方案,任选其一就行:
方法一:用BeautifulSoup解析注释中的表格
核心思路是先把页面里的HTML注释提取出来,再把注释内容转换成可解析的HTML对象,之后就能正常定位表格了:
from urllib.request import urlopen from bs4 import BeautifulSoup, Comment # 目标URL test_url = 'https://www.baseball-reference.com/boxes/SLN/SLN201704020.shtml' # 获取页面内容 page = urlopen(test_url) soup = BeautifulSoup(page, 'lxml') # 提取页面中所有的HTML注释 all_comments = soup.find_all(string=lambda text: isinstance(text, Comment)) # 遍历注释,筛选出包含目标表格的内容 for comment in all_comments: # 把注释文本转换成BeautifulSoup对象 comment_soup = BeautifulSoup(comment, 'lxml') # 查找class为sortable stats_table的表格(就是你要的两个球队打击数据表格) target_tables = comment_soup.find_all("table", {"class": "sortable stats_table"}) if target_tables: # 遍历两个表格,提取数据 for team_idx, table in enumerate(target_tables, 1): print(f"--- 第{team_idx}支球队打击数据 ---") # 提取表头 headers = [th.get_text(strip=True) for th in table.find('tr').find_all('th')] print(headers) # 提取每一行数据 for row in table.find_all('tr')[1:]: row_data = [cell.get_text(strip=True) for cell in row.find_all(['th', 'td'])] print(row_data)
方法二:用Pandas快速读取(更简便)
如果你想省事儿,Pandas的read_html可以快速搞定,不过需要先把注释里的表格“释放”出来,再让Pandas读取:
import pandas as pd import requests from bs4 import BeautifulSoup, Comment test_url = 'https://www.baseball-reference.com/boxes/SLN/SLN201704020.shtml' # 获取页面响应 response = requests.get(test_url) soup = BeautifulSoup(response.text, 'lxml') # 把所有注释中的HTML内容替换到原页面中(相当于把隐藏的表格“显示”出来) for comment in soup.find_all(string=lambda text: isinstance(text, Comment)): parsed_comment = BeautifulSoup(comment, 'lxml') comment.replace_with(parsed_comment) # 直接读取符合class条件的表格 target_tables = pd.read_html(str(soup), attrs={"class": "sortable stats_table"}) # target_tables是一个DataFrame列表,第一个元素是客队数据,第二个是主队数据 print("=== 客队打击数据 ===") print(target_tables[0].dropna(how='all')) # 去掉空行 print("\n=== 主队打击数据 ===") print(target_tables[1].dropna(how='all'))
小提示
- 如果你直接用
pd.read_html(test_url),会返回页面上所有的表格,所以一定要用attrs参数过滤class="sortable stats_table",这样才能精准拿到你需要的两个表格。 - 两种方法都能解决问题,Pandas的方法更适合快速分析数据,BeautifulSoup则更灵活,方便你自定义提取特定字段。
内容的提问来源于stack exchange,提问作者jbf
相关产品推荐
相关产品推荐

