mudfish 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. {mudfish-0.2.0 → mudfish-0.2.1}/Cargo.lock +1 -1
  2. {mudfish-0.2.0 → mudfish-0.2.1}/PKG-INFO +1 -1
  3. {mudfish-0.2.0 → mudfish-0.2.1}/crates/parser/Cargo.toml +4 -0
  4. mudfish-0.2.1/crates/parser/benches/adaptive_relocate.rs +78 -0
  5. mudfish-0.2.1/crates/parser/src/adaptive.rs +1138 -0
  6. {mudfish-0.2.0 → mudfish-0.2.1}/crates/parser/src/lib.rs +2 -0
  7. {mudfish-0.2.0 → mudfish-0.2.1}/crates/python/Cargo.toml +1 -1
  8. {mudfish-0.2.0 → mudfish-0.2.1}/pyproject.toml +1 -1
  9. {mudfish-0.2.0 → mudfish-0.2.1}/python/mudfish/__init__.py +1 -1
  10. {mudfish-0.2.0 → mudfish-0.2.1}/Cargo.toml +0 -0
  11. {mudfish-0.2.0 → mudfish-0.2.1}/LICENSE +0 -0
  12. {mudfish-0.2.0 → mudfish-0.2.1}/README.md +0 -0
  13. {mudfish-0.2.0 → mudfish-0.2.1}/crates/browser/Cargo.toml +0 -0
  14. {mudfish-0.2.0 → mudfish-0.2.1}/crates/browser/src/error.rs +0 -0
  15. {mudfish-0.2.0 → mudfish-0.2.1}/crates/browser/src/lib.rs +0 -0
  16. {mudfish-0.2.0 → mudfish-0.2.1}/crates/browser/src/renderer.rs +0 -0
  17. {mudfish-0.2.0 → mudfish-0.2.1}/crates/browser/tests/render.rs +0 -0
  18. {mudfish-0.2.0 → mudfish-0.2.1}/crates/core/Cargo.toml +0 -0
  19. {mudfish-0.2.0 → mudfish-0.2.1}/crates/core/benches/normalize.rs +0 -0
  20. {mudfish-0.2.0 → mudfish-0.2.1}/crates/core/src/config.rs +0 -0
  21. {mudfish-0.2.0 → mudfish-0.2.1}/crates/core/src/error.rs +0 -0
  22. {mudfish-0.2.0 → mudfish-0.2.1}/crates/core/src/lib.rs +0 -0
  23. {mudfish-0.2.0 → mudfish-0.2.1}/crates/core/src/normalize.rs +0 -0
  24. {mudfish-0.2.0 → mudfish-0.2.1}/crates/core/src/types.rs +0 -0
  25. {mudfish-0.2.0 → mudfish-0.2.1}/crates/engine/Cargo.toml +0 -0
  26. {mudfish-0.2.0 → mudfish-0.2.1}/crates/engine/src/lib.rs +0 -0
  27. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/Cargo.toml +0 -0
  28. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/challenge.rs +0 -0
  29. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/error.rs +0 -0
  30. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/fetcher.rs +0 -0
  31. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/health.rs +0 -0
  32. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/lib.rs +0 -0
  33. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/politeness.rs +0 -0
  34. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/robots.rs +0 -0
  35. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/security.rs +0 -0
  36. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/src/status.rs +0 -0
  37. {mudfish-0.2.0 → mudfish-0.2.1}/crates/fetch/tests/http_fetcher.rs +0 -0
  38. {mudfish-0.2.0 → mudfish-0.2.1}/crates/frontier/Cargo.toml +0 -0
  39. {mudfish-0.2.0 → mudfish-0.2.1}/crates/frontier/src/frontier.rs +0 -0
  40. {mudfish-0.2.0 → mudfish-0.2.1}/crates/frontier/src/item.rs +0 -0
  41. {mudfish-0.2.0 → mudfish-0.2.1}/crates/frontier/src/lib.rs +0 -0
  42. {mudfish-0.2.0 → mudfish-0.2.1}/crates/frontier/src/scheduler.rs +0 -0
  43. {mudfish-0.2.0 → mudfish-0.2.1}/crates/parser/benches/parse_html.rs +0 -0
  44. {mudfish-0.2.0 → mudfish-0.2.1}/crates/python/LICENSE +0 -0
  45. {mudfish-0.2.0 → mudfish-0.2.1}/crates/python/README.md +0 -0
  46. {mudfish-0.2.0 → mudfish-0.2.1}/crates/python/src/lib.rs +0 -0
  47. {mudfish-0.2.0 → mudfish-0.2.1}/crates/python/tests/test_crawl.py +0 -0
  48. {mudfish-0.2.0 → mudfish-0.2.1}/python/mudfish/py.typed +0 -0
