注釈付きの「記事中心」フィクスチャセットでは、newspaper4k は 22 件すべてで出力を返し、採点対象の本文要素の 98.65% を回収し、ラベル付きのボイラープレートトークンは一切含みませんでした。この 3 つの観点だけを見ると、今回の評価基準ではかなり有力です。ただし、これで万能の勝者とまでは言えません。
このセットで、この 3 条件を同時に満たしたのは他にありませんでした。Mozilla Readability は採点対象のコンテンツをすべて回収した一方で、より多くのボイラープレートを含みました。goose3 はラベル付きボイラープレートを含まなかったものの、2 回空文字を返しました。用途によっては別のライブラリが最適になることもあります。
導入前に、1 つだけ明確に注意しておきたい既定値があります。
newspaper4k とは
newspaper4k は newspaper3k のメンテナンス継続版で、さらにその前身である newspaper の Python 3 系統にあたります。この系譜はヘルプを探すときに重要です。オンラインで見つかる情報の多くは前身のものを指しており、一部の API はすでに変わっているためです。
公式リポジトリはこちらです: newspaper4k の公式リポジトリ。

このライブラリで最もやりがちな誤用は、たとえば set_html() を呼んでしまうことです。そんなメソッドは存在しません。HTML は download() 経由で渡します。
from newspaper import Article
a = Article(url="https://example.com/story")
a.download(input_html=html) # set_html() ではない
a.parse()
text = a.text
私も最初の実行ではこれを間違え、原因が自分にあるか確認する前に 22 件中 0 件として採点してしまいました。実際には私のミスでした。
返ってくるのは単なる本文だけではありません。Article オブジェクトには text、title、authors、publish_date、top_image、images、movies、meta_description、meta_lang、tags、article_html などのフィールドがあります。keywords と summary は、後述の任意の NLP 導入とコーパス設定が必要です。フィールドの有無は確認しましたが、メタデータの正確性は採点していません。
検証バージョン: 0.9.6、MIT ライセンス、GitHub スター数 1,135、リポジトリの最終 push は 2026-07-31。これは時点情報であり、保守状況の完全な評価ではありません。Python 3.14.2。
結果
| ライブラリ | 記事再現率(22 件中) | ボイラープレート混入 | 本文トークン精度 | 混入トークン数 | 出力あり |
|---|---|---|---|---|---|
| Readability | 1.0000 | 0.2353 | 0.9109 | 35 | 22/22 |
| trafilatura | 0.9865 | 0.0588 | 0.9411 | 4 | 22/22 |
| newspaper4k | 0.9865 | 0.0000 | 0.9452 | 0 | 22/22 |
| resiliparse | 0.9054 | 0.0588 | 0.9381 | 7 | 22/22 |
| jusText | 0.8378 | 0.4706 | 0.8760 | 74 | 19/22 |
| goose3 | 0.8243 | 0.0000 | 1.0000 | 0 | 20/22 |
sixway-scores.json。各フィクスチャ内の各ユニットには一意のセンチネル・トークンが付いているため、「回収した」「混入した」は類似度ではなく、厳密な部分文字列の一致です。再現率は 22 件すべてを対象とし、混入率と精度は、本文とボイラープレートの両方を含む 11 件を対象にしています。
分けて見るべき列が 3 つあります。
すべてのページに応答しました。 goose3 と jusText はそうではなく、それぞれ 22 件中 20 件、19 件でした。見た目以上に重要です。というのも、この表の精度や F1 は 出力を返した場合に限って 計算されるからです。空文字を返すライブラリは比率のどちら側にも寄与しないため、返さないこと自体が“得”になってしまいます。goose3 の 1.0000 の精度は 11 件中 10 件で採点された値であり、newspaper4k の 0.9452 は 11 件中 11 件での値です。つまり、同じ指標ではありません。
ボイラープレートの混入はゼロでした。 フィクスチャには意図的に厄介なボイラープレートが含まれています。記事の隣接要素として置かれた中立クラスの宣伝ブロック、無害そうな class 名を持つコメントスレッド、「ad」と書かれていない広告ブロックなどです。Readability の sibling-append ヒューリスティックはそれらのいくつかを取り込んでしまいましたが、newspaper4k は一切取り込みませんでした。
74 ユニット中 1 つだけ取りこぼしました。 そして、その 1 つは他のライブラリとも共通の落とし穴でした。
この取りこぼしは非プローズのフィクスチャにあります。段落中心ではなく、表、コードブロック、短い項目、画像キャプションで構成されたページで、落としたのは キャプション です。これが取りこぼされたのは newspaper4k だけではありません。
| ライブラリ | 非プローズページでの再現率 | 落としたユニット |
|---|---|---|
| Readability | 1.000 | — |
| jusText | 1.000 | — |
| trafilatura | 0.875 | キャプション |
| resiliparse | 0.875 | キャプション |
| newspaper4k | 0.875 | キャプション |
| goose3 | 0.250 | 2 つの表、コードブロック、2 つの短い項目、キャプション |
3 つのライブラリが同じキャプションだけを落としており、これは 3 つの別バグというより、「キャプションをどれだけ重要視するか」という共通の継承前提に見えます。あなたのコンテンツがドキュメント、レシピ、あるいはキャプションに段落とは別の情報があるものなら、採用前に必ずテストすべきです。Readability と jusText はこのキャプションを保持していました。
同じフィクスチャでは goose3 がほぼ壊れ、ページの 4 分の 3 を失いました。つまり、「非プローズコンテンツ」は、この 6 製品の差がヘッドライン表よりはるかに大きく出る軸です。
速度面では、22 フィクスチャに対する newspaper4k の抽出時間中央値は 2.69 ms で、6 つの中で最も遅く、最悪値は 199.81 ms でした。resiliparse の中央値 0.06 ms と比べると、この制御実験では 45 倍の差です。単一ページのワークフローなら中央値は小さく見えるかもしれませんが、負荷時のスループットやテールレイテンシは今回の測定対象ではありません。コールドインポートについては後述します。
まず 1 行目で変えたい既定値

