字符串的处理可谓是一个老生常谈的话题了,处理的方法也是有很多的积累的,利用字符串的匹配来计算文档整体之间的相似度是一个惯用的方法,但里面还有很多具体的细节需要注意,今天在使用Levenshtein距离的时候遇到了一个问题,不太知道该如何衡量了,这里先说一下做的事情:
首先使用BeautifulSoup来解析html文档,去除除了html文档非标签节点之外的内容,之后使用prettify函数格式化输出,在得到两个文档的DOM_TAG树之后就是用Levenshtein距离来计算文档之间的相似度,当然这里参与直接运算的就是每一个标签节点的字符串。这个事的目的就是想简单的测试一下Levenshtein距离的时间复杂度以及用于后续计算的话是否可行。
选取的比对对象是百度和京东的html,下面是格式化输出的结果:
<html>
<head>
<meta/>
<meta/>
<meta/>
<meta/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<title>
</title>
<style>
</style>
<style>
</style>
<style>
</style>
<style>
</style>
<style>
</style>
<style>
</style>
<script>
</script>
<noscript>
<meta/>
</noscript>
<script>
</script>
</head>
<body>
<script>
</script>
<div>
<script>
</script>
<div>
<div>
<div>
<div>
<div>
<img/>
</div>
<a>
<img/>
</a>
<form>
<input/>
<input/>
<input/>
<input/>
<input/>
<input/>
<input/>
<span>
<input/>
</span>
<span>
<input/>
</span>
<span>
<span>
<div>
<span>
</span>
</div>
<ul>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
</li>
<li>
<a>
</a>
</li>
</ul>
</span>
</span>
<input/>
<input/>
<input/>
<input/>
<input/>
</form>
<div>
</div>
</div>
</div>
<div>
<a>
</a>
<a>
<i>
</i>
</a>
<a>
</a>
</div>
<div>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
</div>
</div>
</div>
<div>
<b>
</b>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
</div>
<div>
<div>
<div>
<div>
</div>
<div>
<p>
<b>
</b>
</p>
</div>
</div>
</div>
</div>
<div>
<div>
<div>
<p>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
</p>
<p>
<a>
</a>
<a>
</a>
<i>
</i>
<a>
</a>
<i>
</i>
</p>
</div>
</div>
</div>
<div>
</div>
</div>
<div>
</div>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
</body>
</html>
------------------------------------------------jd------------------------------------------------------
<html>
<head>
<meta/>
<title>
</title>
<meta/>
<meta/>
<script>
</script>
<script>
</script>
<script>
</script>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<link/>
<meta/>
<meta/>
<script>
</script>
<script>
</script>
<script>
</script>
<style>
</style>
<script>
</script>
<script>
</script>
</head>
<body>
<script>
</script>
<div>
<div>
<ul>
<li>
</li>
</ul>
<ul>
<li>
<a>
</a>
<a>
</a>
</li>
<li>
</li>
<li>
<div>
<a>
</a>
</div>
</li>
<li>
</li>
<li>
<div>
<a>
</a>
<i>
</i>
<i>
<s>
</s>
</i>
</div>
<div>
</div>
</li>
<li>
</li>
<li>
<div>
<a>
</a>
</div>
</li>
<li>
</li>
<li>
<div>
<a>
</a>
</div>
</li>
<li>
</li>
<li>
<div>
<i>
</i>
<i>
<s>
</s>
</i>
</div>
<div>
</div>
</li>
<li>
</li>
<li>
<div>
<i>
</i>
<i>
<s>
</s>
</i>
</div>
<div>
</div>
</li>
<li>
</li>
<li>
<div>
</div>
<div>
<div>
</div>
</div>
<div>
</div>
</li>
</ul>
</div>
</div>
<div>
<div>
<div>
<h1>
<a>
</a>
</h1>
<h2>
</h2>
<div>
</div>
</div>
<div>
<div>
<div>
<a>
</a>
</div>
<ul>
</ul>
<div>
<input/>
<button>
<i>
</i>
</button>
</div>
</div>
</div>
<div>
<div>
<i>
</i>
<i>
</i>
<i>
</i>
<a>
</a>
</div>
<div>
<div>
</div>
<div>
<span>
</span>
</div>
</div>
</div>
<div>
</div>
<div>
<ul>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
</ul>
<div>
</div>
<ul>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
<img/>
</a>
</li>
<li>
<a>
</a>
</li>
</ul>
<div>
</div>
<ul>
<li>
<a>
</a>
</li>
</ul>
</div>
<div>
</div>
</div>
</div>
<div>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
<a>
</a>
</div>
<div>
<div>
<div>
<div>
<ul>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
<li>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
<span>
</span>
<a>
</a>
</li>
</ul>
<div>
</div>
</div>
</div>
<div>
<div>
<div>
</div>
<div>
</div>
</div>
</div>
<div>
<div>
</div>
<div>
<div>
<div>
<a>
</a>
<a>
</a>
<div>
</div>
<a>
</a>
</div>
<div>
<div>
<ul>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
</ul>
</div>
<div>
<ul>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div>
<div>
<ul>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<span>
<i>
</i>
<i>
</i>
</span>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<span>
<i>
</i>
<i>
</i>
</span>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
<li>
<a>
<i>
</i>
<span>
</span>
</a>
</li>
</ul>
</div>
<div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<a>
</a>
</div>
</div>
</div>
</div>
<div>
</div>
</div>
<style>
</style>
<script>
</script>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
<script>
</script>
</body>
</html>
一共采用了两种计算方法:
1.使用文档1中的每个字符串和文档2中的每一个字符串计算编辑距离,之后的结果除以:m*n,其中,m和n分别为文档1,2 的长度
2.使用文档长度较小的文档作为基准,将其中每个字符串另一个文档中的字符串1对n比对计算,只选取每一轮比对计算中编辑距离的最小值累加,结果除以两个文档长度的平均值
得到的结果如下:
**********************************calculate_distance_simple******************************************
4.59702930817
0.594041983813
***************************************calculate_distance_complex**************************************
0.512249443207
0.331642362975
其中,calculate_distance_simple是第一种方法的结果,calculate_distance_complex是第二种方法的结果
现在的疑惑就是:如果我单纯的只是用这样的编辑距离来计算总体的距离而不加入类似:树的深度、枝叶长度等辅助信息的化很难拉开区分度,百度和京东本身就是很不相似的页面,但是这样的计算得到的相似度比率却是很高的,暂时还没想到该如何找到一个更好的衡量相似度的策略,当然这也只是一个很简单的尝试没有太大的意义,只是想拿两个很不相似的页面来试验一下,期望得到的比率值应该是很低的才对,但是结果却并不是这样的。
此外,方法中使用的Levenshtein方法是一个python实现的库,python-Levenshtein,网上可以收到,下载之后,直接可以使用:python setup.py install安装,中间囊括了之中常见的距离计算方法,如:编辑距离、汉明距离等等,如果有需要可以下载使用,欢迎指点迷津!