pandas 复杂格式处理实战:JSON、XML 与 HTML 解析技巧
在数据分析中,我们经常会遇到非结构化或半结构化数据,比如 JSON、XML 和 HTML 格式的文件。这些格式在网页数据、配置文件、跨系统交互中十分常见,但解析起来往往比 CSV/Excel 更复杂。今天我们就来聊聊 pandas 如何优雅地处理这些复杂格式,结合具体场景和代码示例,看看如何高效提取所需数据。
一、JSON 数据处理:灵活应对多种结构
JSON 是最常见的半结构化数据格式之一,pandas 的read_json和to_json提供了丰富的参数来应对不同场景。
1. 不同 orient 模式的选择
orient参数决定了 JSON 的解析 / 生成方式,常见取值包括:
records:默认模式,适合列表型数据(每行一个对象)python
data = '[{"name":"Alice","age":28},{"name":"Bob","age":35}]' df = pd.read_json(data, orient='records') # 输出: # name age # 0 Alice 28 # 1 Bob 35index:以索引为键的嵌套结构python
data = '{"index":{"0":{"name":"Alice","age":28},"1":{"name":"Bob","age":35}}' df = pd.read_json(data, orient='index')table:符合 JSON Table Schema 标准,保留元数据(如数据类型)python
df.to_json('table.json', orient='table') # 生成包含schema的JSON
2. 嵌套结构扁平化
遇到多层嵌套的 JSON(如 API 返回的复杂数据),可使用json_normalize:
python
from pandas.io.json import json_normalize
nested_data = [
{
"user": {"id": 1, "name": "Alice"},
"orders": [{"product": "book", "price": 99.9}, {"product": "pen", "price": 9.9}]
}
]
df = json_normalize(nested_data,
record_path='orders', # 指定子数组路径
meta=['user.id', 'user.name']) # 保留外层字段
# 输出:
# product price user.id user.name
# 0 book 99.9 1 Alice
# 1 pen 9.9 1 Alice
3. 线性格式(Lines JSON)
处理大文件时,使用lines=True逐行解析:
python
# 写入线性格式
df.to_json('large_data.json', orient='records', lines=True)
# 读取
with open('large_data.json', 'r') as f:
for chunk in pd.read_json(f, lines=True, chunksize=1000):
process(chunk) # 分块处理
二、XML 解析:XPath 与命名空间的博弈
XML 常用于配置文件和结构化数据交换,pandas 的read_xml依赖 lxml 解析器,支持 XPath 查询和命名空间处理。
1. 基础解析与 XPath 过滤
python
xml = '''
<books>
<book category="tech">
<title lang="en">Python Cookbook</title>
<price>69.9</price>
</book>
<book category="novel">
<title lang="zh">三体</title>
<price>59.9</price>
</book>
</books>
'''
# 提取所有book节点
df = pd.read_xml(xml, xpath='//book')
# 过滤category为tech的书籍
tech_books = pd.read_xml(xml, xpath='//book[@category="tech"]')
2. 命名空间处理
当 XML 包含命名空间时(如<ns:book>),需显式声明:
python
xml_namespaced = '''
<ns:data xmlns:ns="http://example.com">
<ns:item>value1</ns:item>
<ns:item>value2</ns:item>
</ns:data>
'''
# 声明命名空间映射
df = pd.read_xml(xml_namespaced,
xpath='//ns:item',
namespaces={'ns': 'http://example.com'})
3. 大文件处理:iterparse
对于 GB 级 XML 文件,使用iterparse逐节点读取(需指定物理文件路径):
python
df = pd.read_xml('large_file.xml',
iterparse={'row': ['title', 'price']}) # 指定目标节点
三、HTML 表格提取:解析器选择与属性过滤
网页中的表格数据常以 HTML 形式存在,read_html支持自动解析表格,但需注意解析器差异。
1. 解析器对比与选择
lxml:速度快,但要求 HTML 结构严格html5lib:容错性强,处理不规范 HTMLbs4:需安装 BeautifulSoup,灵活性高
python
# 显式指定解析器
df_list = pd.read_html('https://example.com/table.html', flavor='html5lib')
2. 通过属性过滤表格
利用attrs参数定位特定表格(如带有 id 或 class 的表格):
python
# 提取id为'table-report'的表格
df = pd.read_html('网页HTML', attrs={'id': 'table-report'})[0]
# 提取class包含'hover'的表格
hover_tables = pd.read_html('网页HTML', attrs={'class': 'hover'})
3. 处理复杂表头与链接
python
html = '''
<table>
<tr>
<th>名称</th>
<th>链接</th>
</tr>
<tr>
<td>熊猫文档</td>
<td><a href="https://pandas.pydata.org">官网</a></td>
</tr>
</table>
'''
# 提取链接(设置extract_links='all')
df = pd.read_html(html, extract_links='all')[0]
# 输出:
# 名称 链接
# 0 熊猫文档 (官网, https://pandas.pydata.org)
四、实战避坑指南
-
JSON 类型推断陷阱:
- 对象数组(
orient='records')会自动推断类型,嵌套字典可能转为object类型,建议用dtype指定
python
pd.read_json(data, dtype={'age': 'int32'}) # 强制指定列类型 - 对象数组(
-
XML 命名空间坑:
- 未声明命名空间时,XPath 可能无法匹配节点,需始终检查命名空间声明
-
HTML 解析器兼容性:
- 复杂网页建议优先用
html5lib,虽然慢但稳定性高
- 复杂网页建议优先用
希望本文能帮助你在处理复杂格式数据时少走弯路!实际项目中,建议根据数据特点选择最合适的解析方式:JSON 用orient匹配结构,XML 用 XPath 精准定位,HTML 结合解析器特性提取表格。
欢迎点赞收藏,后续会分享 pandas 与数据库交互、大文件分块处理等进阶技巧~ 有具体问题或想了解的场景,欢迎在评论区留言讨论!
更多推荐

所有评论(0)