捏造セールをビルドで止める:静的サイトの「断定価格+出典必須」検証ゲートを正規表現で作る

セールやお得情報を扱うサイトで最悪なのは、実在しない割引を「半額」「50%OFF」と断定してしまうことだ。信頼を失ううえ、アフィリエイトの規約面でもリスクになる。人手のレビューだけでは、たまに裏取りの無い断定がすり抜ける。

自分が運用しているKindleマンガのセール速報サイト「マンガセール速報」(manga.autoarticles.net)では、この事故をビルド時の検証ゲートで機械的に防いでいる。方針はシンプルだ。

断定的な割引・価格表現を含む記事は、confirmed(確認日)と出典URL(source)の両方が揃っている場合だけ公開を許す。揃っていなければビルドを落とす。

どんな表現を「断定」とみなすか

「50%OFF」「半額」「◯◯円→◯◯円」「全巻99円」といった、特定商品の割引・価格を言い切る表現をまとめて正規表現で拾う。実際にサイトで使っている判定式がこれだ。

1
2
3
// 断定的な割引率・価格の言い切りを検知する
const assertive =
/(\d{1,3}\s*%\s*(OFF|オフ|還元(?!率))|半額|実質\s*無料|今だけ半額|→\s*\d+\s*円|\d+\s*円均一|全巻\s*\d+\s*円|各\s*\d+\s*円)/;

ポイントは 還元(?!率) の否定先読みだ。「還元」(=具体的なポイント還元の断定)は検知したいが、「還元率」という一般語の解説はゲート対象にしたくない。ここを区別しないと、仕組み解説の記事まで巻き込んで落ちてしまう。

検証ゲート本体

記事1件ずつをJSON文字列化して assertive にかけ、ヒットしたら confirmed と有効な出典URLの両方を要求する。どちらか欠ければ問題として積み、1件でもあればプロセスを異常終了させる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const fs = require("fs");

function validateArticles(articles) {
const assertive =
/(\d{1,3}\s*%\s*(OFF|オフ|還元(?!率))|半額|実質\s*無料|→\s*\d+\s*円|全巻\s*\d+\s*円|各\s*\d+\s*円)/;
const isUrl = (s) => typeof s === "string" && /^https?:\/\//.test(s);
const problems = [];

for (const a of articles) {
const blob = JSON.stringify(a);
const sources = [].concat(a.source || [], a.sourceUrl || []).filter(Boolean);
const hasSource = sources.some(isUrl);

if (assertive.test(blob) && (!a.confirmed || !hasSource)) {
problems.push(`[NG] ${a.slug}: 断定価格には confirmed と出典URL が必須`);
}
if (!a.confirmed && !a.date) {
problems.push(`[NG] ${a.slug}: 確認日(confirmed/date)が無い`);
}
if (sources.length && !hasSource) {
problems.push(`[NG] ${a.slug}: source が有効なURLでない`);
}
}

if (problems.length) {
console.error("セール実在検証に失敗:\n" + problems.join("\n"));
process.exit(1); // ビルドを落とす
}
}

const articles = JSON.parse(fs.readFileSync("data/articles.json", "utf8"));
validateArticles(articles);
console.log("OK: 全記事が検証を通過");

手元で試す

適当なJSONを作って落ちることを確認する。

1
2
3
4
5
6
7
8
9
10
11
mkdir -p data
cat > data/articles.json <<'JSON'
[
{"slug":"ng","title":"全巻50%OFF","source":[],"confirmed":null},
{"slug":"ok","title":"全巻50%OFF","confirmed":"2026-07-14",
"source":["https://example.com/sale"]}
]
JSON
node validate.js
# [NG] ng: 断定価格には confirmed と出典URL が必須
# → 終了コード 1(CIならここで赤くなる)

ng は出典も確認日も無いので落ち、ok は両方揃っているので通る。断定表現を消して「仕組みの一般解説」に書き換えても通る。つまりこのゲートは、言い切るなら裏を取れという編集方針をコードに落としたものだ。

効いているポイント

  • レビュー漏れがあっても、裏付けの無い断定は本番に出る前に止まる。
  • build.js の一部として走らせれば、デプロイ手順に自然に組み込まれる(別途CIを足す必要すらない)。
  • 正規表現は「事故りやすい表現」に絞る。広げすぎると解説記事まで落ちて運用が回らなくなるので、否定先読みで一般語を逃がすのが実務上のコツ。

同じ仕組みは、価格・在庫・締切など「言い切ると危うい」データを扱うどのサイトにも移植できる。実際の運用サンプルとして、このゲートを通した記事だけが並ぶマンガセール速報を眺めると、どの記事にも確認日と出典が付いているのが分かるはずだ。


捏造セールをビルドで止める:静的サイトの「断定価格+出典必須」検証ゲートを正規表現で作る
https://blog.hashito.biz/2026/07/14/fleet-content-integrity-build-gate-fabricated-sales/
著者
hashito
作成日
2026年7月14日
著作権