mcpField
A
article-extractor

article-extractor

github.com/michalparkola生産性564632 回インストール33 週間前に更新
リポジトリ

article-extractor について

記事やブログの URL から読みやすい本文を抽出するスキルです。reader、trafilatura、基本解析の順に試し、整形した内容を記事タイトル由来のテキストファイルに保存します。

主な機能

  1. 01ページの雑多な要素を除いて本文を抽出
  2. 02reader、trafilatura、代替解析の順に試行
  3. 03抽出テキストを整形
  4. 04記事タイトルからテキストファイル名を作成
  5. 05プレビューと保存先を提示

活用シーン

  1. 01Web 記事を読みやすいテキストで保存
  2. 02ナビゲーションや広告を除いてブログ本文を抽出
  3. 03優先する抽出ツールがない環境で記事本文を取得

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/michalparkola/tapestry-skills --skill article-extractor

インストール後、Claude Code で/article-extractorを入力して読み込まれたか確認します。

詳細

記事抽出

このスキルは、ウェブ記事やブログ投稿から主要なコンテンツを抽出し、ナビゲーション、広告、ニュースレター登録フォームなどの不要な要素を取り除きます。読みやすく整えたテキストを保存します。

このスキルを使用するタイミング

ユーザーが次のことを行った場合に有効にします。

  • 記事やブログの URL を提示し、テキストの内容を求める
  • 「この記事をダウンロードして」と依頼する
  • 「[URL] からコンテンツを抽出して」と依頼する
  • 「このブログ投稿をテキストとして保存して」と依頼する
  • 邪魔な要素のない、きれいな記事のテキストを必要としている

仕組み

優先順位:
  1. ツールがインストールされているか確認する(reader または trafilatura)
  2. 利用可能な最適なツールを使って記事をダウンロードし、抽出する
  3. コンテンツを整理する(余分な空白を削除し、適切に書式を整える)
  4. 記事のタイトルをファイル名としてファイルに保存する
  5. 保存先を確認し、プレビューを表示する

インストールの確認

次の順序で記事抽出ツールを確認します。

オプション 1:reader(推奨 — Mozilla の Readability)
command -v reader

インストールされていない場合:

npm install -g @mozilla/readability-cli
# or
npm install -g reader-cli
オプション 2:trafilatura(Python ベースで、非常に優れています)
command -v trafilatura

インストールされていない場合:

pip3 install trafilatura
オプション 3:フォールバック(curl + 簡易解析)

利用可能なツールがない場合は、基本的な curl とテキスト抽出を使用します(信頼性は低くなりますが、機能します)。

抽出方法

方法 1:reader を使用する(ほとんどの記事に最適)
# Extract article
reader "URL" > article.txt

メリット:

  • Mozilla の Readability アルゴリズムに基づいています
  • 不要な要素の削除に優れています
  • 記事の構成を保持します
方法 2:trafilatura を使用する(ブログやニュースに最適)
# Extract article
trafilatura --URL "URL" --output-format txt > article.txt

# Or with more options
trafilatura --URL "URL" --output-format txt --no-comments --no-tables > article.txt

メリット:

  • 非常に正確に抽出できます
  • さまざまなサイト構成に対応します
  • 複数の言語を処理できます

オプション:

  • --no-comments:コメントセクションをスキップします
  • --no-tables:データテーブルをスキップします
  • --precision:再現率より適合率を優先します
  • --recall:より多くのコンテンツを抽出します(一部のノイズが含まれる場合があります)
方法 3:フォールバック(curl + 基本的な解析)
# Download and extract basic content
curl -s "URL" | python3 -c "
from html.parser import HTMLParser
import sys

