rs-trafilatura:Rust用ウェブコンテンツ抽出ライブラリ

Murrough Foley
Murrough Foley
Author·5 min read

私がrs-trafilaturaを構築したのは、記事だけでなく商品ページ、フォーラム、ドキュメント、ランディングページなど、多様なウェブページから大量にクリーンなコンテンツを抽出する必要があったからです。既存のツールは、Python専用(私のパイプラインには遅すぎる)か、Rustクレートで記事ページは上手く処理するものの、それ以外のページではうまく機能しないものばかりでした。

これは当初、Adrien Barbaresiの優れたPythonライブラリTrafilaturaをRustに移植する単純な作業として始まりました。速度が必要でした——SEO分析ワークフローにおいて、Pythonパイプラインで数千ページを処理することはボトルネックだったのです。しかし、さまざまな種類のページでテストするうちに、同じ問題に直面し続けました: 万能型の抽出は現代のウェブでは通用しない、ということです。

そこで、機能は拡張されました。ページタイプの分類。タイプ固有の抽出プロファイル。信頼度スコア。Markdown出力。ルールベースのヒューリスティクスが限界に達した時には、ML分類器の導入。

機能

rs-trafilaturaは、あらゆるウェブページからメインコンテンツ——タイトル、著者、日付、記事本文全体——を抽出し、ナビゲーション、広告、サイドバー、クッキーバナー、その他の定型部分を取り除きます。他の抽出ライブラリとの違いは以下の通りです:

  • ページタイプ分類: 3段階の分類器(URLヒューリスティクス、HTML信号分析、181の特徴量を持つXGBoost)が、87%の精度で7つのページタイプ——記事、フォーラム、商品、コレクション、一覧、ドキュメント、サービス——を検出します。各タイプには専用の抽出プロファイルが適用されます。

  • 抽出信頼度: 全ての抽出結果には、期待されるF1スコアを予測する27の特徴量を持つXGBoost回帰モデルによる品質スコア(0.0-1.0)が含まれます。0.80未満のスコアのページはLLMへのフォールバックの候補となります——詳細は後述します。

  • Markdown出力: GitHub Flavored Markdown形式で、見出し、リンク、表、太字/斜体、コードブロック、ブロック引用を保持します。これはSEO分析に実際に必要なものであり、構造的な信号はテキスト自体と同様に重要です。

  • 速度: CPUで1ページあたり44ms。これは一般的なハードウェアで1秒あたり22ページを処理できることを意味し、A100 GPU上でのMinerU-HTMLの1,570ms/ページと比べて高速です。

use rs_trafilatura::{extract_with_options, Options};

let html = std::fs::read_to_string("page.html")?;
let result = extract_with_options(&html, &Options::default())?;

println!("Title: {:?}", result.metadata.title);
println!("Author: {:?}", result.metadata.author);
println!("Content: {}", result.content_text);
println!("Page type: {:?}", result.metadata.page_type);
println!("Confidence: {:.2}", result.extraction_quality);
import rs_trafilatura

html = open("page.html").read()
result = rs_trafilatura.extract(html, url="https://example.com")

print(f"Title: {result.title}")
print(f"Content: {result.main_content[:200]}...")
print(f"Page type: {result.page_type}")
print(f"Confidence: {result.extraction_quality:.2f}")

Pythonパッケージは、4つのRustクレートをPyO3を介して単一のネイティブ拡張にバンドルしています——サブプロセスのオーバーヘッドはなく、Pythonから直接コンパイルされたRustコードが呼び出されます。

対象ユーザー

正直に言うと、これは私自身のために構築しました。Googleがウェブページを評価する時に何を見ているのかを理解したかったのです。そのためには、検索結果から数千ページにわたってクリーンで構造化されたコンテンツを抽出する必要がありました——記事だけでなく、実際のSERPで見られるあらゆる種類のページのフルセットです。既存のツールではそれができなかったので、できるツールを作りました。

しかし、大量のコンテンツ抽出は多くの人々が解決しようとしている問題であることがわかり、その中には真剣なビジネスに発展させている人々もいます:

