Python如何处理URL中的XML数据

1次阅读

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

Python如何处理URL中的XML数据

urllib.requestrequests 获取 URL 上的 XML 内容

XML 数据通常以纯文本形式暴露在 http 响应体中,不是 json 那种结构化 API,所以第一步是可靠地拿到原始字符串。直接用 urllib.request.urlopen() 容易忽略编码和重定向问题;推荐用 requests,它默认处理 gzip、自动解码、支持会话复用。

  • 如果服务器返回 Content-Type: application/xmltext/xmlresponse.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.ElementTreepython 标准库中最轻量、最常用的选择,适合结构清晰、无 DTD/命名空间冲突的 XML。它不校验 schema,也不处理实体引用(如  ),遇到就报 ParseError

  • ET.fromstring(xml_content) 直接解析字符串;若内容太大,改用 ET.parse(io.StringIO(xml_content)) 或流式读取文件
  • 路径表达式(XPath)支持有限:只支持 //tagtag/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,即使标签存在。

  • 必须显式传入命名空间字典,键是前缀(可自定义),值是 URI;例如 {"a": "http://www.w3.org/2005/Atom"}
  • 所有 XPath 中的标签都要加前缀:a:titlea: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() 就会静默失败或抛出难以定位的异常。

text=ZqhQzanResources