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

使用Pandas读取含合并单元格的表格时如何保持列对齐

解决Pandas读取含合并单元格的HTML表格(伪装成.xls)时的列偏移问题

我之前处理过不少这种“披着xls外衣的HTML表格”,合并单元格(尤其是rowspan)确实会让pandas.read_html()犯糊涂,直接读很容易出现列错位的情况。下面是两种亲测有效的解决思路,你可以根据需求选:

方法一:预处理HTML,展开合并单元格(最通用可靠)

核心思路是用BeautifulSoup先把HTML里的rowspan合并单元格展开,让每一行的单元格数量保持一致,这样Pandas读取时就不会乱偏移了。

具体代码:

from bs4 import BeautifulSoup
import pandas as pd

# 读取伪装成xls的HTML文件内容
with open("your_target_file.xls", "r", encoding="utf-8") as file:
    html_raw = file.read()

# 用BeautifulSoup解析HTML
soup = BeautifulSoup(html_raw, "html.parser")

# 遍历所有表格,处理rowspan合并单元格
for table in soup.find_all("table"):
    rows = table.find_all("tr")
    # 记录需要向下填充的单元格信息:(列索引, 单元格值, 剩余填充行数)
    pending_fill = []
    
    for row in rows:
        cells = row.find_all(["td", "th"])
        
        # 先把上一行需要延续的单元格插入到当前行对应位置
        for col_idx, cell_val in pending_fill:
            if col_idx < len(cells):
                cells.insert(col_idx, soup.new_tag("td"))
                cells[col_idx].string = cell_val
            else:
                # 如果当前行单元格数量不够,直接新增单元格
                new_td = soup.new_tag("td")
                new_td.string = cell_val
                row.append(new_td)
        
        # 更新pending_fill:减少剩余填充行数,移除已完成的条目
        updated_pending = []
        for col_idx, cell_val, remain_count in pending_fill:
            remain_count -= 1
            if remain_count > 0:
                updated_pending.append((col_idx, cell_val, remain_count))
        pending_fill = updated_pending
        
        # 检查当前行的单元格是否有rowspan属性,记录需要填充的内容
        for col_idx, cell in enumerate(cells):
            if cell.has_attr("rowspan"):
                span_count = int(cell["rowspan"])
                if span_count > 1:
                    # 把当前单元格的值和剩余需要填充的行数记录下来
                    pending_fill.append((col_idx, cell.string, span_count - 1))
                # 移除rowspan属性,避免重复处理
                del cell["rowspan"]

# 现在处理后的HTML已经展开了所有合并单元格,用Pandas读取
dfs = pd.read_html(str(soup), header=0)
target_df = dfs[0]  # 假设只有一个表格,按需调整索引

为什么这个方法有效?

HTML里的rowspan合并单元格只会在第一行显示值,后面的行对应位置是缺失<td>标签的,Pandas读取时会自动把后面列的内容往前补,导致错位。我们通过BeautifulSoup手动给缺失的位置补上对应的单元格和值,让每一行的单元格数量完全匹配,Pandas就能正确识别列了。

方法二:读取后手动修正(适合数据规律明确的场景)

如果不想引入BeautifulSoup依赖,且你清楚第一列合并单元格的规律(比如第一列的有效值有固定格式,比如都是分类名称),可以先读取数据,再手动调整列和填充空值。

举个例子,假设读取后的数据是这样的(第一列混入了原本第二列的内容):

分类/项目数值
电子产品1000
手机500
电脑500
日用品800
纸巾300

我们可以这样修正:

import pandas as pd

# 读取文件
dfs = pd.read_html("your_target_file.xls", header=0)
df = dfs[0]

# 步骤1:新增一列存放原本的数值
df["真实数值"] = df["数值"]

# 步骤2:把第一列里的项目内容移到第二列
df["项目"] = df["分类/项目"].where(~df["分类/项目"].str.contains("电子产品|日用品"), df["项目"])
# 步骤3:把第一列的空值(非分类的行)用前一个分类值填充
df["分类"] = df["分类/项目"].where(df["分类/项目"].str.contains("电子产品|日用品"), None)
df["分类"] = df["分类"].ffill()

# 步骤4:整理列顺序,删除多余列
df = df[["分类", "项目", "真实数值"]]

这个方法的缺点是需要你对数据特征有明确认知,通用性不如第一种,但胜在不用额外安装库。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:38:11