【问题标题】:parsing XML file gets UnicodeEncodeError (ElementTree) / ValueError (lxml)解析 XML 文件获取 UnicodeEncodeError (ElementTree) / ValueError (lxml)
【发布时间】:2013-03-15 08:39:06
【问题描述】:

我向CareerBuilder API 发送 GET 请求:

import requests

url = "http://api.careerbuilder.com/v1/jobsearch"
payload = {'DeveloperKey': 'MY_DEVLOPER_KEY',
           'JobTitle': 'Biologist'}
r = requests.get(url, params=payload)
xml = r.text

然后返回一个看起来像 this 的 XML。但是,我无法解析它。

使用lxml

>>> from lxml import etree
>>> print etree.fromstring(xml)

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    print etree.fromstring(xml)
  File "lxml.etree.pyx", line 2992, in lxml.etree.fromstring (src\lxml\lxml.etree.c:62311)
  File "parser.pxi", line 1585, in lxml.etree._parseMemoryDocument (src\lxml\lxml.etree.c:91625)
ValueError: Unicode strings with encoding declaration are not supported.

ElementTree:

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    print ET.fromstring(xml)
  File "C:\Python27\lib\xml\etree\ElementTree.py", line 1301, in XML
    parser.feed(text)
  File "C:\Python27\lib\xml\etree\ElementTree.py", line 1641, in feed
    self._parser.Parse(data, 0)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 3717: ordinal not in range(128)

所以,即使 XML 文件以

开头
<?xml version="1.0" encoding="UTF-8"?>

我的印象是它包含不允许的字符。如何使用 lxmlElementTree 解析此文件?

【问题讨论】:

标签: python xml python-requests lxml elementtree


【解决方案1】:

您正在使用 decoded unicode 值。请改用r.raw raw response data

r = requests.get(url, params=payload, stream=True)
r.raw.decode_content = True
etree.parse(r.raw)

直接从响应中读取数据;请注意stream=True 选项到.get()

设置 r.raw.decode_content = True 标志可确保原始套接字将为您提供解压缩的内容,即使响应是 gzip 或 deflate 压缩。

您没有流式传输响应;对于较小的 XML 文档,可以使用 response.content attribute,它是未解码的响应正文:

r = requests.get(url, params=payload)
xml = etree.fromstring(r.content)

XML 解析器总是期望字节作为输入,因为 XML 格式本身决定了解析器如何将这些字节解码为 Unicode 文本。

【讨论】:

  • 是否有理由使用etree.parse(r.raw) 而不是etree.fromstring(r.content)
【解决方案2】:

更正!

请看下面我是怎么弄错的。基本上,当我们使用 .text 方法时,结果是一个 unicode 编码的字符串。使用它会在 lxml 中引发以下异常

ValueError: 带有编码声明的 Unicode 字符串不是 支持的。请使用不带字节输入或 XML 片段 声明。

这基本上意味着@martijn-pieters 是正确的,我们必须使用.content 返回的原始响应

不正确的答案(但可能有人会感兴趣)

对于任何有兴趣的人。我认为发生此错误的原因可能是请求进行的无效猜测,如Response.text documentation 中所述:

响应的内容,以 unicode 表示。

如果 Response.encoding 为 None,则使用 chardet 猜测编码。

响应内容的编码完全基于 HTTP 标头,严格遵循 RFC 2616。如果你能带 利用非 HTTP 知识更好地猜测 编码,您应该在访问之前适当地设置 r.encoding 这个属性。

因此,在此之后,还可以通过使用r.encoding = 'UTF-8' 显式设置编码来确保请求的r.text 正确编码响应内容

这种方法在使用 lxml 解析之前添加了另一个验证,即接收到的响应确实是正确的编码。

【讨论】:

    【解决方案3】:

    了解这个问题已经得到了答案,我在 Python3 上遇到了类似的问题,它在 Python2 上运行良好。我的解决方案是:str_xml.encode(),然后是xml = etree.fromstring(str_xml),然后是标签和属性的解析和提取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 2021-02-08
      • 2021-09-07
      • 2013-03-14
      • 2017-01-16
      • 2019-03-23
      相关资源
      最近更新 更多