はじめに
貴殿らはWebスクレイピングで泥臭いデータ抽出に追われ、疲弊したことはありませんなwww
「文字化け」「表記揺れ」「クソサイトの突然の仕様変更」……これらはすべて役割を持てないゴミであり、異教徒の仕業ですぞwww
ChatGPT(OpenAI API)を使えば解決すると思いきや、従来の出力はフォーマットが不安定でパースエラーを起こすなど、論理的にあり得ない挙動が多発していましたなwww
しかし!OpenAIの「Structured Outputs(構造化出力)」を使えば、指定したJSON Schemaに100%確実に準拠したJSONが返ってきますぞwww 避けることのない絶対命中技ですぞwww
この記事では、Rubyの神Gem ruby-openai を使い、クソHTMLから「タイトル」「著者」「公開日」「要約」をフルアタ構成で一発抽出する方法を解説しますぞwww ヤーティ(開発環境)に入れ込みますぞwww
ヤーティ編成(開発環境)
- Ruby 3.2以上(必須ですぞwww)
-
ruby-openaiGem(最新版以外あり得ないwww)
gem install ruby-openai
環境変数にAPIキーを仕込む以外あり得ないwww
export OPENAI_ACCESS_TOKEN="your_openai_api_key_here"
構築(実装コード)
require 'openai'
require 'open-uri'
require 'json'
# 1. クライアントの初期化ですぞwww
client = OpenAI::Client.new(access_token: ENV['OPENAI_ACCESS_TOKEN'])
# 2. 仮想敵(ターゲットのHTML)ですぞwww
html_content = <<~HTML
<!DOCTYPE html>
<html>
<head><title>テックニュース - AIの未来</title></head>
<body>
<article>
<div class="meta">
<span class="author">著者: 山田 太郎</span>
<span class="date">公開日: 2026年7月14日</span>
</div>
<h1>RubyとAIの融合がもたらす開発の新時代</h1>
<p class="lead">本日開催されたカンファレンスにて、Rubyを用いたAIアプリケーション開発の新しいエコシステムが発表されました。</p>
<p>これにより、従来Pythonが主流だったデータ処理やLLMとの連携が、Rubyでもよりシームレスに行えるようになります。</p>
</article>
</body>
</html>
HTML
# 3. 完璧な型(Schema)を定義しますぞwww 妥協はあり得ないwww
json_schema = {
type: "object",
properties: {
title: { type: "string", description: "記事のタイトル" },
author: { type: "string", description: "記事の著者名" },
published_at: { type: "string", description: "公開日(YYYY-MM-DD形式に変換すること)" },
summary_points: {
type: "array",
items: { type: "string" },
description: "記事の要約を箇条書きで3点"
}
},
required: ["title", "author", "published_at", "summary_points"],
additionalProperties: false # 余計な行動(キー)はあり得ないwww
}
# 4. 対面勝利チャットAPI呼び出しですぞwww
response = client.chat(
parameters: {
model: "gpt-4o-mini", # 役割の持てる軽量高火力モデルですぞwww
messages: [
{ role: "system", content: "あなたはHTMLから正確に情報を抽出してJSONに変換する職人ですなwww" },
{ role: "user", content: "以下のHTMLから情報を抽出し、指定されたスキーマに従ってJSONで出力する以外あり得ないwww\n\nHTML:\n#{html_content}" }
],
response_format: {
type: "json_schema",
json_schema: {
name: "article_extractor",
strict: true, # 厳格(ストリクト)以外あり得ないwww
schema: json_schema
}
}
}
)
# 5. 勝利のパースですぞwww
raw_result = response.dig("choices", 0, "message", "content")
result_json = JSON.parse(raw_result)
puts "--- 美しいJSON(対面勝利) ---"
puts JSON.pretty_generate(result_json)
ロジカル解説ですぞwww
1. strict: true 以外あり得ないwww
strict: true と additionalProperties: false を指定することで、AIに余計な補助技(「はい、こちらがJSONです」等のゴミ前置きテキスト)を一切許しませんぞwww 常にこちらが想定した通りの最大火力JSONだけを出力させますぞwww
2. 表記揺れは確定一発ですぞwww
HTML内に「2026年7月14日」だろうが「令和8年」だろうが、Schemaの description に指示を書いておくだけで 2026-07-14 に一撃変換ですぞwww 正規表現をシコシコ書いて例外処理に怯えるなどという低火力な行動はあり得ないwww
3. コスパ最強の重火力ヤケモン
gpt-4o-mini は消費トークン(=PP)が非常に少なく、かつ高速で Structured Outputs をぶち込めるため、大量のバッチ処理でも完全に役割を持てますぞwww
結論ですぞwww
ruby-openai の Structured Outputs を使えば、どんなクソHTML相手でも後出しから完封できますぞwww
「NokogiriでCSSセレクタがズレて壊れたwww」と泣いている哀れな異教徒どもは、今すぐこの論理的な実装に切り替える以外あり得ないwww ヤーティ(Gemfile)への追加を推奨しますぞwww