解析XML导出CSV遇TypeError:需字节对象而非字符串,如何解决?
解析XML提取属性写入CSV时的TypeError问题解决
问题背景
需要提取以下XML中kategorie节点的id、parent_id属性:
<?xml version="1.0" encoding="UTF-8"?> <test timestamp="20210113"> <kategorien> <kategorie id="1" parent_id="0"> Sprache </kategorie> </kategorien> </test>
编写的Python代码如下:
import csv import xml.etree.ElementTree as ET fields = ['id', 'parent_id'] with open('output.csv', 'wb') as fp: writer = csv.writer(fp) writer.writerow(fields) tree = ET.parse('./file.xml') # from your example Locations is the root and Location is the first level for elem in tree.getroot(): writer.writerow([(elem.get(name) or '').encode('utf-8') for name in fields])
运行后出现错误:
in <module> writer.writerow(fields) TypeError: a bytes-like object is required, not 'str'
错误原因
错误核心是文件打开模式不匹配:
- 用
wb(二进制写入模式)打开文件时,csv.writer要求所有写入内容都是字节类型; - 虽然属性值做了
encode('utf-8')转换,但表头fields是字符串列表,直接写入触发类型错误; - 同时XML遍历逻辑有问题:
tree.getroot()获取的是<test>节点,遍历它的子节点只会拿到<kategorien>,而非目标<kategorie>节点,最终无法提取正确属性。
解决方法
推荐使用文本模式打开文件并指定编码,这是csv模块的标准用法,无需手动编码字符串:
修正后的代码
import csv import xml.etree.ElementTree as ET fields = ['id', 'parent_id'] # 文本模式打开,指定编码并避免多余空行 with open('output.csv', 'w', newline='', encoding='utf-8') as fp: writer = csv.writer(fp) writer.writerow(fields) tree = ET.parse('./file.xml') # 定位到kategorien节点,再遍历目标kategorie子节点 kategorien = tree.find('kategorien') for elem in kategorien.findall('kategorie'): # 无需手动encode,csv writer自动处理编码 writer.writerow([elem.get(name) or '' for name in fields])
关键修改点
- 文件打开模式:将
wb改为w,添加newline=''(避免CSV写入时产生多余空行)和encoding='utf-8'; - XML节点遍历:通过
tree.find('kategorien')定位父节点,再用findall('kategorie')遍历目标节点,确保提取正确属性; - 移除手动编码:文本模式下
csv.writer会自动完成字符串到字节的转换,无需调用encode。
若坚持使用二进制模式,需将表头也转为字节:
writer.writerow([f.encode('utf-8') for f in fields])
但该方式不如文本模式简洁,不推荐。
内容的提问来源于stack exchange,提问作者x89
相关产品推荐
相关产品推荐

