网页结构相似度检测算法——Go(特征向量)

记录看到的一篇 百度 在2009年发明的专利:网页结构相似性确定方法及装置

【目的】用于批量查找具有相似模板特征向量的作弊网站

【中心思想】

提取模块
处理模块
网页DOM树
网页模板特征向量
计算网页结构相似行 & 查找/聚类

专利中的图示:

大纲步骤

【注】根据个人理解(也可能是曲解,毕竟专利大家都懂,不会写的很准确),我暂且记录我理解的部分:


一、提取“特征单元”

对于特征单元的定义,专利并没有给出明确标准:

特征单元 = { 单个 D O M 节点 D O M 节点组合 { 当前 D O M 节点 + 其兄弟节点 当前 D O M 节点 + 其父节点 特征单元 = \begin{cases} 单个DOM节点 \\ DOM节点组合 \begin{cases} 当前DOM节点 + 其兄弟节点 \\ 当前DOM节点 + 其父节点 \\ \end{cases} \\ \end{cases} 特征单元= 单个DOM节点DOM节点组合{当前DOM节点+其兄弟节点当前DOM节点+其父节点

二、映射“高维特征向量”

关键有三点:

  1. 拼接字符串(即把上面特征单元的HTML标签名称及其相关属性拼接,属性包括但不限于id、class、name、style…)
  2. 哈希运算(借助hash函数,将字符串转换为哈希值)
  3. 确定高维特征向量的维数(即哈希值)

三、确定“权重”

权重即为该DOM节点在DOM树中的重要程度。

这里提到一个定义——衰减因子。确定权重需要定义初始值和衰减因子,然后根据“预定规则”进行权重衰减或累加。原文中的“预定规则”包括:

  1. 随深度递减。原文认为内层内容差异不重要,为提高效率,需确定有限深度(即忽略低权重部分)
  2. 随兄弟节点重复递减。原文估计觉得同级节点只重点关注前面的即可。
  3. 随无关性递减。原文认为应忽略注释语句、换行语句等不重要的排版

累加是指重复维数(节点)

四、对应高维特征向量的“实数值”

专利视 权重值 为高维特征向量对应维数的 实数值

个人理解为确定【维数:权重】键值对

专利中的图示:

图3图4

五、维数压缩,得到“模板特征向量”

这里主要解决维数取值过大问题,毕竟过大也是为了解决哈希冲突,但不利于最终计算。

关键思想:维数取模,权重叠加

将M维降到N维,1<=N<M;
模运算后余数相同的高维特征向量的实数值(权重)相加

个人理解为确定【维数余数:权重和】键值对

六、快速处理

将实数值离散至网格。

这一步没太看懂,个人理解为L:把这些值分布在网格中(然后小数向上或者向下取整)。

最后计算伪距离:
d i s t ( U , V ) = ∑ i ( ∣ U i − V i ∣ ) ∑ i ( min ⁡ { U i , V i } ) dist(U,V)= {\sum_i(|U_i-V_i|) \over \sum_i(\min \lbrace U_i,V_i \rbrace)} dist(U,V)=i(min{Ui,Vi})i(UiVi)
(所有维的差值和/所有维的共同部分和)

图5

浅试一下

按照权重初值为1,递减因子为0.9,暂不忽略低权重(因为很多元素都比较深,不好划定深度),暂不做网格处理,浅试一下。

func HighDimensionalEigenvector(root *cdp.Node, val float64, highWeight map[int]float64) {
	//高维特征向量的维数及权重
	if root.NodeName == "#text" || root.NodeName == "#comment" || root.ChildNodeCount == 0 {
		val *= global.Decay //无关性递减
	}
	hash := int(tools.FNVHash(root.NodeName + strings.Join(root.Attributes, "") + root.NodeValue))
	var v float64
	if v_, ok := highWeight[hash%100]; !ok {
		v = v_
	}
	highWeight[hash%100] = v + val

	for _, child := range root.Children {
		//if i > 20 {
		//	break
		//}
		HighDimensionalEigenvector(child, val*global.Decay, highWeight) //深度递减
		val *= global.Decay                                             //兄弟递减
	}
}

func Compute(highWeight1, highWeight2 map[int]float64) float64 {
	var count, same float64
	for i := 0; i < 100; i++ {
		var v1, v2 float64
		var ok bool
		if v1, ok = highWeight1[i]; !ok {
			count += v1
			continue
		}
		if v2, ok = highWeight2[i]; !ok {
			count += v2
			continue
		}
		count += math.Abs(v1 - v2)
		if v1 == v2 {
			same += math.Min(v1, v2)
		}
	}
	fmt.Println("差值和:", count)
	fmt.Println("共同部分和:", same)
	return count / same
}

注:由于实现方法和原文结果有出入,所以结果也有出入,浮点精度计算容易不准确。

其他内容和之前写的算法差不多,写法肯定是和原专利有很多不同的,也肯定有理解错误的地方,还请大佬指正!!
即便如此不同页面和相同页面还是有差距的:
【相似页面】

Url1 = https://blog.csdn.net/qq_40119224/article/details/132446697?spm=1001.2014.3001.5502
Url2 = https://blog.csdn.net/qq_40119224/article/details/132598415?spm=1001.2014.3001.5502

相同
【不相似页面】

Url1 = https://blog.csdn.net/qq_40119224/article/details/132446697?spm=1001.2014.3001.5502
Url2 = https://www.sina.com.cn/

不同


【求知若渴】

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Levenshtein Distance算法是一种常见的字符串相似度算法,也被称为编辑距离算法。其主要思想是通过计算两个字符串之间的编辑距离来确定它们的相似程度。 编辑距离指的是将一个字符串转换成另一个字符串所需的最少操作次数,其中每次操作可以是插入、删除或替换一个字符。例如,将字符串“kitten”转换成字符串“sitting”需要进行3次操作,即将“k”替换为“s”,将“e”替换为“i”,将“n”替换为“g”。 Levenshtein Distance算法的实现一般使用动态规划的方法,通过填充一个二维矩阵来计算两个字符串之间的编辑距离。具体实现过程可以参考以下伪代码: ``` function LevenshteinDistance(s1, s2): m = length(s1) n = length(s2) d = new matrix(m+1, n+1) for i from 0 to m: d[i, 0] = i for j from 0 to n: d[0, j] = j for j from 1 to n: for i from 1 to m: if s1[i] == s2[j]: cost = 0 else: cost = 1 d[i, j] = min(d[i-1, j]+1, d[i, j-1]+1, d[i-1, j-1]+cost) return d[m, n] ``` 在以上代码中,变量s1和s2分别表示两个待比较的字符串,m和n分别表示它们的长度,矩阵d用于存储编辑距离的计算结果。首先,将矩阵d的第一行和第一列分别初始化为0到n和0到m的整数。然后,对于每个(i, j)位置,如果s1[i]等于s2[j],则将cost设为0,否则设为1。最后,根据递推公式d[i, j] = min(d[i-1, j]+1, d[i, j-1]+1, d[i-1, j-1]+cost)来填充矩阵d,并返回d[m, n]作为编辑距离的结果。 Levenshtein Distance算法的时间复杂度为O(m*n),其中m和n分别为两个字符串的长度。在实际应用中,该算法可用于拼写检查、数据去重等场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值