Go Web Exact

🎯 概要: ウェブからLLM入力用のクリーンな記事本文を抽出するCLIツール
Go Web Exact は、Go言語で実装された、ウェブページからノイズを除去し、記事の本文や主要なコンテンツを正確に抽出するためのCLIツール、およびコアパッケージ群です。
特に、LLM(大規模言語モデル)に入力するためのクリーンで構造化されたテキストデータを生成することを目的としています。
🚀 特徴
-
高精度なコンテンツ抽出: 独自のセレクタとヒューリスティックを用いて、ナビゲーション、広告、コメントなどのノイズを排除し、メインの記事本文を特定します。
-
メモリ安全なリクエスト制限: レスポンスボディの最大読み込みサイズを25MBに制限することで、予期せぬ巨大ファイルによる**メモリ枯渇(OOM)**を防ぎます。
-
汎用的なリトライメカニズム (Exponential Backoff):
ネットワークの堅牢性を高めるため、リトライロジックをpkg/retryパッケージとして分離しました。HTTPクライアントやその他のAPIクライアントは、この汎用サービスを利用して、backoff/v4 を用いた自動リトライ機能を実現します。
🔃 デフォルトのリトライ設定(pkg/retry の定数に基づく)
| 設定項目 |
値 |
概要 |
初期間隔 (InitialBackoffInterval) |
5秒 |
最初の失敗から次の試行までの待機時間。指数バックオフの開始点です。 |
最大間隔 (MaxBackoffInterval) |
30秒 |
指数バックオフにより待機時間が最大となる秒数。サーバーへの過負荷を防ぎます。 |
デフォルト最大試行回数 (DefaultMaxRetries) |
3回 |
デフォルトでの最大リトライ回数。 |
| 遅延戦略 |
指数バックオフ (Jitter適用) |
待機時間を指数関数的に増加させ、ランダムな揺らぎを加えることで、リトライの集中を避けます。 |
注: 最大試行回数を含む全ての設定は、httpclient.New() 関数に httpclient.WithMaxRetries(N) オプションを渡すことで上書き可能です。
-
堅牢なHTTP処理 (GET/POST対応): context を使用したタイムアウト制御に加え、GETリクエストとJSON POSTリクエストの両方をサポートし、不安定なネットワーク環境や一時的なサーバーエラーに対応します。
-
型安全なエラー処理: HTTP 4xx エラー(クライアントエラー)を非リトライ対象のカスタムエラー型で返し、5xx エラー(サーバーエラー)やネットワークエラーのみをリトライ対象とすることで、リソースの無駄遣いを防ぎます。
-
テキストの整形: 抽出されたテキストから不要な改行や連続するスペースを除去し、クリーンな整形済みテキストを返します。
-
テーブルデータの構造化: HTMLテーブルをパースし、Markdown風の行形式に整形してテキストに含めます。
⚙️ CLIとしての利用
このプロジェクトは、cmd/root.go をエントリーポイントとする実行可能なCLIアプリケーションとして設計されています。
ビルドと実行
プロジェクトルートで以下のコマンドを実行し、バイナリを生成します。
# バイナリのビルド
go build -o bin/web_extractor
使用方法
生成された web_extractor を使用して、URLを指定します。
# 位置引数としてURLを指定
./bin/web_extractor https://example.com/article/123
# フラグとしてURLを指定し、タイムアウトを15秒に設定
./bin/web_extractor -u https://example.com/article/123 -t 15
ヘルプメッセージ:
./bin/web_extractor --help
📦 ライブラリ利用方法
主要な機能は pkg/httpclient、pkg/retry、pkg/web パッケージとして提供されます。これらは依存性注入 (DI) の原則に従って設計されています。
1. インポート
import (
"context"
"time"
"github.com/shouni/go-web-exact/pkg/httpclient"
"github.com/shouni/go-web-exact/pkg/web"
// リトライは httpclient 内部で利用されるため、通常は直接インポート不要
)
web.Extractor は httpclient.Client を依存性として受け取ります。
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/shouni/go-web-exact/pkg/httpclient"
"github.com/shouni/go-web-exact/pkg/web"
)
func main() {
url := "https://blog.golang.org/gofmt"
// 1. HTTPクライアント (Fetcher) を設定
// 個々のリクエストのタイムアウトを30秒に設定
clientTimeout := 30 * time.Second
// 2.WithMaxRetries は ClientOption として New 関数に渡す
fetcher := httpclient.New(clientTimeout, httpclient.WithMaxRetries(5)) // 例:デフォルト(3回)を上書きして最大5回のリトライを設定
// 3. Extractor を初期化 (DI)
extractor := web.NewExtractor(fetcher)
// 4. 全体処理のコンテキストを設定(例:全体で60秒のタイムアウト)
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
// 5. 抽出の実行
text, hasBody, err := extractor.FetchAndExtractText(url, ctx)
if err != nil {
log.Fatalf("抽出エラー: %v", err)
}
if !hasBody {
fmt.Printf("本文は見つかりませんでしたが、タイトルを取得しました:\n%s\n", text)
} else {
fmt.Println("--- 抽出された本文 ---")
fmt.Println(text)
fmt.Println("-----------------------")
}
}
🛠️ 開発者向け情報
パッケージ構成
| ディレクトリ |
パッケージ名 |
役割 |
cmd/ |
main |
CLIのエントリーポイントおよびコマンドラインオプションの定義。 |
pkg/httpclient |
httpclient |
HTTPリクエストの実行、カスタムエラー(NonRetryableHTTPError)の定義。pkg/retry を利用して堅牢性を確保。Client 構造体は HTTPClient インターフェースを満たします。 |
pkg/retry |
retry |
汎用的なリトライ実行ロジック(backoff/v4 の設定、指数バックオフ、最大試行回数制御)を抽象化し、提供。 |
pkg/web |
web |
HTMLの解析 (goquery)、メインコンテンツの特定、ノイズ除去、テキスト整形ロジック。 |
📜 ライセンス (License)
このプロジェクトは MIT License の下で公開されています。