python使用BeautifulSoup的prettify功能來處理HTML文件,之後使用Levenshtein編輯距離計算文件間的相似度
字串的處理可謂是一個老生常談的話題了,處理的方法也是有很多的積累的,利用字串的匹配來計算文件整體之間的相似度是一個慣用的方法,但裡面還有很多具體的細節需要注意,今天在使用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是第一種方法的結果,calculate_distance_complex是第二種方法的結果**********************************calculate_distance_simple****************************************** 4.59702930817 0.594041983813 ***************************************calculate_distance_complex************************************** 0.512249443207 0.331642362975
現在的疑惑就是:如果我單純的只是用這樣的編輯距離來計算總體的距離而不加入類似:樹的深度、枝葉長度等輔助資訊的化很難拉開區分度,百度和京東本身就是很不相似的頁面,但是這樣的計算得到的相似度比率卻是很高的,暫時還沒想到該如何找到一個更好的衡量相似度的策略,當然這也只是一個很簡單的嘗試沒有太大的意義,只是想拿兩個很不相似的頁面來試驗一下,期望得到的比率值應該是很低的才對,但是結果卻並不是這樣的。
此外,方法中使用的Levenshtein方法是一個python實現的庫,python-Levenshtein,網上可以收到,下載之後,直接可以使用:python setup.py install安裝,中間囊括了之中常見的距離計算方法,如:編輯距離、漢明距離等等,如果有需要可以下載使用,歡迎指點迷津!