検索・データ企業は、抽出されたウェブコンテンツをサービスとして販売しています。Jina AIはReaderLM-v2とそのReader APIをまさにこの目的のために構築しました——URLを渡せば、クリーンなMarkdownが返ってきます。FirecrawlはJSレンダリングとアンチボット対策を加えて同様のことを行います。Tavilyは検索+抽出をAIエージェント向けAPIとしてパッケージ化しています。Diffbotは10年以上にわたり構造化されたウェブデータ抽出を行ってきました。Zyte(旧ScrapingHub——記事抽出ベンチマークを開発したチームと同じ)は企業規模での抽出サービスを販売しています。市場が存在するのは、問題が困難であり、誰もがその解決を必要としているからです。

RAGおよびLLMパイプラインビルダーは、埋め込みモデルやコンテキストウィンドウに供給するクリーンなコンテンツを必要としています。取得したコンテキスト内の定型部分は、無駄なトークンと質の低い回答を意味します。全てのRAGパイプラインには抽出ステップがあり、その多くはReadabilityやBeautifulSoupを使用しており、非記事ページでは平凡な結果しか得られていません。

LLM学習データチームは数十億のウェブページを処理します。抽出の品質はモデルの品質に直接影響します。Common Crawlは生のHTMLを提供します——しかし、それをクリーンな学習用テキストに変換することが、抽出品質が重要になる部分です。数十億ページにわたってF1が数パーセント向上すれば、数百万ページ分のノイズが除去され、または本物のコンテンツが保持されることになります。MinerU-HTMLのチームは彼らのAICCコーパスでこの問題への一つのアプローチを示しました——DOMテンプレートの類似性でCommon Crawlページをクラスタリングし、クラスターごとに代表的な1ページでLLMを実行し、その後、その決定を軽量なルールに蒸留して残り99.6%のページに適用するというものです。賢いアーキテクチャです。

SEO実務家は、検索エンジンが見ているものを近似するために抽出を使用します。コンテンツ監査、競合分析、SERP品質スコアリング、コンテンツギャップ分析——これらは全て、ページから実際のコンテンツを抽出することから始まります。抽出ツールがナビゲーションメニューやクッキーバナーを「コンテンツ」に含めてしまったら、分析は始まる前から間違っています。

学術研究者(情報検索、ウェブマイニング、NLP分野)は、実験のため再現性のある抽出を必要としています。WCXBベンチマークが存在する理由の一部は、ページタイプを横断して抽出をテストするまともなベンチマークが見つからなかったからです——そして、私だけが探していたわけではないと確信しています。

もしあなたが大量のウェブページを処理し、実際に抽出している内容を気にかけているなら、これはあなたのためのツールです。

ベンチマーク結果

rs-trafilaturaを他の抽出システムと比較し、2つのデータセットでベンチマークを行いました: ScrapingHubベンチマーク(181記事)と、私が構築したWCXBベンチマーク(7ページタイプ、2,008ページ、開発セット1,497ページ、保留テストセット511ページに分割)。

ScrapingHubベンチマーク (181記事)

ライブラリF1スコア適合率再現率
rs-trafilatura0.9660.9420.991
trafilatura (Python)0.9480.9330.983

WCXB開発セット (1,497ページ, 7ページタイプ)

ライブラリF1スコア適合率再現率
rs-trafilatura0.8590.8630.890
MinerU-HTML (0.6B LLM)0.8270.8450.840
Trafilatura (Python)0.7910.8520.793
dom-smoothie0.7620.8060.768
ReaderLM-v2 (1.5B LLM)0.7410.7410.790

WCXB保留テストセット (511ページ, 開発中は一切使用なし)

ライブラリF1スコア適合率再現率
rs-trafilatura0.8930.9000.910
Trafilatura (Python)0.8330.8860.828

rs-trafilaturaは、開発セットでオリジナルのPython実装を6.8 F1ポイント、保留セットで6.0ポイント上回りました。また、CPU上で44ms/ページという速度で動作しながら、両方のLLMベース抽出器(A100 GPU上でMinerU-HTMLは1,570ms、ReaderLM-v2は10,410ms)よりも優れた性能を発揮しています。

Rust抽出クレートの比較

参考までに、主要なRust抽出クレートがWCXBベンチマークでどのように比較されるかを示します:

メインコンテンツ抽出器(定型部分をフィルタリング):

