はじめに
AIの検索リサーチで料金の数字を集めて、記事にまとめる。
自分もそのやり方で比較記事を1本公開したあと、公開済みのその記事を、WebSearch(Web上の情報を検索して集めてくる機能)で各社の公式価格ページと照合しました。
そうしたら、料金の数値が3つずれていました。
しかも一番痛かったのが、記事の結論を支えていた数字です。
本文では、あるサービスを「国内最安」と書いていました。
公式の料金を並べ直したら、そのサービスは並びのいちばん高い側にいました。
この記事は、そのときに何がずれたのか、どう直し、そのあとにどんな工程を足したのかの記録です。
こんな人に向けて書いています
- AIの検索リサーチで数字を拾って、記事やドキュメントに書いている人
- 料金・プランみたいな「あとから変わる数字」を扱うコンテンツを作っている人
- AIに書かせる工程は組んだけれど、確認の工程はまだ人の気合いに任せている人
この記事でわかること
- AI由来の数値がどういう形で混ざるのか(「捏造」ではない、という話)
- 数値のズレがどういう条件で起こるのか、他にどこで起こりえて、何が厄介なのか
- 公開前に通す照合工程の手順と、照合記録を構造化する形
前提
特定の言語・フレームワークの話ではありません。
対象は公開済みの比較記事1本で、数値の照合はWebSearchで各社の公式価格ページを開いて行いました。
そして、この記事にはサービス名と実際の金額を書きません。伏せた数字は読者の側で裏が取れず、載せると「確かめられない数字」を増やすことになるからです。ここで扱うのは、数値そのものではなく、ズレの型と、そこから作った工程のほうです。
背景:AI検索リサーチ由来の数値には、何が混ざるのか
AI検索リサーチ由来の数値には、もっともらしい古い/誤ったデータが混入します。
なので、確認する対象を絞る必要があります。
この記事は「価格のような外部の数値」を、その絞り先として扱った記録です。
見つかった食い違いは3つ
公開済みの記事を照合したところ、料金まわりで3つの食い違いが出ました。型で並べるとこうなります。
- 更新料:記事の記載より、公式ページの金額のほうが高かった
- ドメイン料金:記事の記載より、公式ページの金額のほうが安かった
- 率で示す調整費:記事の公開直後に改定されていた
加えて、外部のレビューサイトから引いていたスコアも載せていたのですが、こちらで検証できる形になっていなかったので全部削除しました。
数字は、確かめられないなら載せないほうがいい、という判断です。
3つ目の調整費のズレは、性質が少し違います。
書いた時点では合っていた可能性があるからです。
公開したあとに、参照先のほうが動いていました。
いつ起こるか
一般化するとこうです。
外部の公式ページが更新されうる数値を、AIの検索リサーチ経由で取り込み、公開までに公式ページと突き合わせないときに起こります。
他に起こりえる場面
同じ原理で起こるのは、たとえばこういう数値です。
- 更新料やドメイン料金のような、公式ページ側が改定する料金。今回ずれた2件がこれでした
- 調整費のような「率」。公開後に改定されると、書いた時点では正しかったのに間違いになります
- 外部のレビューサイトから引いたスコア。こちらで検証できる形になっていないと、正しいかどうかを確かめる手段がありません
困りポイント
何が厄介かを並べると、こうなります。
- ゼロから作られた嘘ではない。もっともらしい古い/誤ったデータとして混ざるため、公式ページとの照合が必要
- 情報源が動く。書いた時点で正しくても、公開後に改定されることがある(調整費がまさにこれでした)
- 1つのミスが結論を裏返す。「最安」は並び順ひとつで真逆になる
- 直しが1箇所で終わらない。次に書くとおり、記事の骨格まで連鎖します
数値は本文の一部ではなく、記事の骨格
更新料の数字を直すと、そのサービスの順位が変わります。
順位が変わると、10年使ったときのランキングが変わります。
実際、記事で上位に置いていたサービスは、並べ直すと最も高い側へ移りました。
そして、リード文の結論も修正しました。
さらに記事の後半には「こういう人にはこれがおすすめ」という状況別のセクションがあって、そこも前提が変わるので直しになります。
つまり、直した箇所はこうなりました。
- 料金表の数値そのもの
- 10年ランキングの順位
- リード文の結論
- 状況別おすすめ
数値の修正が3件でも、記事の主張が乗っている場所は全部書き換えです。
「国内最安」と断言していたサービスが、実は最も高い側だったと知った時は、血の気が引きました。
ここで学んだのは、価格系の記事では数値は本文の一部ではなく、記事の骨格だということです。
骨格を後から差し替えると、上に載っているものが全部ずれます。
だから公開前に固めるしかない。
公開前に足した工程(手順)
作ったのは機能ではなく、記事の工程です。
「気をつける」だと次も同じことをやるので、入力と確認条件のある手順に落としました。順番に通します。
1. 数値の抽出
- 入力:公開前の原稿
- 確認条件:外部由来の数値が1つ残らず一覧になっている(金額・率・順位・スコア・件数)。自分で数えた数と、外部から持ってきた数を混ぜない
2. 公式ページの確認
- 入力:手順1の一覧
- 確認条件:各数値に、その数値の発行元=公式ページのURLが1つ対応している。まとめサイトや解説記事しか出てこない数値は、ここで「検証できない」に分類する
3. 確認日の記録
- 入力:数値とURL
- 確認条件:項目/公式URL/確認日/旧値→新値の4要素が埋まっている。ズレがなかったものも「差分なし」で残す。記録が無いと、あとで「見たつもり」と区別がつかない
4. 波及先の検索
- 入力:手順3でズレが出た数値
- 確認条件:その数値が出てくる箇所を全部拾って直してある。検索は2通りかける。①数字そのもの(表記ゆれ込み)②数字が根拠になっている言い回し(「最安」「1位」「おすすめ」など、本文・順位・リード文の結論・CTA)。②を飛ばすと、表だけ正しくて結論が古いままの記事ができます
5. 検証できない数値の削除
- 入力:手順2で「検証できない」に分類したもの
- 確認条件:原稿に残っていない。残したいなら手順2に戻って一次情報を探す
6. 公開判定
- 入力:手順3の記録
- 確認条件:原稿の外部数値の件数と、記録の件数が一致している。かつ確認日が公開日から離れすぎていない。合わなければ公開しない
照合記録を構造化する
手順6を目視でやると、件数の突き合わせが一番先に飛びます。記録を構造化しておくと、そこだけ機械に判定させられます。
記録はこの形です(4要素+検証可否)。
[
{
"item": "更新料",
"source_url": "https://example.com/pricing",
"checked_on": "2026-08-26",
"before": "記事に書いていた値",
"after": "公式ページの値"
}
]
判定はこれだけで足ります。
import json
from datetime import date
REQUIRED = ("item", "source_url", "checked_on", "before", "after")
def validate(path: str, numbers_in_draft: int, published_on: date) -> list[str]:
"""照合記録を読み、公開してよい状態かを判定する。返り値が空なら公開OK。"""
records = json.load(open(path, encoding="utf-8"))
errors: list[str] = []
# 4要素の欠けを見る。空文字も「未記入」として弾く(None だけ見ると素通りするため)
for i, r in enumerate(records):
for key in REQUIRED:
if not r.get(key):
errors.append(f"{i}件目: {key} が未記入")
# URLが書かれているかだけを見る
# ⚠️ これは「二次情報を弾く」検査ではない。https:// で始まれば通るので、
# まとめサイトや個人ブログも素通りする。一次情報かどうかを機械で判定したいなら、
# 案件ごとに公式ドメインの一覧を持って照合する必要がある(ここでは持っていない)
for r in records:
if not str(r.get("source_url", "")).startswith("https://"):
errors.append(f"{r.get('item')}: source_url が https:// で始まっていない")
# 手順6の本体。原稿に出てくる外部数値の件数と、記録の件数を突き合わせる
if len(records) != numbers_in_draft:
errors.append(f"件数不一致: 記録{len(records)}件 / 原稿{numbers_in_draft}件")
# 確認日が古い記録は「確認済み」に数えない
# ⚠️ 日付が読めないときに例外で落とさない。判定器が落ちると「エラー0件」と区別がつかなくなる
for r in records:
try:
checked_on = date.fromisoformat(str(r.get("checked_on", "")))
except ValueError:
errors.append(f"{r.get('item')}: 確認日が読めない({r.get('checked_on')!r})")
continue
if (published_on - checked_on).days > 7:
errors.append(f"{r['item']}: 確認日が古い({r['checked_on']})")
return errors
numbers_in_draft を人が数える以上、完全な自動化ではありません。それでも「記録し忘れた1件」は、この時点で止まります。
出典・確認先
この記事には、公式ページで裏取りが必要な外部数値を載せていません。金額・率・サービス名を伏せ、ズレの型と工程だけを書いているためです。
数値を載せる記事では、この位置に手順3の4要素をそのまま並べます。
## 出典・確認先
- 項目:〈数値の名前〉
- 公式URL:〈発行元の公式ページのURL〉
- 確認日:〈YYYY-MM-DD〉
- 旧値→新値:〈記事に書いていた値〉→〈公式ページの値〉
参照先はあとから改定されるので、数字だけでは足りません。どこを見て、いつ確認したのかまでを1組で残します。
最後に握っておくのは「本当にこの数字?」
AI検索リサーチ由来の数値を扱う運用では、警戒する先は「嘘をつかれること」より「古いまま混ざること」でした。
そして混ざった数字は、単体では小さく見えても、結論のほうを裏返してきます。
便利さのために自動化するほど、最後の「本当にこの数字?」を人間が握っておく価値が上がる。
今回はそれを、公開したあとに教わった形になりました。
個人でAIツールや業務自動化を作っているMiyokiといいます。
今回のような記事づくりの工程も含めて、自分の作業を楽にするための小さな仕組みを作っては、その開発ログをZennとQiitaに書いています。
こういう「確認の工程ごと仕組みにする」相談も受けています。
作ったものやポートフォリオはこちらです。