解析HTML时出现Python Unicode和ASCII问题

时间:2016-05-27 17:03:42

标签: python html unicode encoding utf-8

我正在尝试在Chrome网络浏览器上编写类似于Ctrl + S的Python脚本,它会保存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时,有输出(我注意到底部的中文写作)。

1 个答案:

答案 0 :(得分: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中情况并非如此。

话虽如此,这就是上面的片段:

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

外卖是这样的:

  1. 早期对读取/解码进行解码,最后对写入/编码进行编码
  2. str个对象用于字节,将unicode个对象用于文本