遍历DOM树时Jsoup节点哈希码冲突

Posted

技术标签:

【中文标题】遍历DOM树时Jsoup节点哈希码冲突【英文标题】:Jsoup node hash code collision when traversing DOM tree 【发布时间】:2015-05-12 07:19:01 【问题描述】:

我正在使用 java jsoup 构建 html DOM 树,其中使用了Node.hashCode()。但是我发现在遍历DOM树的时候有很多hash码冲突,使用如下代码:

doc.traverse(new NodeVisitor()

    @Override
    public void head(Node node, int depth) 

        System.out.println("node hash: "+ node.hashCode());

        /* some other operations */
    

    @Override
    public void tail(Node node, int depth) 
        // TODO Auto-generated method stub

        /* some codes */
    

因此,当它运行时,即使在前几个输出中,我也会看到许多相同的哈希码。

哈希码非常大,我不希望出现这种奇怪的行为。我使用了 jsoup-1.8.1。 任何意见将不胜感激,谢谢。

【问题讨论】:

出于兴趣,节点的内容是否相同?如果 1)哈希是从内容创建的,或者 2)它识别重复以减少内存占用,那将会很有趣。 我使用的html页面来自亚马逊(我想分析他们产品页面中的字段)。我认为每一个在内容方面都是独一无二的。即使有相同内容的节点,也不可能那么多。 您能否提供一些重现此行为的 html 示例? @alkis ,我可以重现,看我的回答。 【参考方案1】:

注意:此错误已在 jSoup 1.8.2 中修复,因此我的回答不再相关。

这可能是 jSoup 源代码中的错误。来自source:

@Override
public int hashCode() 
   int result = parentNode != null ? parentNode.hashCode() : 0;
   // not children, or will block stack as they go back up to parent)
   result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
   return result;

我不是 Java 专家,但是如果它们具有相同的属性,这看起来可以为不同的节点返回相同的值。 (同样的家长,感谢@alkis 的评论)


编辑:我可以重现这个。使用以下 HTML:

<html>
    <head>
    </head>
    <body>
        <div style="blah">TODO: write content</div>
        <div style="blah">Nothing here</div>
        <p style="test">Empty</p>
        <p style="nothing">Empty</p>
    </body>
</html>

还有如下代码:

String html = //HTML posted above

Document doc = Jsoup.parse(html);

Elements elements = doc.select("[style]");
for (Element e : elements) 
   System.out.println(e.hashCode());

它给出:

-148184373
-148184373
-1050420242
2013043377

在计算哈希时似乎完全忽略了内容文本,只有属性是重要的。


您可能应该实施自己的解决方法。


错误报告here。

【讨论】:

显然这两个&lt;div style="blah"&gt;TODO: write content&lt;/div&gt;&lt;div style="blah"&gt;Nothing here&lt;/div&gt; 具有相同的哈希值。它们具有相同的属性 (style="blah") 和相同的父级。是的,这一定是一个错误。你应该归档。很好的发现。赞一个! 感谢您的报告,我已经解决了这个问题。它将在 jsoup 1.8.2 中

以上是关于遍历DOM树时Jsoup节点哈希码冲突的主要内容,如果未能解决你的问题,请参考以下文章

快速简单的哈希码组合

为所有字谜生成相同的唯一哈希码

iOS中的哈希表

开散列的实现--哈希冲突

开散列的实现--哈希冲突

MySql数据库索引