ライブラリF1スコア得意分野
rs-trafilatura0.859メタデータを含む完全な抽出、7ページタイプ対応
dom_smoothie0.762Readabilityスタイルの抽出
dom-content-extraction0.731CETDアルゴリズム、研究に基づく

全文抽出器(全てを抽出、フィルタリングなし):

ライブラリF1スコアトレードオフ
nanohtml2text0.670高速 (606us) だが定型部分を含む
fast_html2md0.664Markdown出力、定型部分を含む

この区別は重要です: 全文抽出器はナビゲーションやフッターを含む全てを捕捉します。メインコンテンツ抽出器は記事本文のみを識別して返します。SEO分析、コンテンツアグリゲーション、LLM学習データには後者が適しています。

dom_smoothieについて一言: これは優れたクレートであり、私がrs-trafilaturaを構築する際に詳細に研究したものです。また、より高速です——rs-trafilaturaの44msに対し27ms/ページ——なぜなら分類やタイプ固有のプロファイルのオーバーヘッドなしにReadabilityスタイルの抽出を行っているからです。もし主に記事やブログを扱うのであれば、dom_smoothieは強力な選択肢です。rs-trafilaturaが遅いのは、ページタイプを分類し、ページごとに異なる抽出ロジックを適用しているからです——それが非記事コンテンツを扱うためのトレードオフです。

dom_smoothieとrs-trafilaturaの両方は、niklakのdom_query——Rust用のDOM操作ライブラリで、CSSセレクターベースの走査を容易にします——を基に構築されています。これは十分な評価を受けていない基礎的なクレートの一つです。

Rust HTMLパーシングクレート(html5ever, scraper, select.rs, dom_query)に関する詳細な考察については、Evan SchwartzによるHTMLからのテキスト抽出のための13のRustクレートの包括的な比較をお勧めします。

ページタイプが重要な理由

これが私が最も驚いた部分です。記事では、全ての抽出器の結果は収束します——F1スコアは0.88から0.93の間です。それ以外のページタイプでは、結果は劇的に分かれます:

ページタイプNrs-trafilaturaMinerU-HTMLTrafilaturaReaderLM-v2
記事7930.9320.9280.9260.878
ドキュメント910.9310.8380.8880.776
サービス1650.8430.8240.7630.703
フォーラム1130.7920.7940.5850.589
コレクション1170.7130.5060.5530.417
一覧990.7040.7100.5890.559
商品1190.6700.6190.5670.463

フォーラム: 最良と最悪の間で33ポイントの差。コレクション: 30ポイント。商品: 26ポイント。記事のみのベンチマークでは、これら全てが隠されてしまいます。

その理由は構造にあります。フォーラムスレッドのユーザー投稿は class="comment" にマッチします——これはほとんどの抽出器が定型部分として扱います。サービスページはコンテンツを10の異なる <section> 要素に分散させています——単一ノード抽出は一つを捕捉し、残りを見逃します。商品ページはその説明をJSON-LD構造化データに保存しています——DOMのみの抽出器には見えません。

rs-trafilaturaは、まずページを分類し、その後タイプ固有の抽出戦略を適用することでこれらを処理します。フォーラムプロファイルはコメント要素をコンテンツとして扱います。サービスページプロファイルは複数のDOMセクションからのコンテンツをマージします。商品プロファイルはDOM抽出が失敗した場合にJSON-LDにフォールバックします。## 信頼度スコアリングとハイブリッドパイプライン

抽出品質予測器は、私が最もさらなる開発に関心を持っている機能です。現在は抽出時に利用可能な信号——抽出テキストとHTMLの比率、段落構造、リンク密度、ページタイプに基づく期待値に対するコンテンツの長さ、冒頭テキスト内の定型文キーワードなど——を見る27の特徴量を持つXGBoostモデルです。しきい値を0.80に設定すると、不十分な抽出ページの約35%を正しくフラグ付けしつつ、残りのページに対して97%の精度を維持しています。

実用的な用途はハイブリッドパイプラインです。すべてのページに対してrs-trafilaturaを44ミリ秒/ページで実行します。信頼度が低い約8%のページについては、ニューラル抽出器にルーティングします。WCXBの保留テストセットでは、これによりF1スコアが0.893から0.910に押し上げられます——両方の利点を兼ね備えた結果です。