公式リファレンス: newspaper4k documentation。
同梱の Configuration オブジェクトを読むと、設定項目は 22 個あります。そのうち 1 つがこれです。

_honor_robotstxt = False
newspaper4k は、明示しない限り robots.txt を尊重しません。Article(url).download() を input_html なしで呼ぶと、指し示した URL のサイト側 robots ファイルに関係なく取得しに行きます。
HTML をすでに持っている場合のパーサーとして使うなら合理的な既定値ですが、1,000 件の URL に向けた後で本番環境に入って初めて気づくには危険すぎる設定です。Configuration で honor_robotstxt=True を設定するか、input_html を渡して取得処理を自前で行ってください。今回のテストではすべて後者にしています。
知っておくべき設定をもう 2 つ。
number_threads = 10。 複数記事向けヘルパーの既定並列数は 10 です。並列数は毎秒リクエスト数そのものではありませんが、ホスト単位の制限やスケジューリングを明示しなければ同時リクエストが一気に増える可能性があります。
fetch_images = True。 画像取得が既定で有効なため、オフライン利用では少し気になります。socket.connect をブロックした状態でも、今回検証した newspaper4k 0.9.6 のパス、つまり download(input_html=…) の後に 1 つの保持済み HTML 入力へ parse() を実行する流れは完了し、1,292 文字を返し、ネットワーク接続は 0 回 でした。これはあくまでこの経路に関する結果であり、すべての設定、プラグイン、コンテンツ型、将来版に一般化できるわけではありません。
その他の既定値は妥当です。min_word_count 300、min_sent_count 7、max_text 100,000、http_success_only True、memorize_articles True、follow_meta_refresh False、allow_binary_content False。
セットアップの実態
pip install newspaper4k では 22 パッケージ、47.5 MiB が約 6 秒で入ります。新しい subprocess でのコールドインポートは 2.812 秒。比較中で最も遅い結果でした。
| ライブラリ | パッケージ数 | site-packages | コールドインポート | 抽出 p50 |
|---|---|---|---|---|
| resiliparse | 5 | 21.0 MiB | 0.015 s | 0.06 ms |
| jusText | 3 | 22.4 MiB | 0.777 s | 0.56 ms |
| goose3 | 16 | 44.3 MiB | 2.181 s | 1.85 ms |
| newspaper4k | 22 | 47.5 MiB | 2.812 s | 2.69 ms |
| trafilatura | 17 | 69.9 MiB | 1.584 s | 0.51 ms |
install-and-import.json。各ライブラリはそれぞれ空の仮想環境で実行しており、隣のライブラリの依存関係は継承していません。
インポートに 2.812 秒かかるのは、resiliparse の 15 ミリ秒の 187 倍です。長時間動くワーカーなら 1 回払うだけなので大きな問題ではありませんが、serverless 関数ではコールドスタートのたびに支払うことになり、その場合は抽出精度がどれだけ良くても newspaper4k は不向きです。
インストール時の注意点も 1 つあります。インポート時に次の警告が出ます。
UserWarning: nltk is not installed. Some NLP features will be unavailable. Install it with: pip install 'newspaper4k[nlp]'
今回のテストではその機能を使っておらず、NLP がなくても抽出は問題なく動作しました。ただし、ベースインストールが完全版ではないことは明確ですし、newspaper4k[nlp] を入れると依存ツリーとコーパスのダウンロードがかなり重くなります。キーワード抽出や要約が必要な場合のみ、そのコストを見込んでください。
メモリと、壊れた HTML がそれに与える影響
このシリーズのレビューで未測定として扱っていた 2 点を、今回測定しました。
より広いストレステストの背景は、10 ライブラリのメモリと不正 HTML の比較 にあります。
ピーク常駐メモリ は /usr/bin/time -l で測定し、各セルごとに新しいプロセスを立てました。インポート時の下限はライブラリが読み込まれてアイドル状態のときのコスト、ピークは文書込みのコストです。
| ライブラリ | ランタイム | インポート下限 (MiB) | 226 KB HTML のピーク (MiB) | 10 MB HTML のピーク (MiB) |
|---|---|---|---|---|
| html2text | python3.14 | 18.7 | 19.9 | 71.2 |
| pyquery | python3.14 | 30.3 | 33.9 | 172.5 |
| resiliparse | python3.14 | 20.5 | 25.1 | 225.1 |
| markdownify | python3.14 | 23.9 | 28.9 | 278.5 |
| goose3 | python3.14 | 44.1 | 52.4 | 398.5 |
| cheerio | node22 | 66.8 | 76.5 | 398.5 |
| justext | python3.14 | 30.3 | 36.6 | 431.2 |
| newspaper4k | python3.14 | 52.6 | 61.8 | 668.5 |
| trafilatura | python3.14 | 52.5 | 64.8 | 927.1 |
| turndown | node22 | 47.8 | 68.4 | 2947.1 |
memory-results.json。Python と Node の基準値は互いに直接比較できません。どちらにもインタプリタのオーバーヘッドが含まれます。
newspaper4k の下限は 52.6 MiB、10 MB 入力時のピークは 668.5 MiB で、Python 系では 2 番目に重い部類です。普通のページでは問題にならなくても、大きな文書をメモリ制限付きワーカーでまとめて処理するなら重要です。
壊れた HTML。 以下のように 1 か所だけ壊した 12 文書、つまり未閉じタグ、入れ子が崩れたインライン要素、スペースを含む未引用属性、余計な閉じタグ、<html> がない、重複属性、タグ途中で切れた文書、不正エンティティ、未閉じの <script>、偽の charset 宣言、マークアップを含むコメント、600 階層のネスト、に加えて、サイズを合わせた整形式の制御文書 2 件を用意しました。「何も返さなかった」だけでは、もし同サイズの整形式文書でも黙るのなら、不正さの影響だとは言えないからです。
制御ケースと壊れたケースは、生の結果では明確に分かれます。
| グループ | 文書数 | 例外発生 | 空出力 | 採点対象センチネルの回収 |
|---|---|---|---|---|
| 整形式のサイズ一致制御 | 2 | 0 | 0 | 不正 HTML スコアでは未使用 |
| 不正 HTML フィクスチャ | 12 | 0 | 10 | 5/33(未閉じ <script> ケースを除く) |
2 つの制御ケースはそれぞれ 70 文字と 1,351 文字を出力し、12 件中 10 件の不正入力は空文字でした。これにより、この設計では、沈黙は単に入力が短いからではなく不正 HTML に起因すると判断できます。スコアラーは、対象となる 11 件の不正文書について、見出し・段落・リンクのセンチネルを確認します。未閉じ \malformed-results.json`](https://github.com/thunderbit-operations/scraper-benchmark/blob/f01471d6eafb345df0f009f1fb517622c43a1dd7/cross-cuts/robustness-and-memory/artifacts/malformed-results.json) を参照してください。これは単なる「例外を出さなかった」成功ではなく、採用判断に持ち込むべき重要な回復制約です。
長所と短所
長所。 この比較ではラベル付きボイラープレートトークンが 0、22 件すべての制御済み記事フィクスチャで出力あり、採点対象の記事再現率は 0.9865 でした。記事本文とメタデータ系フィールドを露出しますが、メタデータの正確性は未検証です。保持済み HTML を使うテスト経路では、socket.connect をブロックした状態でネットワーク接続は試みられませんでした。確認時点でリポジトリには最近の日時付き push がありましたが、保守性全体の健全性は評価していません。
短所。 2.812 秒で、このセット内では最も重いコールドインポートです。さらに、測定された site-packages は 22 パッケージ / 47.5 MiB でした。honor_robotstxt の既定は False、複数記事ヘルパーの既定並列数は 10 です。ベースインストールでは NLTK 不足の警告が出るため、キーワードや要約には重い任意インストールが必要です。もっとも重要なのは、12 件中 10 件の不正フィクスチャで空出力になった一方、整形式の制御ケース 2 件ではテキストが返ったことです。
どんな人に向いていて、どんな人には向かないか
newspaper4k を検討すべきケース は、優先順位が「HTML はすでにある状態で、記事中心コーパスに対して空でないテキストを返す」「そのコーパスでラベル付きボイラープレートを最小化する」「多少遅いコールドインポートは許容する」の順に並ぶ場合です。この明示的なルールでは、このフィクスチャ比較で先頭に立ちました。別の基準なら、採点済みコンテンツの保持最大化を求めるなら Readability、起動速度と中央値抽出速度を重視するなら resiliparse を選ぶこともできます。
避けるか、かなり慎重に事前検証すべきケース は、コールドスタートが支配的な場合、47.5 MiB の site-packages が重い場合、あるいは不正 HTML からの復元が重要な場合です。resiliparse はここでは 187 倍速くインポートできましたが、品質列のすべてで trafilatura と同率ではありませんでした。trafilatura は記事再現率が高く、混入や精度の傾向も異なりました。newspaper4k は記事向けであり、商品一覧やダッシュボードは未テストなので、その挙動はここでは主張しません。
何をするにしても、取得させるなら honor_robotstxt は必ず設定してください。 これは性能に関する話ではありません。
マネージド API が適する場面
newspaper4k は呼び出し側が渡した HTML を解析でき、取得経路も持っています。一方、マネージドな抽出サービスは、取得、レンダリング、スキーマ整備をベンダー側の境界に閉じ込めます。私たちは Thunderbit を提供していますが、このフィクスチャセットでは実行していないため、品質、レンダリング、bot 対策、レイテンシ、コストの比較は行っていません。保持済みの記事 HTML について、このレビューが示しているのは newspaper4k 単体の結果です。記事以外の対象には、それぞれ別の評価が必要です。
同じ 6 つの抽出器でのフィクスチャ比較は、6 ライブラリの抽出比較 をご覧ください。
ホスト型サービス全体を見るなら、Web スクレイピング API の総覧 が参考になります。セルフホストの代替案なら、オープンソーススクレイパーの総集編 をどうぞ。テキストをモデルに入れるなら、Python で HTML を Markdown に変換する方法 で、どこで忠実性が落ちるかを確認できます。
newspaper4k は使うべきか?
HTML がすでにあるなら、記事テキスト抽出の有力候補として newspaper4k を扱い、導入前には自分のコーパスで実サイトを使った検証を行ってください。今回の制御セットでは、記事再現率の高さ、ラベル付きボイラープレートのなさ、22 件すべてで空でない出力を返したことが確認できました。ただし、実ページやメタデータ精度は対象外であり、12 件中 10 件の不正フィクスチャは空出力でした。
取得経路を使うなら、honor_robotstxt=False、10 スレッド並列、ホスト単位のレート制御を必ず見直してください。コールドスタートや依存関係の重さが重要なら、2.812 秒のローカルインポート時間と 47.5 MiB の site-packages を、自分のデプロイ環境で測ってください。一般的なコンテナコストとして片付けるべきではありません。
Web データ抽出に Thunderbit を試す Get Started Free
よくある質問
なぜ set_html() が動かないのですか?
newspaper4k にはそのメソッドが存在しないからです。HTML は download(input_html=html) で渡してから parse() します。検索結果には newspaper3k の例が出てくるため、よくある勘違いです。私も最初の実行でやってしまい、採点前にテストハーネスを修正しました。
newspaper4k は robots.txt を尊重しますか?
既定ではしません。honor_robotstxt は False で出荷されます。ライブラリに取得させるなら Configuration で True にしてください。あるいは input_html を渡して自前で取得してください。複数記事処理の既定並列数も 10 です。これは勝手な並列化であって、固定のリクエストレートではありません。取得時はホスト単位の制限を明示してください。
parse() はネットワーク要求を行いますか?
newspaper4k 0.9.6 では、検証した download(input_html=…) と parse() の経路は、socket.connect をブロックした状態で保持済み HTML 入力に対して接続試行を 1 回も行いませんでした。ただし、これでパーサー設定、プラグイン、コンテンツ型、将来版のすべてがネットワークなしだと証明されたわけではありません。
インポート時の NLTK 警告は何ですか?
ベースインストールには NLTK が含まれていないため、キーワード抽出と要約は使えず、そのことをライブラリ自身がインポート時に通知します。抽出機能自体には影響しません。ここで測定したものはすべてベースインストールで実行しました。pip install 'newspaper4k[nlp]' を入れると、より重い依存ツリーとコーパスのダウンロードが追加されます。
このレビューで未テストのものは何ですか? 実世界のページです。ここで扱ったのは、ラベル付きユニットを持つ制御フィクスチャです。メタデータ項目は一覧化しましたが、タイトル、著者、日付、画像の正確性は採点していません。多言語抽出、NLP 追加機能、マルチスレッドのソース巡回、負荷下のスループットも未検証です。プロセスのピークメモリは 226 KB と 10 MB の HTML 入力 1 件ずつで測定しており、並行処理や継続負荷下ではありません。


