前言
在爬虫数据采集场景中,网页table表格是非常典型的结构化数据,榜单、统计报表、参数清单等大量网页都会使用表格展示数据。
解析网页数据常见方案:正则表达式、beautifulsoup、xpath。
对比来看:
- 正则表达式适合简单文本,处理嵌套标签极易出错;
- beautifulsoup api友好,但复杂筛选书写繁琐;
- xpath 基于文档层级定位,语法简洁,精准筛选节点,搭配
lxml解析速度优秀,是抓取表格数据的热门选择。
本文结合实战案例,讲解如何利用python + xpath提取表格表头、行数据,封装通用解析代码,同时整理开发中高频踩坑点。
一、环境准备
我们使用两大核心库:
requests:请求网页,获取html源码lxml:html解析器,支持完整xpath语法
安装命令:
pip install requests lxml
二、html表格基础结构认知
标准网页表格标签层级:
<table>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>城市</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>22</td>
<td>重庆</td>
</tr>
<tr>
<td>李四</td>
<td>25</td>
<td>成都</td>
</tr>
</tbody>
</table>标签说明:
<table>:表格根标签<thead>:表头区域,<th>代表表头单元格<tbody>:表格主体数据区域<tr>:表格单行<td>:普通数据单元格
三、表格常用xpath表达式
# 匹配页面中所有表格下的表头文本 //table//th/text() # 获取表格内所有行(包含表头行) //table//tr # 只获取tbody内数据行(过滤表头) //table//tbody//tr # 获取单行内所有单元格文本 .//td/text() # 指定id的表格,精准定位(推荐,避免页面多个表格干扰) //table[@id="data-table"]//tbody//tr
小知识点:// 代表跨层级搜索;. 代表在当前节点下继续搜索,循环遍历tr的时候必须使用 .。
四、实战案例1:解析本地html表格
先模拟一段html源码,直接解析,不发起网络请求,方便测试:
from lxml import etree
# 模拟网页html
html = """
<table>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>城市</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>22</td>
<td>重庆</td>
</tr>
<tr>
<td>李四</td>
<td>25</td>
<td>成都</td>
</tr>
</tbody>
</table>
"""
# 构建html解析对象
tree = etree.html(html)
# 提取表头
headers = tree.xpath('//table//th/text()')
print("表头:", headers)
# 提取所有数据行
rows = tree.xpath('//table//tbody//tr')
table_data = []
for row in rows:
# .//td 代表当前tr节点下查找td
cell_text = row.xpath('.//td/text()')
table_data.append(cell_text)
print("表格数据:", table_data)
运行结果:
表头: ['姓名', '年龄', '城市']
表格数据: [['张三', '22', '重庆'], ['李四', '25', '成都']]
我们可以把表头和数据结合,生成字典列表,结构更友好:
result = [dict(zip(headers, item)) for item in table_data]
print("结构化字典数据:", result)
五、实战案例2:抓取线上网页表格
结合requests获取远程网页,通用模板:
import requests
from lxml import etree
headers = {
"user-agent": "mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/120.0.0.0 safari/537.36"
}
url = "目标网页地址"
resp = requests.get(url, headers=headers)
resp.encoding = resp.apparent_encoding
tree = etree.html(resp.text)
# 修改xpath适配目标页面
th_list = tree.xpath('//table//th/text()')
tr_list = tree.xpath('//table//tbody//tr')
data_list = []
for tr in tr_list:
td_list = tr.xpath('.//td/text()')
data_list.append(td_list)
print(data_list)
六、常见问题与避坑指南
1. 页面存在多个table,抓取数据错乱
解决方法:通过id、class精准定位表格,不要直接使用//table
//table[@class="table-data"]//tbody//tr
2. td内部存在<a>、<span>等子标签,text()拿不到全部文本
text()只能获取当前标签直接文本,内部标签文本会丢失。
改用 string() 或者 xpath('.//td//text()')
# 提取单元格内所有文本,包含子标签文字
texts = row.xpath('.//td[1]//text()')
content = "".join([i.strip() for i in texts])
3. 文本存在大量换行、空格
增加清洗逻辑,封装工具函数:
def clean_text(text):
if not text:
return ""
return text.strip().replace("\n", "").replace("\r", "")
4. 动态渲染表格(js加载数据)
requests只能拿到静态html,如果表格由ajax、vue/react动态生成,lxml无法获取内容。
解决方案:使用playwright、selenium加载完整页面。
5. 部分网页没有thead,表头直接放在第一行tr
不要强制匹配thead,灵活调整xpath表达式。
七、封装通用表格解析函数
可以直接复用在项目中:
from lxml import etree
def parse_table(html: str, table_xpath: str = "//table"):
"""
通用表格解析函数
:param html: html源码
:param table_xpath: 表格定位xpath
:return: 表头、字典格式表格数据
"""
tree = etree.html(html)
# 提取表头
headers = tree.xpath(f"{table_xpath}//th/text()")
headers = [h.strip() for h in headers if h.strip()]
# 提取数据行
rows = tree.xpath(f"{table_xpath}//tbody//tr")
result = []
for tr in rows:
cells = tr.xpath('.//td//text()')
cells = [c.strip() for c in cells if c.strip()]
if len(cells) == len(headers):
result.append(dict(zip(headers, cells)))
return headers, result
总结
- 使用
lxml.etree加载html,配合xpath实现表格节点筛选; - 遍历
<tr>时,内部单元格查找必须使用.//td,代表当前行内搜索; - 优先通过id/class精准定位表格,避免多表格干扰;
- 遇到单元格嵌套标签,使用
//text()获取全部文本并清洗; - 静态页面适用lxml,js动态渲染表格需要使用浏览器自动化工具。
如果你经常做网页采集,这套xpath解析表格方案可以作为基础模板,根据不同网页结构微调xpath表达式即可快速复用。
到此这篇关于python使用xpath提取表格数据的详细教程的文章就介绍到这了,更多相关python xpath提取表格数据内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论