class ArticleExtractor(HTMLParser):
    def __init__(self):
        super().__init__()
        self.in_content = False
        self.content = []
        self.skip_tags = {'script', 'style', 'nav', 'header', 'footer', 'aside'}
        self.current_tag = None

    def handle_starttag(self, tag, attrs):
        if tag not in self.skip_tags:
            if tag in {'p', 'article', 'main', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'}:
                self.in_content = True
        self.current_tag = tag

    def handle_data(self, data):
        if self.in_content and data.strip():
            self.content.append(data.strip())

    def get_content(self):
        return '\n\n'.join(self.content)

parser = ArticleExtractor()
parser.feed(sys.stdin.read())
print(parser.get_content())
" > article.txt

注: 信頼性は低くなりますが、依存関係なしで動作します。

記事タイトルの取得

ファイル名に使用するタイトルを抽出します。

reader を使用する場合:
# reader outputs markdown with title at top
TITLE=$(reader "URL" | head -n 1 | sed 's/^# //')
trafilatura を使用する場合:
# Get metadata including title
TITLE=$(trafilatura --URL "URL" --json | python3 -c "import json, sys; print(json.load(sys.stdin)['title'])")
curl を使用する場合(フォールバック):
TITLE=$(curl -s "URL" | grep -oP '<title>\K[^<]+' | sed 's/ - .*//' | sed 's/ | .*//')

ファイル名の作成

ファイルシステムで使用できるようにタイトルを整えます。

# Get title
TITLE="Article Title from Website"

# Clean for filesystem (remove special chars, limit length)
FILENAME=$(echo "$TITLE" | tr '/' '-' | tr ':' '-' | tr '?' '' | tr '"' '' | tr '<' '' | tr '>' '' | tr '|' '-' | cut -c 1-100 | sed 's/ *$//')

# Add extension
FILENAME="${FILENAME}.txt"

ワークフロー全体

ARTICLE_URL="https://example.com/article"

# Check for tools
if command -v reader &> /dev/null; then
    TOOL="reader"
    echo "Using reader (Mozilla Readability)"
elif command -v trafilatura &> /dev/null; then
    TOOL="trafilatura"
    echo "Using trafilatura"
else
    TOOL="fallback"
    echo "Using fallback method (may be less accurate)"
fi

# Extract article
case $TOOL in
    reader)
        # Get content
        reader "$ARTICLE_URL" > temp_article.txt

        # Get title (first line after # in markdown)
        TITLE=$(head -n 1 temp_article.txt | sed 's/^# //')
        ;;

    trafilatura)
        # Get title from metadata
        METADATA=$(trafilatura --URL "$ARTICLE_URL" --json)
        TITLE=$(echo "$METADATA" | python3 -c "import json, sys; print(json.load(sys.stdin).get('title', 'Article'))")

        # Get clean content
        trafilatura --URL "$ARTICLE_URL" --output-format txt --no-comments > temp_article.txt
        ;;

    fallback)
        # Get title
        TITLE=$(curl -s "$ARTICLE_URL" | grep -oP '<title>\K[^<]+' | head -n 1)
        TITLE=${TITLE%% - *}  # Remove site name
        TITLE=${TITLE%% | *}  # Remove site name (alternate)

        # Get content (basic extraction)
        curl -s "$ARTICLE_URL" | python3 -c "
from html.parser import HTMLParser
import sys

class ArticleExtractor(HTMLParser):
    def __init__(self):
        super().__init__()
        self.in_content = False
        self.content = []
        self.skip_tags = {'script', 'style', 'nav', 'header', 'footer', 'aside', 'form'}

    def handle_starttag(self, tag, attrs):
        if tag not in self.skip_tags:
            if tag in {'p', 'article', 'main'}:
                self.in_content = True
        if tag in {'h1', 'h2', 'h3'}:
            self.content.append('\n')

    def handle_data(self, data):
        if self.in_content and data.strip():
            self.content.append(data.strip())

    def get_content(self):
        return '\n\n'.join(self.content)

parser = ArticleExtractor()
parser.feed(sys.stdin.read())
print(parser.get_content())
" > temp_article.txt
        ;;
esac

# Clean filename
FILENAME=$(echo "$TITLE" | tr '/' '-' | tr ':' '-' | tr '?' '' | tr '"' '' | tr '<>' '' | tr '|' '-' | cut -c 1-80 | sed 's/ *$//' | sed 's/^ *//')
FILENAME="${FILENAME}.txt"

