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

使用Python爬取MLB首发阵容时数据缺失问题求助

MLB首发阵容爬取人员不全问题排查

我尝试用Python爬取https://www.baseballpress.com/lineups/2022-08-04页面的MLB首发阵容,运行下方代码后数据存入DataFrame,客队阵容在first_lineup列、主队在second_lineup列,但存在人员爬取不全的问题。附数据框输出和网页截图,求解释原因。

import requests
import pandas as pd
from bs4 import BeautifulSoup


url = "https://www.baseballpress.com/lineups/2022-08-04"

def get_names(item):
    try:
        player_name = item.get('data-razz').split("/")[-2].replace("+"," ")
    except IndexError: player_name = ""
    return player_name

r = requests.get(url)
soup = BeautifulSoup(r.text,'lxml')
first_lineup = [get_names(item) for item in soup.select(".col--min:nth-of-type(1) > a.player-link, [class$='col--min']:nth-of-type(1) .player > a.player-link")]
second_lineup = [get_names(item) for item in soup.select(".col--min:nth-of-type(2) > a.player-link, [class$='col--min']:nth-of-type(2) .player > a.player-link")]

df = pd.DataFrame({"first_lineup":first_lineup,"second_lineup":second_lineup})
df.to_csv("baseballpress.csv", encoding='utf-8', index=False)
print(df)

截图:

  • 数据框输出:Dataframe Code Output
  • 网页示例:Website example

问题原因分析

  1. CSS选择器覆盖范围不全
    你的选择器仅针对.col--min:nth-of-type(1)和:nth-of-type(2)下的直接子链接、特定嵌套层级的.player > a.player-link,但网页中部分球员的DOM结构可能不在这些范围内,导致该部分球员被遗漏。比如部分球员可能处于更深的嵌套容器,或是页面布局存在例外情况,你的选择器未覆盖到。

  2. 名字提取依赖不稳定属性
    你通过data-razz属性拆分获取球员名字,但部分球员的链接可能没有这个属性,触发IndexError后返回空字符串,看起来像是爬取不全,实际是名字提取失败。依赖这类非标准属性的方式容错性差,页面属性一旦变更就会失效。

  3. 动态加载数据未被捕获
    页面部分阵容数据可能通过JavaScript动态渲染,requests.get()只能获取初始静态HTML,无法加载JS异步请求生成的内容。如果有球员数据是页面加载后才填充的,静态HTML里就没有这些信息,自然爬取不到。

修正建议

  • 优化CSS选择器:先定位每个比赛的阵容容器(.lineup),再分别提取客队和主队的所有球员链接,确保覆盖所有阵容区块。
  • 更换名字提取方式:优先提取链接的文本内容,比依赖data-razz更稳定。
  • 处理动态内容:如果确认是JS动态加载,可改用Selenium等工具模拟浏览器加载页面,获取完整渲染后的HTML。

修正后的示例代码:

import requests
import pandas as pd
from bs4 import BeautifulSoup

url = "https://www.baseballpress.com/lineups/2022-08-04"

def get_names(item):
    # 优先提取链接文本,备用data-razz属性
    try:
        name = item.text.strip()
        if not name:
            name = item.get('data-razz', '').split("/")[-2].replace("+", " ")
        return name
    except:
        return ""

r = requests.get(url)
soup = BeautifulSoup(r.text, 'lxml')

first_lineup = []
second_lineup = []

# 遍历每个比赛的阵容区块
for lineup_block in soup.select(".lineup"):
    # 提取客队所有球员链接
    away_players = lineup_block.select(".col--min:first-of-type .player-link")
    first_lineup.extend([get_names(p) for p in away_players])
    # 提取主队所有球员链接
    home_players = lineup_block.select(".col--min:nth-of-type(2) .player-link")
    second_lineup.extend([get_names(p) for p in home_players])

# 对齐两队阵容长度,避免DataFrame行列不匹配
max_length = max(len(first_lineup), len(second_lineup))
first_lineup += [""] * (max_length - len(first_lineup))
second_lineup += [""] * (max_length - len(second_lineup))

df = pd.DataFrame({"first_lineup": first_lineup, "second_lineup": second_lineup})
df.to_csv("baseballpress.csv", encoding='utf-8', index=False)
print(df)

内容的提问来源于stack exchange,提问作者Ben Ahnen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:48:22