我正在抓一些网站,编码是unicode:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
要做到这一点,我使用urllib:
html = unicode(urllib.openurl(url).read(), 'utf-8')
有时一些unicode字符将被随机替换为两个0xFFFD字符。我想用4个字节编码的单个字符会被破坏,并且对于两个2字节的一半被替换为两个0xFFFD。这种替换的可能性非常低 - 可能会替换500 000中的一个角色。似乎只有非ascii字符被破坏了。
当在浏览器中呈现相同的页面时,我没有观察到任何这些替换。
如何识别哪个部分引入了问题?它是发送损坏字节的服务器还是没有正确读取它们的客户端?
@John Machin:
所以我认为错误是在Web服务器端引入的。我会试着忽略它们。
答案 0 :(得分:0)
浏览器为纠正无效字符做了很多魔术。尝试查看.read()
返回的原始字节,并检查源页面是否包含无效字符。例如,有时页面会使用latin-1或类似字母编码重音字母,而其他字符则使用utf-8编码。
答案 1 :(得分:0)
我看到两种可能性。
.read()
调用最后只返回多字节序列的一部分,则部分序列将被U + FFFD替换。请参阅UTF-8编码的this explanation。可以使用编码的代码点的第一个字节中的前导1位数轻松检测部分字节序列,这样您就可以解码除部分序列之外的所有内容,并在下一次读取时继续。代码点U + 007F和更低版本用一个字节编码,因此这个问题永远不会影响那些代码点。charset=utf-8
声明,但实际上并未使用UTF-8编码。然后,任何不恰好是有效的UTF-8序列的字节将由U + FFFD替换。如果您发布从服务器获得的一些示例字节序列,对于每个单独的读取操作,以及由这些字节产生的字符串,我们可以更加确定发生了什么。
答案 2 :(得分:0)
服务器和客户端完全有可能忠实地再现早期的填充结果。场景:有人在cp1252
(通常的嫌疑人)中编码了文本。他们使用带有“替换”选项的UTF-8对其进行解码 - 引入u“\ ufffd” - 然后对结果进行编码。
示例原始文字:Seine Füße sind wund.
>>> original = "Seine F\xfc\xdfe sind wund." # encoded in cp1252
>>> ucode1 = original.decode('utf8', 'replace')
>>> ucode1
u'Seine F\ufffd\ufffde sind wund.'
>>> input_to_server = ucode1.encode('utf8')
>>> input_to_server
'Seine F\xef\xbf\xbd\xef\xbf\xbde sind wund.'
>>> observed_result = unicode(input_to_server, 'utf8')
>>> observed_result
u'Seine F\ufffd\ufffde sind wund.'
>>>
在任何情况下,如果您不提供更多信息,所有答案都将基于猜测,例如:
什么版本的Python(正好请,例如2.7.1)
您正在检查网址的浏览器是什么?什么是“观点 文字“告诉你?
你说“我在同一页面上没有观察到任何替换
在浏览器中呈现。“好的,所以您从代码和浏览器中看到rhubarb \ufffd\ufffd
artichoke
rhubarb
PLEASE-TELL-US-WHAT-YOU-SEE-HERE artichoke
- 请透露。
你有什么理由不能透露你所拥有的网址 问题?