【问题标题】:Python Unicode and ASCII issues when parsing HTML解析 HTML 时出现 Python Unicode 和 ASCII 问题
【发布时间】:2016-09-26 02:43:23
【问题描述】:

我正在尝试编写一个 Python 脚本,其作用类似于 Chrome 网络浏览器上的 Ctrl + S,它保存 HTML 页面,下载网页上的任何链接,最后,用本地路径替换链接的 URI磁盘。

下面发布的代码尝试将 CSS 文件中的 URI 替换为我计算机上的本地路径。

我在尝试解析不同的网站时遇到了一个问题,这让我有点头疼。

我原来的错误码是UnicodeDecodeError: 'ascii' codec can't decode byte 0xa3 in position 13801: ordinal not in range(128)

url = 'http://www.s1jobs.com/job/it-telecommunications/support/edinburgh/620050561.html'

response = urllib2.urlopen(url)
webContent = response.read()
dest_dir = 'C:/Users/Stuart/Desktop/' + title
for f in glob.glob(r'./*.css'):
    newContent = webContent.replace(cssUri, "./" + title + '/' + cssFilename)
    shutil.move(f, dest_dir)

当我尝试打印 newContent 或将其写入文件时,此问题仍然存在。我试图按照这个堆栈问题UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 13: ordinal not in range(128) 中的最佳答案并修改了我的行

newContent = webContent.decode('utf-8').replace(cssUri, "./" + title + '/' + cssFilename)

newContent = webContent.decode(utf-8).replace(cssUri, "./" + title + '/' + cssFilename)。我还尝试了.decode(utf-16) 和 32,我分别得到了这些错误代码:13801: invalid start bytebyte 0x0a in position 44442: truncated data,最后是can't decode bytes in position 0-3: code point not in range(0x110000)

有人知道我应该如何解决这个问题吗?我必须补充一点,当我打印变量 webContent 时,会有输出(我注意到底部有中文)。

【问题讨论】:

  • 我建议您观看和阅读nedbatchelder.com/text/unipain.html,特别注意“Unicode 三明治”。
  • 你是python2还是3?
  • @ThomasTu Python 2.7,我也会看看那个 Unicode 三明治文章

标签: python html unicode encoding utf-8


【解决方案1】:

这将解决您的问题

使用webContent.decode('utf-8', errors='ignore')webContent.decode('latin-1')

webContent[13801:13850] 有一些奇怪的字符。忽略它们。

忽略此处的所有内容


这有点像在黑暗中拍摄,但试试这个:

在文件的顶部,

from __future__ import unicode_literals
from builtins import str

看起来正在发生的事情是您正在尝试解码一个可能是 python 2.7 str 对象的 python 对象,原则上它应该是一些解码的文本对象。

简要说明

在默认的python 2.7内核中:

(iPython 会话)

In [1]: type("é") # By default, quotes in py2 create py2 strings, which is the same thing as a sequence of bytes that given some encoding, can be decoded to a character in that encoding.
Out[1]: str

In [2]: type("é".decode("utf-8")) # We can get to the actual text data by decoding it if we know what encoding it was initially encoded in, utf-8 is a safe guess in almost every country but Myanmar.
Out[2]: unicode

In [3]: len("é") # Note that the py2 `str` representation has a length of 2.  There's one byte for the "e" and one byte for the accent.  
Out[3]: 2

In [4]: len("é".decode("utf-8")) # the py2 `unicode` representation has length 1, since an accented e is a single character
Out[4]: 1

python 2.7 中的其他一些注意事项:

  • "é"str("é") 相同
  • u"é""é".decode('utf-8')unicode("é", 'utf-8') 相同
  • u"é".encode('utf-8')str("é") 相同
  • 您通常使用 py2 str 调用 decode,并使用 py2 unicode 进行编码。
    • 由于早期的设计问题,您可以同时调用其中任何一个,尽管这实际上没有任何意义。
    • 在 python3 中,str 与 python2 unicode 相同,无法再解码,因为根据定义,字符串是解码后的字节序列。默认情况下,它使用 utf-8 编码。
  • 在 ascii 编解码器中编码的字节序列的行为与其解码的对应物完全相同。
    • 在没有未来导入的 python 2.7 中:type("a".decode('ascii')) 提供一个 unicode 对象,但这与str("a") 的行为几乎相同。在 python3 中不是这种情况。

话虽如此,这就是上面的 sn-ps 的作用:

  • __future__ 是一个由核心 python 团队维护的模块,它将 python3 功能反向移植到 python2 以允许您在 python2 中使用 python3 习语。
  • from __future__ import unicode_literals 具有以下效果:
    • 没有未来导入"é"str("é") 相同
    • 未来导入"é" 在功能上与unicode("é") 相同
  • builtins 是一个由核心 python 团队批准的模块,它包含在 python2 中使用 python3 习语和 python3 api 的安全别名。
    • 由于我以外的原因,包本身被命名为“未来”,所以要安装你运行的builtins模块:pip install future
  • from builtins import str 具有以下效果:
    • str 构造函数现在提供您认为的功能,即 python2 unicode 对象形式的文本数据。所以它在功能上和str = unicode是一样的
    • 注意:Python3 str 在功能上与 Python2 unicode 相同
    • 注意:要获取字节,您可以使用“字节”前缀,例如b'é'

要点是这样的:

  1. 在读时解码/在早期解码,在写时编码/在最后编码
  2. 对字节使用str对象,对文本使用unicode对象

【讨论】:

    猜你喜欢
    • 2016-04-17
    • 2013-09-16
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多