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

如何用BeautifulSoup提取HTML中Span及整行国际象棋赛事信息

优化BeautifulSoup提取国际象棋赛事数据的方案

一、初始需求的简化方案

你之前提取选手和评分的代码确实有点绕,还没搞定动态class的国家提取。其实可以利用BeautifulSoup的CSS选择器和元素定位来大幅简化:

目标HTML片段:

<div class="user-tagline "> <span class="username " data-avatar="aaaaaaa">player1</span> <span class="user-rating">(1357)</span> <span class="country-flag-small flag-113" tip="Portugal"></span> </div> <div class="user-tagline "> <span class="username " data-avatar="bbbbbbb">player2</span> <span class="user-rating">(1387)</span> <span class="country-flag-small flag-70" tip="Indonesia"></span> </div>

简化后的代码:

from bs4 import BeautifulSoup

html = # 你的HTML字符串
soup = BeautifulSoup(html, 'html.parser')

# 提取第一个选手的完整信息
first_player_div = soup.find('div', class_='user-tagline')
player1 = first_player_div.find('span', class_='username').get_text(strip=True)
pscore1 = first_player_div.find('span', class_='user-rating').get_text(strip=True).strip('()')
# 直接通过tip属性拿国家,彻底绕开动态的flag-xxx class
player1_country = first_player_div.find('span', class_='country-flag-small')['tip']

print(player1, pscore1, player1_country)  # 输出:player1 1357 Portugal

优势说明:

  • 用find()替代findAll()[0]更直接,避免不必要的列表索引操作
  • get_text(strip=True)自动去除文本前后空白,不用手动拆分字符串
  • 直接读取元素属性获取国家,完全不受动态class影响

二、更新需求:完整提取整行赛事数据

对于包含多字段的赛事行,我们可以结构化地提取所有信息,代码逻辑更清晰易维护:

目标HTML片段:

<tr board-popover="" fen="r1bk2r1/1p2n3/pN6/1B1qQp2/P2Pp2p/1P6/2P2PPP/R3K1R1 b Q -" flip-board="1" highlight-squares="c4b6"> <td> <a class="clickable-link td-user" href="https://www.chess.com/live/game/2249663029?username=belemnarmada" target="_self"> <span class="time-control"> <i class="icon-rapid"> </i> </span> <div class="user-tagline "> <span class="username " data-avatar="https://betacssjs.chesscomfiles.com/bundles/web/images/noavatar_l.1c5172d5.gif" data-country="Portugal" data-enabled="true" data-flag="113" data-joined="Joined Jun 19, 2016" data-logged="Online 6 hrs ago" data-membership="basic" data-name="Atikinounette" data-popup="hover" data-title="" data-username="Atikinounette"> Atikinounette </span> <span class="user-rating"> (1357) </span> <span class="country-flag-small flag-113" tip="Portugal"> </span> </div> <div class="user-tagline "> <span class="username " data-avatar="https://images.chesscomfiles.com/uploads/v1/user/28196414.83e31ff1.50x50o.3a6f77e4aa44.jpeg" data-country="Indonesia" data-enabled="true" data-flag="70" data-joined="Joined May 15, 2016" data-logged="Online Nov 7, 2017" data-membership="basic" data-name="belemnarmada" data-popup="hover" data-title="" data-username="belemnarmada"> belemnarmada </span> <span class="user-rating"> (1387) </span> <span class="country-flag-small flag-70" tip="Indonesia"> </span> </div> </a> </td> <td> <a class="clickable-link text-middle" href="https://www.chess.com/live/game/2249663029?username=belemnarmada" target="_self"> <div class="pull-left"> <span class="game-result"> 1 </span> <span class="game-result"> 0 </span> </div> <div class="result"> <i class="icon-square-minus loss" tip="Lost"> </i> </div> </a> </td> <td class="text-center"> <a class="clickable-link" href="https://www.chess.com/live/game/2249663029?username=belemnarmada" target="_self"> 30 min </a> </td> <td class="text-right"> <a class="clickable-link text-middle moves" href="https://www.chess.com/live/game/2249663029?username=belemnarmada" target="_self"> 25 </a> </td> <td class="text-right miniboard"> <a class="clickable-link archive-date" href="https://www.chess.com/live/game/2249663029?username=belemnarmada" target="_self"> Aug 9, 2017 </a> </td> <td class="text-center miniboard"> <input class="checkbox" game-checkbox="" game-id="2249663029" game-is-live="true" ng-model="model.gameIds[2249663029].checked" type="checkbox"/> </td> </tr>

完整提取代码:

from bs4 import BeautifulSoup

html = # 你的HTML字符串
soup = BeautifulSoup(html, 'html.parser')

# 定位目标赛事行
game_row = soup.find('tr', {'board-popover': ''})

# 提取两位选手的信息
player_divs = game_row.find_all('div', class_='user-tagline')
players = []
for div in player_divs:
    player_info = {
        'name': div.find('span', class_='username').get_text(strip=True),
        'rating': div.find('span', class_='user-rating').get_text(strip=True).strip('()'),
        'country': div.find('span', class_='country-flag-small')['tip']
    }
    players.append(player_info)

# 提取比赛结果
result_spans = game_row.find('div', class_='pull-left').find_all('span', class_='game-result')
game_result = [span.get_text(strip=True) for span in result_spans]

# 提取其他赛事字段
game_duration = game_row.find('td', class_='text-center').get_text(strip=True)
total_moves = game_row.find('td', class_='text-right').find('a', class_='moves').get_text(strip=True)
game_date = game_row.find('a', class_='archive-date').get_text(strip=True)

# 整理成结构化数据
game_data = {
    'players': players,
    'result': game_result,
    'duration': game_duration,
    'total_moves': total_moves,
    'date': game_date
}

print(game_data)

输出示例:

{
    'players': [
        {'name': 'Atikinounette', 'rating': '1357', 'country': 'Portugal'},
        {'name': 'belemnarmada', 'rating': '1387', 'country': 'Indonesia'}
    ],
    'result': ['1', '0'],
    'duration': '30 min',
    'total_moves': '25',
    'date': 'Aug 9, 2017'
}

方案亮点:

  • 用字典结构化存储数据,可读性和扩展性拉满
  • 精准定位元素,避免冗余的文本拆分操作
  • 统一用get_text(strip=True)处理文本,自动清理空白字符
  • 完全兼容动态class的元素提取(比如国家flag)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:23:52