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

Python Unicode and ASCII issues when parsing HTML

我尝试在ChromeWeb浏览器上编写一个类似于ctrl+s的python脚本,它保存HTML页面,下载网页上的任何链接,最后用磁盘上的本地路径替换链接的uri。

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

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

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

1
2
3
4
5
6
7
8
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)

当我尝试打印新内容或将其写入文件时,此问题仍然存在。我试图遵循这个堆栈问题unicodedecodeerror的最上面的答案:"ascii"编解码器无法解码位置13中的字节0xe2:序号不在范围(128)内,并修改了我的行

1
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时,会有输出(不过我注意到底部有中文书写)。


这会解决你的问题

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

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

忽略下面的所有内容

这是对黑暗的一种射击,但是尝试一下:

在你的文件顶部,

1
2
from __future__ import unicode_literals
from builtins import str

似乎您正试图解码一个可能是python 2.7str对象的python对象,原则上,该对象应该是某种已解码的文本对象。

简要说明

在默认的python 2.7内核中:

(IPython会议)

1
2
3
4
5
6
7
8
9
10
11
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

在Python2.7中还有一些值得注意的地方:

  • "é"str("é")相同。
  • u"é""é".decode('utf-8')unicode("é", 'utf-8')相同。
  • u"é".encode('utf-8')str("é")相同。
  • 您通常使用py2-str调用decode,并使用py2-unicode进行编码。
    • 由于早期的设计问题,您可以两者都调用,即使这没有任何意义。
    • 在python3中,与python2 unicode相同的str不能再被解码,因为一个按定义的字符串是一个经过解码的字节序列。默认情况下,它使用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习语与python3 API一起使用。
    • 由于我以外的原因,包本身被命名为"未来",因此要安装您运行的builtins模块:pip install future
  • from builtins import str具有以下作用:
    • str构造函数现在给出了您认为它所做的工作,即以python2 unicode对象的形式提供文本数据。所以它在功能上与str = unicode相同。
    • 注:python3 str功能与python2 unicode相同。
    • 注:要获取字节,可以使用"字节"前缀,例如b'é'

外卖是这样的:

  • 在读取/解码时进行解码,在结束时进行写入/编码
  • 字节使用str对象,文本使用unicode对象