python - 如何用python获取原始字符?

标签 python unicode utf-8 ascii lxml

我正在使用 lxml 的 etree 制作个人 rss 阅读器,但在转换回原始字符时遇到问题。我期待看到“2014 年世界杯:在 Júlio César 的帮助下”:

url = 'rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'
xml = etree.parse(url)
for x in xml.findall('.//item'):
    text = x.find('.//description').text
    print text
    # 'World Cup 2014: With J\xfalio C\xe9sar\u2019s Help'
    text = text.encode('utf-8')
    print text
    # 'World Cup 2014: With J\xfalio C\xe9sar\u2019s Help'
    text = text.decode('utf-8')
    # Error: 'UnicodeEncodeError: 'ascii' codec can't encode character....'

我已阅读Python's Unicode HOWTO以及Joel's Unicode Intro但我一定错过了一些东西。

编辑:几乎有很多感谢unutbu...只需要帮助转换\u2019:

content = 'World Cup 2014: With J\xfalio C\xe9sar\u2019s Help'
html = LH.fromstring(content)
text = html.text_content()
print text
print(repr(text))
print text.encode('utf-8')

##RESULTS##
World Cup 2014: With Júlio César\u2019s Help
u'World Cup 2014: With J\xfalio C\xe9sar\\u2019s Help'
World Cup 2014: With Júlio César\u2019s Help

最佳答案

就在 UnicodeEncodeError 之前,我相信 textunicode:

text = u'World Cup 2014: With J\xfalio C\xe9sar\u2019s Help'
text = text.decode('utf-8')

重现错误消息:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xfa' in position 22: ordinal not in range(128)
<小时/>

在Python2中,lxml sometimes returns str for text, and sometimes unicode 。 事实上,如果您运行此脚本,您会看到这种不幸的行为:

import lxml.etree as ET
import urllib2

url = 'http://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'
xml = ET.parse(urllib2.urlopen(url))
for x in xml.findall('.//item'):
    text = x.find('.//description').text
    print(type(text))

打印

<type 'str'>
<type 'str'>
<type 'str'>
<type 'unicode'>
<type 'str'>
<type 'unicode'>
...

但是,当文本由纯 ASCII 值(即 0 到 127 之间的字节值)组成时,它仅返回 str

尽管一般情况下不应该对 str 进行编码,但对由以下内容组成的 str 进行编码 使用 utf-8 的 0-127 (ASCII) 范围内的字节值保留 str

因此,您实际上可以通过使用 utf-8两者进行编码,以相同的方式处理 strunicode >,就好像 text 始终是 unicode

由于 text 实际上是 HTML,因此下面我使用 lxml.html 将 HTML 简化为纯文本内容。这也可以是 strunicode。然后在打印之前对该对象文本进行编码:

import lxml.etree as ET
import lxml.html as LH
import urllib2

url = 'http://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'
xml = ET.parse(urllib2.urlopen(url))
for x in xml.findall('.//item'):
    content = x.find('.//description').text
    html = LH.fromstring(content)
    text = html.text_content()
    print(text.encode('utf-8'))

请注意,在 Python3 中,lxml 始终返回 unicode,因此恢复了思想的纯粹性。

<小时/>

UnicodeEncodeError 是如何发生的:

text = u'World Cup 2014: With J\xfalio C\xe9sar\u2019s Help'
text = text.decode('utf-8')
# Error: 'UnicodeEncodeError: 'ascii' codec can't encode character....'

首先请注意,即使您要求 Python 解码 文本,这也是一个 UnicodeEncodeError。 另请注意,错误消息显示 Python 正在尝试使用 ascii 编解码器。

这是一个典型的迹象,表明问题与 Python2's automatic conversion between str and unicode. 有关。

假设text是unicode。如果你打电话

text.decode('utf-8')

那么你要求 Python 执行一个禁忌——解码 unicode。然而,Python2 会尝试先使用 ascii 编解码器对 unicode 进行静默编码,然后再使用 utf-8 进行解码。 strunicode 之间的这种自动转换旨在方便处理仅在 ASCII 范围内的值的 str 和 unicode,但它会导致精神上的不清晰,因为它鼓励程序员忘记 str 和 unicode 之间的差异,它仅有时有效 - 当值在 ASCII 范围内时。当值超出 ASCII 范围时,您会收到错误 - 这就是您所遇到的情况。

在Python3中,bytesstr之间没有自动转换(或者用Python2的说法是strunicode,分别)。当您尝试编码 bytes 或解码 str 时,Python 只会引发错误。精神清晰​​度得以恢复,但代价是迫使程序员注意类型。然而,正如这个问题所示,即使使用 Python2,这种成本也是不可避免的。

关于python - 如何用python获取原始字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24497802/

相关文章:

Python3 : cassandra. cluster.NoHostAvailable : ("Unable to connect to any servers using keyspace ' test '", [' 127. 0.0.1']) 使用execute_async future

mysql - html 页面显示西里尔字母 OK,如果包含 charset=windows-1251,但不包含 utf-8

html - IRI 作为 HTML 属性值有效吗?

mysql - 从 R 中的 MySQL 获取 UTF-8 文本返回 "????"

python - 类型错误 : argument 1 must have a "write" method

python - 如何使用多个条件过滤 Python 列表?

python - 在 Django 模板中通过 {% url %} 传递命名模式参数

perl - 有没有比 kakasi 库更适合 gojûon 校对的东西?

.net - 确定TextFile编码?

powershell - 在Windows下将unicode粘贴到vim中的问题