推荐用 requests 获取 xml 内容并手动解码,用 xml.etree.elementtree 解析;遇命名空间需传入字典并加前缀;须捕获 parseerror 并预清洗非法结构。

用 urllib.request 或 requests 获取 URL 上的 XML 内容
XML 数据通常以纯文本形式暴露在 HTTP 响应体中,不是 JSON 那种结构化 API,所以第一步是可靠地拿到原始字符串。直接用 urllib.request.urlopen() 容易忽略编码和重定向问题;推荐用 requests,它默认处理 gzip、自动解码、支持会话复用。
- 如果服务器返回
Content-Type: application/xml或text/xml,response.text一般能正确解码;但若响应头缺失或错误(比如只写text/plain),得手动指定response.content.decode("utf-8") - 遇到中文乱码?先检查
response.encoding,再试response.apparent_encoding,最后 fallback 到chardet.detect(response.content)["encoding"] - 别用
response.json()—— 这会抛JSONDecodeError,XML 不是 JSON
import requests <p>url = "<a href="https://www.php.cn/link/73693853a57a48e11cdea2a77e88a501">https://www.php.cn/link/73693853a57a48e11cdea2a77e88a501</a>" response = requests.get(url, timeout=10) response.raise_for_status() # 抛出 4xx/5xx 错误 xml_content = response.content.decode(response.encoding or "utf-8")
用 xml.etree.ElementTree 解析并提取数据
xml.etree.ElementTree 是 Python 标准库中最轻量、最常用的选择,适合结构清晰、无 DTD/命名空间冲突的 XML。它不校验 schema,也不处理实体引用(如 ),遇到就报 ParseError。
- 用
ET.fromstring(xml_content)直接解析字符串;若内容太大,改用ET.parse(io.StringIO(xml_content))或流式读取文件 - 路径表达式(XPath)支持有限:只支持
//tag、tag/sub、.[@attr="val"],不支持namespace:tag(除非手动注册命名空间) - 获取属性值用
elem.get("attr_name"),不是elem["attr_name"];获取文本用elem.text.strip(),注意前后空白和换行
import xml.etree.ElementTree as ET
<p>root = ET.fromstring(xml_content)
titles = [item.find("title").text.strip() for item in root.findall(".//item") if item.find("title") is not None]处理带命名空间的 XML(如 Atom、RSS、SOAP)
很多公开 XML 接口(如 GitHub Atom feed、气象局 SOAP 服务)使用命名空间,例如 <feed xmlns="http://www.w3.org/2005/Atom"></feed>。不处理命名空间会导致 find() 返回 None,即使标签存在。
第一步】:将安装包中所有的文件夹和文件用ftp工具以二进制方式上传至服务器空间;(如果您不知如何设置ftp工具的二进制方式,可以查看:(http://www.shopex.cn/support/qa/setup.help.717.html)【第二步】:在浏览器中输入 http://您的商店域名/install 进行安装界面进行安装即可。【第二步】:登录后台,工具箱里恢复数据管理后台是url/sho
- 必须显式传入命名空间字典,键是前缀(可自定义),值是 URI;例如
{"a": "http://www.w3.org/2005/Atom"} - 所有 XPath 中的标签都要加前缀:
a:title、a:entry,不能省略 - 如果不知道命名空间 URI,先打印
root.tag—— 它通常是{http://...}feed这种格式,花括号里就是 URI
ns = {"a": "http://www.w3.org/2005/Atom"}
entries = root.findall("a:entry", ns)
for entry in entries:
title_elem = entry.find("a:title", ns)
if title_elem is not None:
print(title_elem.text.strip())遇到 malformed XML 或外部实体时怎么办
真实场景中常遇到:XML 声明缺失、编码声明错误、含未定义实体(©)、DOCTYPE 引用远程 DTD(引发 XXE 漏洞)。标准 ElementTree 默认禁用外部实体,但依然可能因格式错乱崩溃。
立即学习“Python免费学习笔记(深入)”;
- 永远用
try/except ET.ParseError包裹解析逻辑,不要假设输入合法 - 拒绝处理含
DOCTYPE的 XML,除非你明确控制数据源;可用正则预清洗:re.sub(r"^>]*>", "", xml_content) - 需要健壮解析(如 HTML 混合 XML、标签不闭合)?换
lxml库,它自带修复模式:from lxml import etree; doc = etree.fromstring(xml_content, parser=etree.XMLParser(recover=True))
实际跑通的关键往往不在“怎么解析”,而在“怎么让原始字符串进得来、不出错、不被截断”。网络请求的编码协商、命名空间的显式声明、以及对非法结构的防御性清洗,这三步漏掉任何一环,ET.fromstring() 就会静默失败或抛出难以定位的异常。









