解析不可读字符

1 投票
1 回答
619 浏览
提问于 2025-04-18 04:21

我正在尝试解析一个API的响应数据,但里面有些字符让Python处理起来有点麻烦。

API的响应内容是:电价 | 19.52¢/千瓦时(2014年1月1日)天然气价格 | 每千立方英尺11.05美元(2014年1月15日)取暖油价格 | 每加仑4.338美元(2014年3月17日)丙烷价格 | 每加仑3.968美元(2014年3月17日)

错误发生在“每千瓦时的美分”这个字符上。

完整错误信息是:UnicodeEncodeError: 'ascii' codec can't encode character u'\xa2' in position 25: ordinal not in range(128)

在终端中显示的响应内容是:电价 | 19.52\xa2/千瓦·时 (2014年1月1日)\n天然气价格 | 每千立方英尺11.05美元 (2014年1月15日)\n取暖油价格 | 每加仑4.338美元 (2014年3月17日)\n丙烷价格 | 每加仑3.968美元 (2014年3月17日)

我该如何处理这些问题字符周围的数据呢?我只需要里面的数字值,不需要完整的文本。谢谢你的帮助。

编辑:

导致错误的代码:

search('electricity price | {:d}', energy)

我也尝试了:

search('electricity price | {:f}', energy)

结果也差不多。energy是一个变量,里面存储了上面提到的完整字符串。

编辑2:

包括API调用的完整代码:

client = wolframalpha.Client('apikey')
energy_query = 'utilities prices in ' + city + ' ' + state_abbr
res = client.query(energy_query)


energy = (next(res.results).text)

search('electricity price | {:d}', energy)

完整的错误追踪信息:

File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-    packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site- packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/nulife.py", line 120, in index
search('electricity price | {:d}', energy)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-    packages/parse.py", line 1041, in search
return Parser(format, extra_types=extra_types).search(string, pos, endpos)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-    packages/parse.py", line 678, in search
return self._generate_result(m)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-    packages/parse.py", line 699, in _generate_result
fixed_fields[n] = self._type_conversions[n](fixed_fields[n], m)
File "/Users/aaronpardes/Dropbox/Python/nuLife2/newlifenv/lib/python2.7/site-packages/parse.py", line 375, in f
if string[0] == '-':
TypeError: 'NoneType' object has no attribute '__getitem__'

1 个回答

4

energy 已经是一个 Unicode 对象了;如果你试图在它上面调用 .decode(),会先隐式地进行一次 编码(默认使用 ASCII 编码):

>>> energy = u'19.52¢/kW·h'
>>> energy.decode('windows-1252')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/encodings/cp1252.py", line 15, in decode
    return codecs.charmap_decode(input,errors,decoding_table)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa2' in position 5: ordinal not in range(128)

注意到异常;解码一个 Unicode 字符串时触发了 UnicodeEncodeError 错误。

这是设计使然,wolframalpha 使用 ElementTree 来解析 XML 响应,这总是会给你 Unicode 对象。

在你更新之后,我查看了 parse 库的源代码,我担心你发现了代码中的一个 bug;它们没有对你输入的字面字符串中的正则表达式元字符进行转义。如果你转义 | 字符,它就能正常工作:

>>> search('electricity price \\| {:f}', u'electricity price | 19.52¢/kW·h')
<Result (19.52,) {}>

我已经在 parse 项目上提交了一个 bug 报告

请注意,这个库可能仅限于解析 ASCII 文本;至少不要尝试将 ¢/kW·h 作为单词字符进行匹配。

更新parse 版本 1.6.4 已经发布,修复了这个特定的 bug。

撰写回答