You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:41:06