# Move to final filename
mv temp_article.txt "$FILENAME"

# Show result
echo "✓ Extracted article: $TITLE"
echo "✓ Saved to: $FILENAME"
echo ""
echo "Preview (first 10 lines):"
head -n 10 "$FILENAME"

エラー処理

よくある問題

1. ツールがインストールされていない

  • 別のツールを試します(reader → trafilatura → フォールバック)
  • インストールを提案します:「reader は次のコマンドでインストールできます:npm install -g reader-cli」

2. ペイウォールまたはログインが必要

  • 抽出ツールが失敗する場合があります
  • ユーザーに伝えます:「この記事の抽出には認証が必要です。抽出できません。」

3. 無効な URL

  • URL の形式を確認します
  • リダイレクトありとなしの両方で試します

4. コンテンツが抽出されない

  • サイトで多くの JavaScript が使われている可能性があります
  • フォールバック方法を試します
  • 抽出に失敗した場合はユーザーに伝えます

5. タイトルに特殊文字が含まれている

  • ファイルシステムで使用できるようにタイトルを整えます
  • 次の文字を削除します:/、:、?、"、<、>、|
  • - に置き換えるか、削除します

出力形式

保存されるファイルの内容:
  • 記事のタイトル(取得できる場合)
  • 著者(ツールで取得できる場合)
  • 記事の主要なテキスト
  • セクションの見出し
  • ナビゲーション、広告、不要な要素なし
削除される要素:
  • ナビゲーションメニュー
  • 広告やプロモーションコンテンツ
  • ニュースレター登録フォーム
  • 関連記事のサイドバー
  • コメントセクション(任意)
  • ソーシャルメディアボタン
  • Cookie 通知

最良の結果を得るためのヒント

1. ほとんどの記事には reader を使用する

  • 幅広い用途に適したツールです
  • Firefox の Reader View に基づいています
  • ほとんどのニュースサイトやブログで動作します

2. 次の場合は trafilatura を使用する:

  • 学術記事
  • ニュースサイト
  • 複雑なレイアウトのブログ
  • 英語以外のコンテンツ

3. フォールバック方法の制限:

  • 一部のノイズが含まれる場合があります
  • 段落の検出精度が低くなります
  • シンプルなサイトでは、何もしないよりは有効です

4. 抽出品質を確認する:

  • 必ずユーザーにプレビューを表示します
  • 正しく見えるか尋ねます
  • 必要に応じて別のツールを試すことを提案します

使用例

簡単な抽出:

# User: "Extract https://example.com/article"
reader "https://example.com/article" > temp.txt
TITLE=$(head -n 1 temp.txt | sed 's/^# //')
FILENAME="$(echo "$TITLE" | tr '/' '-').txt"
mv temp.txt "$FILENAME"
echo "✓ Saved to: $FILENAME"

エラー処理あり:

if ! reader "$URL" > temp.txt 2>/dev/null; then
    if command -v trafilatura &> /dev/null; then
        trafilatura --URL "$URL" --output-format txt > temp.txt
    else
        echo "Error: Could not extract article. Install reader or trafilatura."
        exit 1
    fi
fi

ベストプラクティス

  • ✅ 抽出後は必ずプレビュー(最初の 10 行)を表示します
  • ✅ 保存する前に、抽出が成功したことを確認します
  • ✅ ファイルシステムとの互換性を考慮してファイル名を整えます
  • ✅ 主な方法で失敗した場合は、代替方法を試します
  • ✅ 使用したツールをユーザーに伝えます
  • ✅ ファイル名は適切な長さ(100 文字未満)にします

抽出後

ユーザーに次の内容を表示します:

  1. 「✓ 抽出しました:[Article Title]」
  2. 「✓ 保存先:[filename]」
  3. プレビュー(最初の 10~15 行)
  4. ファイルサイズと保存場所

必要に応じて確認します:

  • 「Ship-Learn-Next のプランも作成しましょうか?」(ship-learn-next スキルを使用している場合)
  • 「別の記事も抽出しますか?」

コメント