ただし、ルーティングはページタイプを考慮する必要があります。MinerU-HTMLは記事、フォーラム、サービスページでは役立ちますが、コレクション(0.506対0.713)や商品ページ(0.619対0.670)では実際にはrs-trafilaturaより性能が低下します。信頼度の低いコレクションページをMinerU-HTMLに送ることは、改善ではなく悪化につながります。

これをどこまで発展させたいかというと、信頼度の低いすべてのページを単一の汎用LLMにルーティングするのではなく、その特定の抽出タスク用に訓練されたページタイプ固有のモデルにルーティングすることです。商品ページ抽出専用にファインチューニングされた小型モデル。フォーラムスレッド用に訓練された別のモデル。ページタイプ分類器がすでにどのモデルを呼び出すかを教えてくれる——インフラはもう一方の端に特化されたモデルを用意するだけです。これが長期的に勝つと考えているアーキテクチャです:90%以上のページには高速なヒューリスティック、ヒューリスティックが限界に達するページタイプには特化したニューラルモデル。

私はまだこれを構築していません。しかし、信頼度スコアラーとページタイプ分類器はその基礎です。

見出し、SEO、およびHTML抽出の限界

ベンチマーク作業からの興味深い発見:ウェブページ上の視覚的に目立つセクションタイトルのうち、意味論的な<h1>-<h6>タグを使用しているのは一部のみです。残りは<strong>、スタイル付き<span>要素、またはCSSのfont-weight: boldを使用して、意味論的マークアップなしで視覚的な見出しを作成しています。

これはSEOと抽出の両方にとって重要です:

  • **Googleの見出しベクトル特許**は、<h1>-<h6>見出しに数値ベクトルを割り当て、トピック理解に利用します。
  • **Googleのページセグメンテーション特許**は、HTMLタグに関係なく視覚的に目立つテキストを検出するためにページを擬似的にレンダリングする方法を説明しています。
  • HTMLのみの抽出(rs-trafilaturaやすべてのヒューリスティック抽出器が行うこと)は、<h>タグを使用する見出ししか検出できません。<strong>セクションタイトル</strong>は太字テキストになり、見出しにはなりません。

HTMLを制御できる場合:常に意味論的な見出しタグを使用してください。見出しのように見える<strong>のセクションタイトルは、ほとんどの抽出ツールからは見えず、検索エンジンへの信号も弱くなります。

抽出パイプラインの場合:このギャップは、rs-trafilaturaを含む純粋なHTML-to-Markdownコンバーターにとっての理論的上限です——<strong>セクションタイトル</strong>は、見出しとしてではなく、Markdown出力において太字テキストとして出力されます。視覚的レンダリングやLLMによる解釈なしにこれを回避する方法はありません。構造検出が不確実なページに対して高速なヒューリスティック抽出とLLMによるフォールバックを組み合わせるハイブリッドパイプラインを支持する、もう一つの論拠です。

まだ改善が必要な点

これがまだ十分ではない点について率直に説明したいと思います。

ページタイプ分類は87%です。 これはおよそ8ページに1ページが誤った抽出プロファイルを割り当てられることを意味します。記事、フォーラム、商品ページについては精度は低い90%台——問題ありません。しかし、一覧ページ(再現率53%)とサービスページ(71%)は、しばしば記事として誤分類されます。全体的な精度を低い90%台に押し上げたいと考えており、おそらくそれは編集コンテンツとコンテンツインデックスを区別するためのより良い特徴量を意味するでしょう。

商品ページ抽出(F1 = 0.670)とコレクションページ(0.713)は理想的な状態ではありません。 商品ページは、多くのコンテンツがJSON-LDやタブ付きインターフェース内に存在するため困難です。コレクションページは、「コンテンツ」が商品カードとフィルターUIの混在であるため困難です。これらは、ヒューリスティックアプローチが最も強く限界に直面するページタイプです。

これはサイドプロジェクトです。 私はSEOコンサルタントです——有償の仕事が優先され、rs-trafilaturaにまったく注意が向かない週もあります。進捗は、クライアントプロジェクトの合間に時間があるときに集中的に生まれます。これを言い訳としてではなく、期待値を調整するために述べます——これはチームや会社に支えられたものではなく、一人の人間が可能なときに作業しているものです。