@@ -1821,7 +1821,7 @@ dependencies = [
1821
1821
 
1822
1822
  [[package]]
1823
1823
  name = "mudfish-python"
1824
- version = "0.2.0"
1824
+ version = "0.2.1"
1825
1825
  dependencies = [
1826
1826
  "mudfish-core",
1827
1827
  "mudfish-engine",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mudfish
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
@@ -20,3 +20,7 @@ criterion = { version = "0.8.2", features = ["html_reports"] }
20
20
  [[bench]]
21
21
  name = "parse_html"
22
22
  harness = false
23
+
24
+ [[bench]]
25
+ name = "adaptive_relocate"
26
+ harness = false
@@ -0,0 +1,78 @@
1
+ use criterion::{criterion_group, criterion_main, Criterion};
2
+ use mudfish_parser::adaptive::{fingerprint, relocate, RelocateOptions};
3
+ use scraper::{Html, Selector};
4
+ use std::hint::black_box;
5
+
6
+ /// A listing-style page made of product cards, grown until it is at least
7
+ /// `target_bytes`. This mirrors the shape the crawler actually meets (many
8
+ /// near-identical repeated blocks) and is the pathological case for
9
+ /// similarity scoring: the target's decoys are structurally near-identical.
10
+ fn synthetic_page(target_bytes: usize) -> String {
11
+ let mut html = String::from(
12
+ "<html><head><title>Bench Listing</title></head><body><main class=\"catalog\">",
13
+ );
14
+ let mut index = 0usize;
15
+ while html.len() < target_bytes {
16
+ html.push_str(&format!(
17
+ "<article class=\"card\"><h2 class=\"name\">Product {index}</h2>\
18
+ <p class=\"desc\">A synthetic description of product {index} long enough \
19
+ to resemble a real listing blurb.</p>\
20
+ <span class=\"price\" data-currency=\"USD\">${index}.99</span>\
21
+ <a class=\"buy\" href=\"/item/{index}\">Buy</a></article>"
22
+ ));
23
+ index += 1;
24
+ }
25
+ html.push_str("</main></body></html>");
26
+ html
27
+ }
28
+
29
+ /// Fingerprints one `.price` element from a minimal page that has the same
30
+ /// card structure as `synthetic_page`, so the benchmark measures a genuine
31
+ /// recovery against a large number of similar candidates.
32
+ fn bench_fingerprint() -> mudfish_parser::adaptive::ElementFingerprint {
33
+ let html = "<html><body><main class=\"catalog\"><article class=\"card\">\
34
+ <h2 class=\"name\">Product 0</h2>\
35
+ <p class=\"desc\">A synthetic description of product 0 long enough to resemble \
36
+ a real listing blurb.</p>\
37
+ <span class=\"price\" data-currency=\"USD\">$0.99</span>\
38
+ <a class=\"buy\" href=\"/item/0\">Buy</a></article></main></body></html>";
39
+ let document = Html::parse_document(html);
40
+ let selector = Selector::parse(".price").unwrap();
41
+ fingerprint(document.select(&selector).next().unwrap())
42
+ }
43
+
44
+ fn bench_relocate(c: &mut Criterion) {
45
+ let fp = bench_fingerprint();
46
+ let small = Html::parse_document(&synthetic_page(20_000));
47
+ let large_html = synthetic_page(2_000_000);
48
+ let large_size = large_html.len();
49
+ let large = Html::parse_document(&large_html);
50
+ let options = RelocateOptions::default();
51
+
52
+ // Report the actual fixture size once so the number in the ADR (§11
53
+ // targets a 2 MB document) is verifiable rather than assumed.
54
+ eprintln!("adaptive_relocate: large fixture is {large_size} bytes");
55
+
56
+ c.bench_function("relocate_20kb_document", |b| {
57
+ b.iter(|| {
58
+ black_box(relocate(
59
+ black_box(&fp),
60
+ black_box(&small),
61
+ black_box(&options),
62
+ ))
63
+ })
64
+ });
65
+
66
+ c.bench_function("relocate_2mb_document", |b| {
67
+ b.iter(|| {
68
+ black_box(relocate(
69
+ black_box(&fp),
70
+ black_box(&large),
71
+ black_box(&options),
72
+ ))
73
+ })
74
+ });
75
+ }
76
+
77
+ criterion_group!(benches, bench_relocate);
78
+ criterion_main!(benches);