【问题标题】:web page change detection网页变化检测
【发布时间】:2011-04-23 05:50:41
【问题描述】:

目前我正在做我最后一个学期的项目/论文,我想在“检测网络中的网页变化”上做这件事。我已经阅读了两篇关于这个主题的论文,但我有些困惑

1.在一篇题为

的论文中

一种增强的网页变化检测算法,用于加速移动网页转码1

写好了

首先从 HTML 文档中生成子树,其中每个子树根据其标记内容被赋予一个标记。

我的问题是如何从 HTML 文档生成子树?这样做的技术是什么。下一个问题是“根据标签内容打分”是什么意思。

2.请看这里的图片!! General diagram of proposed approach

在“计算最相似的子树”框中,匹配是如何完成的?在另一篇题为

的论文中

一种基于优化匈牙利算法的高效网页变化检测系统[2]

使用匈牙利算法进行匹配,引用了题为

的论文中的一句话

一种基于散列和减少相似度计算次数的快速HTML网页变化检测方法[3]

[2] 中的方法使用 O(N3) 匈牙利算法来计算加权二分图上的最大加权匹配,并且运行时间在 O(N2 x N1 3) ,其中 N1 和 N2 分别是旧页面和新页面中的节点数(更改)页面。”我的问题是,由于子树正在形成为什么要添加权重,以及如何添加它们?

感谢您阅读我的问题/困惑,我真的需要帮助,而且很快,请任何人帮助我解决这个问题,我将永远感激不尽。

【问题讨论】:

    标签: java subtree hungarian-notation


    【解决方案1】:

    我认为我有一个非常简单快捷的方法。

    我最近编写并发布了 jqgram 用于计算树编辑距离近似,它带有一个易于使用的 API,用于比较类似 DOM 的结构、JSON 结构或您自己设计的树结构: p>

    https://github.com/hoonto/jqgram

    基于原始论文:http://www.vldb2005.org/program/paper/wed/p301-augsten.pdf 最初移植自 Python 实现:https://github.com/Sycondaman/PyGram

    jqgram树编辑距离近似模块实现了服务器端和浏览器端应用的PQ-Gram算法; O(n log n) 时间和 O(n) 空间性能,其中 n 是节点数。 PQ-Gram 近似比通过 Zhang & Shasha、Klein、Guha 或其他人获得真正的编辑距离要快得多,他们提供的真正编辑距离算法最多执行 O(n^2) 或 O(n^3),具体取决于你看的是哪种算法。

    这是我将如何使用 jqgram 来应对您的具体挑战的开始,我直接从 github 上的 README 中摘取。要回答您的问题之一,您可以在 jQuery 等库(如下所示)中使用 DOM 作为其自己的树结构,或者复制它或从 Cheerio 或其底层 HTML 解析库或其任何组合中的 html 字符串生成一个(jqgram 为您提供了这种灵活性)。此处的示例将当前页面中的 DOM 与从字符串生成的 Cheerio 表示进行比较 - 您已知的参考。

    // This could probably be optimized significantly, but is a real-world
    // example of how to use tree edit distance in the browser.
    
    // For cheerio, you'll have to browserify, 
    // which requires some fiddling around
    // due to cheerio's dynamically generated 
    // require's (good grief) that browserify 
    // does not see due to the static nature 
    // of its code analysis (dynamic off-line
    // analysis is hard, but doable).
    //
    // Ultimately, the goal is to end up with 
    // something like this in the browser:
    var cheerio = require('./lib/cheerio');
    
    // But you could use jQuery for both sides of this comparison in which case your
    // lfn and cfn callback functions become the same for both roots. 
    
    // The easy part, jqgram:
    var jq = require("../jqgram").jqgram;
    
    // Make a cheerio DOM:
    var html = '<body><div id="a"><div class="c d"><span>Irrelevent text</span></div></div></body>';
    
    var cheeriodom = cheerio.load(html, {
        ignoreWhitespace: false,
        lowerCaseTags: true
    });
    
    // For ease, lets assume you have jQuery laoded:
    var realdom = $('body');
    
    // The lfn and cfn functions allow you to specify
    // how labels and children should be defined:
    jq.distance({
        root: cheeriodom,
        lfn: function(node){ 
            // We don't have to lowercase this because we already
            // asked cheerio to do that for us above (lowerCaseTags).
            return node.name; 
        },
        cfn: function(node){ 
            // Cheerio maintains attributes in the attribs array:
            // We're going to put id's and classes in as children 
            // of nodes in our cheerio tree
            var retarr = []; 
            if(!! node.attribs && !! node.attribs.class){
                retarr = retarr.concat(node.attribs.class.split(' '));
            }
            if(!! node.attribs && !! node.attribs.id){
                retarr.push(node.attribs.id);
            }
            retarr = retarr.concat(node.children);
            return  retarr;
        }
    },{
        root: realdom,
        lfn: function(node){ 
            return node.nodeName.toLowerCase(); 
        },
        cfn: function(node){ 
            var retarr = [];
            if(!! node.attributes && !! node.attributes.class && !! node.attributes.class.nodeValue){
                retarr = retarr.concat(node.attributes.class.nodeValue.split(' '));
            }
            if(!! node.attributes && !! node.attributes.id && !! node.attributes.id.nodeValue) {
                retarr.push(node.attributes.id.nodeValue);
            }
            for(var i=0; i<node.children.length; ++i){
                retarr.push(node.children[i]);
            }
            return retarr;
        }
    },{ p:2, q:3, depth:10 },
    function(result) {
        console.log(result.distance);
    });
    

    请注意,lfn 和 cfn 参数指定每棵树应如何独立确定每个树根的节点标签名称和子数组,以便您可以将您的 DOM 与 JSON 对象或其他使用不同语义的对象进行比较是孩子,什么是节点标签。另请注意,在此示例中,我利用了 DOM 实体类属性,将其拆分为各个类,并将 DOM 节点本身的 id 作为节点的直接子节点,以便更清楚地了解两棵树是非常相似还是非常不同.您可以扩展它以包含您自己的属性。或者,您还可以修改每棵树的 lfn 函数,以在标签中包含 id,例如“tagname:id”——这取决于你,并且会改变算法的执行方式——也许在你的研究中调查一些有趣的东西。

    总而言之,您需要做的就是提供这些 lfn 和 cfn 函数以及每个根,而 jqgram 将完成其余的工作,调用 lfn 和 cfn 函数来构建树。

    jqgram 实现的 PQ-Gram 算法将提供编辑距离作为一个介于 0 和 1 之间的数字,需要注意的是,零值并不一定表示绝对相等,只是两棵树非常相似。如果您需要继续确定 jqgram 确定的两棵 非常 相似的树是否确实相同,您可以使用 Zhang 和 Shasha,但是使用 jqgram 来获取指标将为您节省大量计算,这将成为在终端用户性能显然很重要的客户端浏览器应用程序中极为重要。

    希望有帮助!

    【讨论】:

      【解决方案2】:

      首先可以使用Java 的Document Object Model (DOM) API 来实现。然而,DOM 模型的速度和内存效率都不是很高,但它几乎可以完美地满足您的需求。

      已经有 HTML-to-DOM 解析器,我个人推荐你一个Cobra HTML renderer and parser。您不需要它的渲染功能,但它有一个单独且非常易于使用的解析机制 - 只需创建一个新的 DocumentBuilderImpl 并将页面内容输入流或页面的 URL 传递给它的 parse() 方法。

      关于第二个问题,看看所谓的“树相似性算法”,例如在this one

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-17
        • 2011-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-07
        • 1970-01-01
        相关资源
        最近更新 更多