使用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
相关产品推荐
相关产品推荐

