HTML混合编码?

4

首先,提前感谢你的帮助。

我正在编写一个网络爬虫,用于解析HTML内容、剥离HTML标签,然后对从解析中检索到的文本进行拼写检查。

使用JSoup和Google拼写检查API,剥离HTML标签和拼写检查都没有引起任何问题。

我能够从URL获取内容,并将这些信息传递给一个byte[],最终转换成字符串,以便进行剥离和拼写检查。现在,我遇到了字符编码的问题。

例如,在解析http://www.testwareinc.com/时...

原始文本:我们已扩展我们的移动Web和移动应用测试服务。

...该页面使用ISO-8859-1编码,根据meta标记...

ISO-8859-1解析:我们已扩展我们的移动Web和移动应用测试服务。

...尝试使用UTF-8...

UTF-8解析:We�ve expanded our Mobile Web and Mobile App testing services.

问题:网页的HTML是否可能包含多种编码?如何检测?


处理文本很烦人。祝好运! - cdeszaq
从非常快速的浏览中(仅在浏览器中,而不是十六进制编辑器中),该字符看起来像一个有效的ISO-8559-1字符。为什么您认为这里有两种编码方式?您是否认为您的解析器可能只是吞咽了该字符? - Pekka
谢谢cdeszaq。我已经在开发这个网络爬虫大约6个月了,而解析部分一直是让我头疼的问题,因为“野生”的HTML代码在不同的网站上可能会有很大的差异。 - mikesalvia
我认为CP1252和ISO-8859-1在相互玩弄。我按照下面的说明使用了juniversalchardet,它告诉我页面上的内容实际上并不是ISO-8859-1。至少我可以找出应该使用什么来获取尽可能多的数据,如果失去一点也没关系。 - mikesalvia
4个回答

2
看起来撇号被编码为0x92字节,根据维基百科,这是一个未分配/私有代码点。
从那里开始,浏览器似乎通过假设它是非编码的1字节Unicode代码点:+0092Private Use Two),其似乎被表示为一个撇号。等等,如果它是一个字节,更可能是cp1252:浏览器必须根据所广告的CP采取回退策略,例如ISO-8859-1-> CP1252。
因此,在这里没有编码混合,但正如其他人所说的,这是一个损坏的文档。但是有一个回退启发式方法,有时会有帮助,有时不会有帮助。
如果你足够好奇,你可能想深入FF或Chrome的源代码,以了解他们在这种情况下确切的操作。

运行 juniversalchardet 时,您是正确的,我看到页面实际上是 CP1252 而不是在 meta 标签中设置的 ISO-8859-1。使用 CP1252 作为 Charset 解码 InputStream 时,撇号出现了正确的结果。 - mikesalvia

1

在一个文档中使用超过1个编码并不是混合文档,而是损坏的文档。

不幸的是,有很多网页使用与文档定义不匹配的编码,或包含一些在给定编码下有效的数据和一些无效的内容。

没有很好的处理方法。尝试猜测文档的编码可能是一种方法,但这很难且不完全可靠。在像你这样的情况下,最简单的解决方案就是忽略不能解码的部分。


谢谢回复,不幸的是,这就是我担心的事情。看起来我将能够使用juniversalchardet准确检测编码。但我确定即使这样也会导致问题。例如,使用juniversalchardet发现HTML使用的是cp1252而不是元标记中规定的ISO-8859-1。再次感谢! - mikesalvia
我不同意。混合语言非常普遍。许多手册和说明文件需要用多种语言表达。翻译引用和摘录通常是不合适的。即使在对话中,语言也经常混合使用。因此,如果任何文档不支持混合字符集,则是文档呈现框架出了问题,而不是文档设计。 - ekerner

0

Apache Tika具有编码检测器。如果您需要C++等商业替代方案,并且有能力花钱,那么还有其他选择。

我可以很肯定地保证每个网页都是以一种编码方式存在的,但很容易弄错它是哪一种


我同意,我决定使用juniversalchardet。它似乎运行良好。如果juniversalchardet找不到字符集,我可能想要研究一种使用元标签作为备选的方法。 - mikesalvia

-2

似乎是特殊字符的问题。如果有帮助,检查StringEscapeUtils.escapeHtml或任何方法。

编辑:添加此逻辑,因为他无法让代码正常工作。

public static void main(String[] args) throws FileNotFoundException {
        String asd = "’";
        System.out.println(StringEscapeUtils.escapeXml(asd)); //output - ’
    System.out.println(StringEscapeUtils.escapeHtml(asd)); //output - ’
}

@daniel 很奇怪人们认为问题的唯一解决方案是问卷调查所想的。在否定一个答案之前,你本可以等待他评论这不是他的解决方案。 - Naveen Babu
不,StringEscapeUtils无法使用。我已经尝试过了。在源代码中,撇号被编码为撇号,而不是HTML的’,因此这种方法行不通。 - mikesalvia
@spitpsu 请检查你的代码。我尝试了这个逻辑,得到了如上所示的输出。从问题中复制你的字符,再次尝试这个逻辑或者使用我的代码。代码运行良好。如果它对你有用,请接受答案。你的问题已经让我损失了4分。 - Naveen Babu
@Daniel 希望你能看到,我的方法也可以达到逻辑:P - Naveen Babu
Babu,我完全理解你的意思,是的,你编写的代码第一次执行就没有问题。我只是想说你给出的答案并不是这个问题的适当答案。我提出的问题是关于分析HTML文档字符集的,而不是如何转换特定字符,我提供的URL只是一个例子。 - mikesalvia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接