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

使用pandas read_html爬取表格时如何将合并单元格的单行拆分为两行

解决方案

核心原因

目标表格的每一行<tr>中,每个<td>单元格都嵌套了2个<p>标签,分别存储两位选手的对应统计值,pandas.read_html()默认会把同一单元格内的所有文本直接拼接,所以会出现一行同时包含两类数据的问题。

方案1:预处理HTML后再解析(符合修改原始HTML的需求)

先通过bs4修改提取到的表格结构,把原来的每一行拆成独立的两行,再传给read_html解析:

import requests
import pandas as pd
from bs4 import BeautifulSoup

url = "http://ufcstats.com/fight-details/bb15c0a2911043bd"
headers = {
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0",
}
req = requests.get(url, headers=headers)
soup = BeautifulSoup(req.content, "html.parser")
table = soup.find_all("table", {"class": "b-fight-details__table"})[-1]

# 处理每一行,拆成两个选手的独立行
new_rows = []
for tr in table.find_all("tr"):
    # 保留表头
    if tr.find("th"):
        new_rows.append(str(tr))
        continue
    # 提取所有单元格里的两个p标签内容,分别组装成两行
    tds = tr.find_all("td")
    fighter1_tds = []
    fighter2_tds = []
    for td in tds:
        p_tags = td.find_all("p")
        if len(p_tags) >= 2:
            fighter1_tds.append(f"<td>{p_tags[0].get_text(strip=True)}</td>")
            fighter2_tds.append(f"<td>{p_tags[1].get_text(strip=True)}</td>")
        else:
            # 公共单列单元格两边同步补全
            text = td.get_text(strip=True)
            fighter1_tds.append(f"<td>{text}</td>")
            fighter2_tds.append(f"<td>{text}</td>")
    new_rows.append(f"<tr>{''.join(fighter1_tds)}</tr>")
    new_rows.append(f"<tr>{''.join(fighter2_tds)}</tr>")

# 拼接成新的表格HTML
processed_table = f"<table>{''.join(new_rows)}</table>"
# 解析处理后的HTML
df = pd.read_html(processed_table)[0]
# 可根据需求自定义列名
df.columns = [f"col_{i}" for i in range(df.shape[1])]

执行后得到的DataFrame就是两个选手各占一行的预期格式。

方案2:直接拆分读取后的DataFrame(更简便)

如果不想修改HTML,也可以直接对读取到的原始DataFrame做拆分处理:

import pandas as pd

url = "http://ufcstats.com/fight-details/bb15c0a2911043bd"
raw_df = pd.read_html(url)[-1]

# 拆分每行的双选手数据
df_list = []
for _, row in raw_df.iterrows():
    row1 = []
    row2 = []
    for val in row:
        # 单元格内两个值默认用换行/空格分隔,直接拆分即可
        parts = str(val).split()
        if len(parts) >=2:
            row1.append(parts[0])
            row2.append(parts[1])
        else:
            row1.append(val)
            row2.append(val)
    df_list.append(row1)
    df_list.append(row2)

df = pd.DataFrame(df_list, columns=[f"col_{i}" for i in range(raw_df.shape[1])])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 03:45:06