Skip to main content

web2textpy

Python reimplementation of the Web2Text pipeline for labeling HTML DOM nodes as content or boilerplate using paired (raw_html, clean_text) data.

Installation

uv add web2textpy

Quick Start

from datasets import load_dataset
from web2text import run_pipeline

ds = load_dataset("williambrach/html-boilerplate-labeled", split="test")
row = ds[0]

tree, extracted_text, metrics = run_pipeline(row["html"], row["text"])

print(extracted_text[:200])
print(metrics)

Get text from labeled HTML

from web2text import extract_text_from_labeled_html
text = extract_text_from_labeled_html(labeled_html_string)

Step-by-Step API

Each stage of the pipeline is exposed as a standalone function:

from web2text import build_cdom, extract_leaves, align, label_nodes, extract_text, evaluate

# 1. Parse HTML into a collapsed DOM tree
tree = build_cdom(html_string)

# 2. Extract ordered text-bearing leaf nodes
leaves = extract_leaves(tree)  # [(element, "normalized text"), ...]

# 3. Align leaf texts against ground-truth clean text
scores = align(leaves, clean_text)  # {leaf_id: 0.0-1.0 match score}

# 4. Label each node as "content" or "boilerplate"
tree = label_nodes(tree, scores, threshold=0.667)

# 5. Extract text from content-labeled nodes
result = extract_text(tree)

# 6. Evaluate against ground truth
metrics = evaluate(result, clean_text)
# => {'token_f1': 0.99, 'precision': 0.99, 'recall': 0.99, 'rouge1_f': 0.99, 'bleu': 98.5, 'chrf': 98.8}

How the Matching Algorithm Works

Given raw HTML and its known clean text, the algorithm determines which DOM nodes are content versus boilerplate in six steps:

  1. Simplify the DOM — strip non-content tags (<script>, <style>, etc.) and collapse single-child chains into a Collapsed DOM (CDOM) representation
  2. Collect leaf text — walk the CDOM, concatenate text from every leaf node into one source string with tracked character offsets
  3. Find anchors — identify 10-character substrings that appear exactly once in both the source and clean text, splitting the problem into independent segments
  4. DP alignment — for each segment between anchors, run character-level dynamic programming with affine gap penalties to map source characters to clean-text characters
  5. Score leaves — map alignment results back to leaf boundaries via stored offsets, giving each leaf a score: matched_chars / total_chars
  6. Label nodes — leaves scoring above 0.667 are labeled "content", the rest "boilerplate", with labels propagating upward to parents

Alignment pipeline: extract leaf texts → anchor matching → DP alignment → per-leaf scores

Dataset

Dataset: williambrach/html-boilerplate-labeled — ~4k pages from CleanEval, Dragnet, CETD, Readability, and others (3,985 pages total).

Source Train (ROUGE-1 F) Test (ROUGE-1 F)
readability 0.993 (92) 0.997 (23)
scrapinghub 0.991 (145) 0.996 (36)
cetd 0.993 (560) 0.987 (140)
google-trends-2017 0.986 (144) 0.995 (36)
cleanportaleval 0.985 (57) 0.971 (14)
cleaneval 0.985 (590) 0.991 (148)
dragnet 0.983 (1,103) 0.983 (276)
l3s-gn1 0.920 (497) 0.927 (124)
Overall 0.976 (3,188) 0.978 (797)

Sample counts in parentheses.

Original Work

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

web2textpy-0.2.0.tar.gz (155.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

web2textpy-0.2.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file web2textpy-0.2.0.tar.gz.

File metadata

  • Download URL: web2textpy-0.2.0.tar.gz
  • Upload date:
  • Size: 155.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.16

File hashes

Hashes for web2textpy-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c902800d104a6ae5bb286ae2b07de0e46512e90b65fda8f4a373824034e6e5d0
MD5 5a11296688dc4814d798d25fdd8f8ace
BLAKE2b-256 a7676ed96fa8969c53fd0b7615bcde8391a280a9bcd9ec0b1d28ca80b7f66d24

See more details on using hashes here.

File details

Details for the file web2textpy-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: web2textpy-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.16

File hashes

Hashes for web2textpy-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b96c132d027f5442f496b4a64f8550f33a5b145523a314b8275905ecf18435d1
MD5 1f049f0cb4b799bd1ce49f160b2975e1
BLAKE2b-256 7cedba09f3e0033d3d52684edb18d8fd5175ca6f8ac25eca58f90fd23bb45ad4

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page