
在数据采集和分析工作中,经常需要从网页上获取表格数据。传统爬虫方法需要构造请求、解析网页、提取要素等多个步骤,代码量较大。而Python的pandas库提供了一个非常便捷的函数pd.read_html() ,可以轻松抓取网页上的表格数据,大大简化了爬取表格数据的流程。
pd.read_html() 函数适合抓取HTML中以 <table> 标签结构展示的数据。典型的表格数据结构如下:
<table>
<thead>
<tr>
<th>标题1</th>
<th>标题2</th>
</tr>
</thead>
<tbody>
<tr>
<td>数据1</td>
<td>数据2</td>
</tr>
<tr>
<td>数据3</td>
<td>数据4</td>
</tr>
</tbody>
</table>只要网页具有这种结构,就可以使用 pd.read_html() 来抓取数据。
pd.read_html() 函数的工作原理是:
1、向指定的URL或HTML文件发送请求
2、解析HTML内容,查找所有的 <table> 标签
3、将每个表格转换为一个DataFrame
4、返回包含所有DataFrame的列表
pandas.read_html(io, match='.+', flavor=None, header=None,
index_col=None, skiprows=None, attrs=None,
parse_dates=False, thousands=',', encoding=None,
decimal='.', converters=None, na_values=None,
keep_default_na=True, displayed_only=True)import pandas as pd
url = "https://www.stats.gov.cn/sj/xwfbh/fbhwd/202507/t20250715_1960414.html"
try:
tables = pd.read_html(url, encoding='utf-8')
# 第一张表即 2024-06 至 2025-06 环比增速
mom = tables[0]
print("环比增速(%):")
print(mom.head(10))
mom.to_csv("industry_mom_2025.csv", index=False, encoding='utf-8-sig')
except Exception as e:
print("抓取失败:", e)import pandas as pd
from time import sleep
base_url = ' https://example.com/stock_data?page= {}'
all_data = pd.DataFrame()
for page in range(1, 6): # 假设抓取5页数据
url = base_url.format(page)
try:
df = pd.read_html(url)[0] # 获取第一张表格
all_data = pd.concat([all_data, df])
print(f'第{page}页抓取成功')
sleep(1) # 礼貌性暂停1秒
except Exception as e:
print(f'第{page}页抓取失败: {e}')
# 保存所有数据
all_data.to_csv('stock_data_all_pages.csv', index=False)
print('所有数据已保存')import pandas as pd
url = ' https://example.com/complex_page '
# 只抓取id为'main-table'的表格
table = pd.read_html(url, attrs={'id': 'main-table'})
# 清理数据 - 删除空行和空列
clean_table = table.dropna(how='all').dropna(axis=1, how='all')
print(clean_table.head())def grab_table(url: str, *, attrs=None, skiprows=None) -> pd.DataFrame | None:
try:
tabs = pd.read_html(url, attrs=attrs, skiprows=skiprows, encoding='utf-8')
return tabs[0].dropna(how='all').dropna(axis=1, how='all')
except ValueError:
return None
if __name__ == "__main__":
df = grab_table("https://example.com/report.html", attrs={"class": "data"})
if df is not None:
df.to_csv("report.csv", index=False)"""
目标:抓取需登录的「个人成绩表」
思路:① 登录拿 Cookie ② 把 Cookie 塞进后续请求 ③ read_html 解析
"""
importrequests, pandasaspd
login_url = "https://example.com/login"
grade_url = "https://example.com/grade"
sess = requests.Session()
# 1. 登录
sess.post(login_url, data={"username": "me", "password": "pass"}, timeout=10)
# 2. 拿表格
resp = sess.get(grade_url)
tables = pd.read_html(resp.text) # 支持 io 为字符串
grades = tables[0]
grades.to_csv("my_grades.csv", index=False, encoding='utf-8-sig')"""
200 个 URL 形如 /report/2020 … /report/2219
使用 aiohttp 异步拉取,IO 耗时从 20 min → 1 min
"""
importasyncio, aiohttp, pandasaspd
frompathlibimportPath
BASE = "https://example.com/report/{}"
SAVE = Path("reports")
SAVE.mkdir(exist_ok=True)
asyncdeffetch_save(year: int, session: aiohttp.ClientSession):
url = BASE.format(year)
asyncwithsession.get(url) asresp:
html = awaitresp.text(encoding='utf-8')
try:
df = pd.read_html(html)[0]
df.to_csv(SAVE/f"{year}.csv", index=False)
print(f"{year}")
exceptValueError:
print(f"{year}无表")
asyncdefmain():
asyncwithaiohttp.ClientSession() assession:
tasks = [fetch_save(y, session) foryinrange(2020, 2220)]
awaitasyncio.gather(*tasks)
if__name__ == "__main__":
asyncio.run(main())"""
维基百科「各国 GDP」页面含 3 张表,按「国家」列对齐后合并
"""
importpandasaspd
url = "https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(nominal)"
tables = pd.read_html(url, match="Country") # 只抓表头含 Country 的表
# 统一索引后 concat
merged = (
pd.concat([t.set_index("Country") fortintables], axis=1)
.reset_index()
)
merged.to_csv("gdp_merged.csv", index=False)"""
每天凌晨跑批,把官网「每日通报」表追加到本地,重复行自动跳过
"""
importpandasaspd
fromdatetimeimportdatetime, timedelta
LOCAL = "daily_report.csv"
url = "https://example.com/daily"
latest = pd.read_html(url, parse_dates=["Date"])[0]
yesterday = (datetime.today() -timedelta(days=1)).date()
new = latest[latest["Date"].dt.date>yesterday]
ifnew.empty:
print("无新数据")
else:
new.to_csv(LOCAL, mode="a", header=notpd.io.common.file_exists(LOCAL), index=False)
print(f"追加 {len(new)} 行")"""
某交易所同时提供「HTML 表格」和 「REST JSON」
HTML 404 时立即切 API,保证脚本不中断
"""
importrequests, pandasaspd
HTML_URL = "https://exchange.com/price.html"
API_URL = "https://exchange.com/api/v1/price"
defget_price() ->pd.DataFrame:
try:
# 优先读表
returnpd.read_html(HTML_URL, attrs={"id": "price"})[0]
exceptException:
# 兜底:调 REST API
data = requests.get(API_URL, timeout=10).json()
returnpd.DataFrame(data["list"]) # JSON -> DataFrame
df = get_price()
df.to_csv("price.csv", index=False)1、不是所有网页表格都能用 pd.read_html() 抓取,对静态table场景pandas是高效方案。
2、对于需要登录或反爬虫机制严格的网站,需要配合selenium使用。
3、抓取数据时应注意网站的robots.txt文件和使用条款。
4、大量请求时添加适当的延迟,避免给服务器造成负担。
pd.read_html() 是Python中一个非常强大的工具,能够用极简的代码实现网页表格数据的抓取。对于数据分析师和爬虫初学者来说,这是一个高效且易于上手的解决方案。对于更复杂的爬取需求,可能需要结合其他工具如requests、BeautifulSoup或selenium来实现。
“无他,惟手熟尔”!有需要就用起来。
如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!
本文分享自 Nicholas与Pypi 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!