我在Windows 8中使用python 3.3.0。
requrl = urllib.request.Request(url)
response = urllib.request.urlopen(requrl)
source = response.read()
source = source.decode('utf-8')
如果网站有utf-8
字符集,它会正常运行,但如果它有iso-8859-1
或任何其他charset
,该怎么办?意味着我可能有不同的网站网址与不同的字符集。
那么,如何处理多个charset?
现在让我告诉你我在努力解决这个问题时的努力,如:
b1 = b'charset=iso-8859-1'
b1 = b1.decode('iso-8859-1')
if b1 in source:
source = source.decode('iso-8859-1')
它给了我一个像TypeError: Type str doesn't support the buffer API
这样的错误
所以,我假设它正在考虑将b1视为字符串!这不是正确的方法! :(
请不要说在源代码中手动更改字符集或者您是否阅读过python文档! 我已经尝试过将我的脑袋放到python 3文档中,但仍然没有运气,或者我可能没有选择正确的模块/内容来阅读!
答案 0 :(得分:5)
在Python 3中,str
实际上是一系列unicode字符(相当于Python 2中的u'mystring'
语法)。从response.read()
返回的是一个字节字符串(一个字节序列)。
您的b1 in source
失败的原因是您试图在字节字符串中找到 unicode字符序列。这没有任何意义,所以它失败了。如果你取出行b1.decode('iso-8859-1')
,它应该可以工作,因为你现在正在比较两个字节序列。
现在回到您真正的基础问题。要支持多个字符集,您需要确定字符集,以便将其解码为Unicode字符串。这很棘手。通常,您可以检查响应的Content-Type
标头。 (请参阅下面的规则。)但是,这么多网站在标题中声明了错误的编码,我们必须开发其他complicated encoding sniffing rules for html。请阅读该链接,以便您了解这是一个难题!
我建议你:
lxml
或html5lib
)并让它们处理确定编码。他们经常为文档类型实现正确的charset-sniffing算法。如果这些都不起作用,您可以更积极地使用像chardet这样的库来检测编码,但根据我的经验,错误地为其网页提供服务的人是如此无能,以至于他们生成混合编码文档,无论你做什么,你都会得到垃圾字符!
以下是解释content-type
标题中声明的字符集的规则。
(请注意,html5规范通过查找优先于 Content-Type标头的UTF8和UTF16字节标记来故意违反w3c规范。请阅读该编码检测算法链接,看看为什么我们可以没有好东西......)
答案 1 :(得分:2)
这里的一个大问题是,在很多情况下,您无法确定网页的编码,即使它定义了一个字符集。我已经看到足够的页面声明了一个字符集,但实际上存在于另一个字符集中,或者在其Content-Type标题中有不同的字符集,然后是在他们的元标记或xml声明中。
在这种情况下,chardet
可能会有所帮助。
答案 2 :(得分:1)
您正在检查str
对象中是否包含bytes
字节:
>>> 'df' in b'df'
Traceback (most recent call last):
File "<pyshell#107>", line 1, in <module>
'df' in b'df'
TypeError: Type str doesn't support the buffer API
所以,是的,它认为b1
为str
,因为您已使用特定编码将bytes
对象解码为str
对象。相反,您应该检查b1
的原始值。目前尚不清楚为什么要对其进行.decode
。
答案 3 :(得分:1)
查看HTML standard, Parsing HTML documents, Determine character set(HTML5足以满足我们的目的)。
有一种算法可供选择。对于您的目的归结为以下内容: