首页 > 解决方案 > 使用 Pandas read_html 抓取表格并识别标题

问题描述

我对网络抓取完全陌生,想解析一个特定的表格,该表格出现在美国证券交易委员会提交的公司 DEF 14A 文件中。我能够获得正确的 URL 并将其传递给熊猫。注意:即使每个 DEF 14A 中都应该出现所需的表格,但它的布局可能因公司而异。现在我正在努力格式化数据框。我如何设法获得正确的标题并将其加入单个索引(列)?

到目前为止,这是我的代码:

url_to_use: "https://www.sec.gov/Archives/edgar/data/1000229/000095012907000818/h43371ddef14a.htm"

resp = requests.get(url_to_use)
soup = bs.BeautifulSoup(resp.text, "html.parser")

dfs = pd.read_html(resp.text, match="Salary")
pd.options.display.max_columns = None
df = dfs[0]

df.dropna(how="all", inplace = True)
df.dropna(axis = 1, how="all", inplace = True)

display(df)

现在我的代码输出如下所示: Dataframe output

而正确的布局如下所示: 原始格式

是否有某种方法可以识别属于标题的那些行并将它们组合为标题?

标签: pythonpandasweb-scraping

解决方案


桌子html比较乱。空单元格实际上在源代码中。做一些后期处理是最简单的:

import pandas as pd
import requests

r = requests.get("https://www.sec.gov/Archives/edgar/data/1000229/000095012907000818/h43371ddef14a.htm", headers={'User-agent': 'Mozilla/5.0'}).text
df = pd.read_html(r) #load with user agent to avoid 401 error

df = df[40] #get the right table from the list of dataframes
df = df[8:].rename(columns={i: ' '.join(df[i][:8].dropna()) for i in df.columns}) #generate column headers from the first 8 rows

df.dropna(how='all', axis=1, inplace=True) #remove empty columns and rows
df.dropna(how='all', axis=0, inplace=True)
df.reset_index(drop=True, inplace=True)

def sjoin(x): return ''.join(x[x.notnull()].astype(str))
df = df.groupby(level=0, axis=1).apply(lambda x: x.apply(sjoin, axis=1)) #concatenate columns with the same headers, taken from https://stackoverflow.com/a/24391268/11380795

结果

所有其他补偿 ($)(4) 养老金价值和不合格递延薪酬收入的变化(美元) 姓名及主要职务 非股权激励计划补偿 ($) 薪水 ($) 股票奖励 ($)(1) 总计 ($)
0 8953 (3) David M. Demshur 总裁兼首席执行官 766200(2) 504569 1088559 2368281 2006年
1 8944 (3) Richard L. Bergmark 执行副总裁、首席财务官兼财务主管 330800(2) 324569 799096 1463409 2006年
2 8940 (3) Monty L. Davis 首席运营官兼高级副总裁 320800(2) 314569 559097 1203406 2006年
3 8933 (3) John D. Denson 副总裁、总法律顾问兼秘书 176250(2) 264569 363581 813333 2006年

推荐阅读