网页更改检测

时间:2011-04-23 05:50:41

标签: java subtree hungarian-notation

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

1。在一篇名为

的论文中
  

增强的网页更改检测算法,用于加速移动网页转码1

写的是

  

首先从HTML文档生成子树,其中每个子树根据其标签内容给出一个标记。

我的问题是如何从HTML文档生成子树?这样做的技术是什么。接下来的问题是“根据标签内容给出标记”是什么意思。

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

在“计算最相似的子树”框中如何进行匹配?在另一篇题为

的论文中
  

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

匈牙利算法用于匹配,一行引用了题为

的论文
  

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

[2]中的方法使用O(N 3 )匈牙利算法计算加权二分图上的最大加权匹配,并且运行时间为O(N 2 < / sub> x N 1 3 ),其中N 1 和N 2 分别是旧页面和新页面中的节点数量(更改)页面。“我的问题是,因为子树正在形成为什么要添加权重,以及如何添加权重?

感谢您阅读我的问题/困惑,我真的需要帮助,不久之后,请任何人帮助我这个,我会永远感激。

2 个答案:

答案 0 :(得分:0)

首先可以使用Java的Document Object Model(DOM)API实现。然而,DOM模型并不是真正的快速或内存效率,但它完全符合您的需求。

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

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

答案 1 :(得分:0)

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

我最近编写并发布了用于计算树编辑距离 approximation 的jqgram,其中包含一个易于使用的API,用于比较您自己设计的类似DOM的结构,JSON结构或树结构:

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&amp;获得真正的编辑距离快得多。 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来获取指标将为你节省大量的计算量在终端用户性能显然非常重要的客户端浏览器应用程序中非常关键。

希望有所帮助!

相关问题