これらの制限のいずれかがあなたのユースケースにとって致命的なものである場合、MinerU-HTMLは記事中心のワークロードに対する強力な代替手段であり、独自の抽出を実行したくない場合はFirecrawlがインフラ面を処理します。

始め方

Rustcrates.ioからインストール:

[dependencies]
rs-trafilatura = "0.2"

PythonPyPIからインストール:

pip install rs-trafilatura

またはCLIバイナリを使用:

curl -s https://example.com/article | extract_stdin

出力は、タイトル、著者、日付、メインコンテンツ、ページタイプ、分類信頼度、抽出信頼度を含むJSONです。

関連


引用と参考文献

Googleのコンテンツ抽出とページセグメンテーションに関する特許

  • ページセグメンテーション — Mehta, B., et al. (2011). "Segmenting Web Pages." US Patent 7,930,307. Google. — HTMLタグ構造に依存せず、視覚的に区別されるコンテンツ領域を識別するためにページを擬似的にレンダリングする方法を説明。SEO by the Sea 解説
  • 見出しベクトル<h1><h6>見出しに数値ベクトルを割り当て、主題理解と文書構造分析に利用するGoogle特許。MarketBrew 解説
  • DOM Distiller — Chromeリーダーモードを支えるGoogleの本番環境用コンテンツ抽出システム。BoilerpipeベースでReadabilityスタイルのフォールバックを備える。ソースコード

基礎的な抽出研究

  • Boilerpipe — Kohlschutter, C., Fankhauser, P., Nejdl, W. (2010). "Boilerplate Detection using Shallow Text Features." WSDM 2010. — テキスト密度に基づくコンテンツ抽出の基礎論文。抽出をテキストブロックの二値分類として扱う。
  • Trafilatura — Barbaresi, A. (2021). "Trafilatura: A Web Scraping Library and Command-Line Tool for Text Discovery and Retrieval." ACL 2021. GitHub — 最も広く使用されているPython抽出ライブラリ。rs-trafilaturaはこの移植として始まった。
  • Readability — Mozilla (2010). Firefoxリーダービューを支えるアルゴリズム。テキスト密度とリンク比率でDOMノードをスコアリング。GitHub
  • jusText — Pomikalek, J. (2011). "Removing Boilerplate and Duplicate Content from Web Corpora." PhD thesis, Masaryk University. GitHub

ニューラル / LLM抽出

  • MinerU-HTML (Dripper) — Liu, M., et al. (2025). "Dripper: Token-Efficient Main HTML Extraction with a Lightweight LM." arXiv:2511.23119 | GitHub — Qwen3-0.6Bを二値要素分類用にファインチューニング。
  • ReaderLM-v2 — Jina AI (2025). "ReaderLM-v2: HTML to Markdown with a Small Language Model." arXiv:2503.01151 | HuggingFace — HTMLから直接Markdownを生成する15億パラメータモデル。
  • BoilerNet — Leonhardt, J., Anand, A., Khosla, M. (2020). "Boilerplate Removal using a Neural Sequence Labeling Model." WWW 2020 Companion.
  • Web2Text — Vogels, T., Ganea, O.E., Eickhoff, C. (2018). "Web2Text: Deep Structured Boilerplate Removal." ECIR 2018.

比較研究とベンチマーク

  • Bevendorff et al. — Bevendorff, J., Gupta, S., Kiesel, J., Stein, B. (2023). "An Empirical Comparison of Web Content Extraction Algorithms." SIGIR 2023. GitHub — 最も包括的な既存の比較。8つのデータセットを組み合わせ、14の抽出器を評価。重要な発見:「性能はジャンルに大きく依存する」。
  • ScrapingHub — (2019). Article Extraction Benchmark. 181 pages. GitHub
  • Evan Schwartz — (2024). "Comparing 13 Rust Crates for Extracting Text from HTML." Blog — RustのHTML解析オプションの包括的比較。

本作


Murrough Foley (ORCID: 0009-0008-3127-2101) はSEOコンサルタントであり、rs-trafilaturaの作者です。WCXBベンチマークはDOI 10.5281/zenodo.19316874で利用可能です。

マロウ・フォーリー
つながりましょう

ご質問やお仕事のご相談は、SNSでお気軽にどうぞ。