Subotai: Data Mining for HTML Documents

I spent the last few months studying and implementing some routines that take a raw HTML document (or documents) and do stuff with it (them). Subotai is a library that consolidates some of these routines. In this blog post I will describe what is currently implemented and what the roadmap is.

Structural Similarity

Dynamic web-pages are built by populating templates and thus two pages that look the same, possibly share the same underlying template. Structural similarity measures the similarity of the underlying templates. Subotai contains an implementation of the Restricted Top-Down Mapping algorithm (which I shall call RTDM) - a dynamic programming algorithm which measures the Tree-Edit-Distance (rather like its cousin that works on strings). You can use the subotai implementation like so:

For the following two documents (which clearly look the same and as we can guess use the same underlying HTML template):

you can do this with Subotai:

1
2
3
4
5
6
7
8
9
user=> (use 'clj-http.client)
user=> (use 'subotai.structural-similarity.core :reload)
user=> (def bod1 (:body (get "http://blog.shriphani.com/"))) ; this is page 1
#'user/bod1
user=> (def bod2 (:body (get "http://blog.shriphani.com/index-2.html"))) ; this is page 2
#'user/bod2
user=> (similar? bod1 bod2)
true ; both pages have the same structure
user=>

Near-Duplicate Detection

One can often find pages on the web that are near duplicates of each other - for instance a page on a site mirror vs the actual destination. I have an example here of two web-pages that are not identical but near-identical: the first and the second.

The two documents differ in the templating slightly and have dates and other meta content that is slightly different. You can test it using:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
user> (use 'clj-http.client)
WARNING: get already refers to: #'clojure.core/get in namespace: user,
being replaced by: #'clj-http.client/get
user> (use 'subotai.near-duplicate.core :reload)
user> (def b2 (:body (get "http://www.kidneyspace.com/index.php/topic,5286.msg30719.html")))
#'user/b2
user> (def b1 (:body (get "http://www.kidneyspace.com/index.php/topic,5286")))
#'user/b1
user> (near-duplicate-html? b1 b2)
true
user> 

The github project page: [github: Subotai]

PDFs of the papers implemented: [github: Papers]

Pipeline

Next, I want to implement record detection (automatically figuring out different reviews on an amazon product page for instance).

The thresholds used are picked from papers or 2-fold cross validation. I will move that codebase into Subotai later.


Twitter: @shriphani
Instagram: @life_of_ess
Fortior Per Mentem
(c) Shriphani Palakodety 2013-2020