1mod fingerprint;
9mod index;
10mod web;
11
12pub use fingerprint::{
13 fnv1a64, FeatureHash, SimHash64, SimHashOptions, TieBreaker, WeightedFeature,
14 DEFAULT_NEAR_DUP_DISTANCE,
15};
16pub use index::{IndexConfig, Match, SimHashIndex, TableSpec};
17pub use web::{WebFeatureExtractor, WebFeatureOptions};
18
19#[cfg(test)]
20mod tests {
21 use super::*;
22
23 #[test]
24 fn end_to_end_html_near_duplicate_lookup() {
25 let extractor = WebFeatureExtractor::default();
26 let canonical = SimHash64::from_html(
27 r#"
28 <html>
29 <head><title>Ignored title chrome</title></head>
30 <body>
31 <nav>Home About Contact</nav>
32 <main>
33 <h1>Rust SimHash for web crawling</h1>
34 <p>Near duplicate web documents differ mostly in counters and ads.</p>
35 <p>The crawler should avoid fetching the same useful content twice.</p>
36 </main>
37 <aside>Advertisement 12345</aside>
38 </body>
39 </html>
40 "#,
41 &extractor,
42 );
43 let duplicate = SimHash64::from_html(
44 r#"
45 <html>
46 <body>
47 <main>
48 <h1>Rust SimHash for web crawling</h1>
49 <p>Near duplicate web documents differ mostly in counters and ads.</p>
50 <p>The crawler should avoid fetching the same useful content twice.</p>
51 </main>
52 <aside>Advertisement 99999</aside>
53 </body>
54 </html>
55 "#,
56 &extractor,
57 );
58
59 let mut index = SimHashIndex::new_google64_k3();
60 index.insert("canonical", canonical);
61 let matches = index.query(duplicate);
62
63 assert_eq!(matches.len(), 1);
64 assert_eq!(matches[0].id, "canonical");
65 assert!(matches[0].distance <= DEFAULT_NEAR_DUP_DISTANCE);
66 }
67}