2026年5月20日
2026年5月20日
WordPressのコメントスパムを完全に防ぐ方法
はじめに
WordPressのコメントスパムはSEOに悪影響を与え、管理者の負担を増やし、サイトの信頼性を損ないます。Akismet・honeypot・レート制限を組み合わせることでスパムをほぼ完全に防止できます。
症状・原因
- 毎日大量のスパムコメントが届き、承認待ちが数百件になっている
- カジノ・薬・アダルト等のスパムリンクを含むコメントが自動投稿されている
- ボットがWordPressのコメントAPIを直接叩いてスパムを送信している
- Akismetを設定しているのにスパムが通過してしまっている
解決手順
ステップ1:現在のスパム状況を確認する
# スパムコメントの件数を確認
wp comment list --status=spam --format=count
# 直近のスパムコメントを確認
wp comment list --status=spam --fields=comment_author,comment_author_email,comment_author_url,comment_date --format=table | head -20
# スパムコメントを一括削除
wp comment delete $(wp comment list --status=spam --format=ids) --force
# データベースから直接削除(大量の場合)
wp eval "
global \$wpdb;
\$count = \$wpdb->query(\"DELETE FROM {\$wpdb->comments} WHERE comment_approved = 'spam'\");
echo \"Deleted spam comments: \" . \$count . PHP_EOL;
"
ステップ2:Akismet を正しく設定する
# Akismet をインストール・有効化
wp plugin install akismet --activate
# Akismet APIキーを設定(WordPress.com アカウントで取得)
wp option update akismet_strictness 1 # 厳格モード
# Akismet の設定をWP-CLIで確認
wp option get akismet_strictness
// functions.php: Akismet の設定を最適化
// ① 自動的にスパムを削除(承認待ちに入れない)
add_filter('akismet_spam_count', '__return_true');
// ② Akismet チェック後の処理をカスタマイズ
add_filter('pre_comment_approved', function(mixed $approved, array $comment_data): mixed {
// Akismet が spam と判定した場合
if ($approved === 'spam') {
// オプション: 即座に削除(デフォルトはスパムフォルダに保存)
// return 'trash'; // ゴミ箱へ
}
return $approved;
}, 10, 2);
// ③ APIキーなしでもスパムをある程度防ぐ
add_filter('pre_comment_approved', function(mixed $approved, array $comment_data): mixed {
// URLを多数含むコメントを自動的にスパム扱い
$url_count = substr_count($comment_data['comment_content'], 'http');
if ($url_count > 2) {
return 'spam';
}
return $approved;
}, 5, 2);
ステップ3:honeypot フィールドでボットをトラップする
// functions.php: honeypot(ハニーポット)でボットを検出
// ① honeypot フィールドをコメントフォームに追加
add_filter('comment_form_defaults', function(array $defaults): array {
$defaults['fields']['hp_website'] =
'<p class="comment-form-hp" style="display:none!important">'
. '<label for="hp_website">Website (leave blank)</label>'
. '<input type="text" name="hp_website" id="hp_website" value="" tabindex="-1" autocomplete="off">'
. '</p>';
return $defaults;
});
// ② honeypot フィールドが入力されていたらスパム扱い
add_filter('pre_comment_approved', function(mixed $approved, array $comment_data): mixed {
// ボットは非表示フィールドにも値を入れる
if (!empty($_POST['hp_website'])) {
return 'spam';
}
return $approved;
}, 1, 2);
// ③ タイムスタンプ検証(人間は最低数秒かかる)
add_action('comment_form', function(): void {
echo '<input type="hidden" name="comment_timestamp" value="' . time() . '">';
});
add_filter('pre_comment_approved', function(mixed $approved, array $comment_data): mixed {
$timestamp = (int) ($_POST['comment_timestamp'] ?? 0);
$elapsed = time() - $timestamp;
// 3秒未満での送信はボット
if ($timestamp > 0 && $elapsed < 3) {
return 'spam';
}
// 1時間以上経過したフォームも拒否
if ($timestamp > 0 && $elapsed > 3600) {
return 'spam';
}
return $approved;
}, 2, 2);
ステップ4:コメント投稿のレート制限と検証を強化する
// functions.php: コメント投稿を厳格に制御
// ① 同一IPからの連続投稿を制限
add_filter('pre_comment_approved', function(mixed $approved, array $comment_data): mixed {
$ip = $comment_data['comment_author_IP'];
$transient_key = 'comment_rate_' . md5($ip);
$count = (int) get_transient($transient_key);
if ($count >= 3) { // 30分間に3件まで
return 'spam';
}
set_transient($transient_key, $count + 1, 30 * MINUTE_IN_SECONDS);
return $approved;
}, 10, 2);
// ② 禁止キーワードを含むコメントをブロック
add_filter('pre_comment_approved', function(mixed $approved, array $comment_data): mixed {
$blocked_keywords = ['casino', 'viagra', 'buy cheap', 'click here', 'free money'];
$content = strtolower($comment_data['comment_content']);
foreach ($blocked_keywords as $keyword) {
if (str_contains($content, $keyword)) {
return 'spam';
}
}
return $approved;
}, 10, 2);
// ③ ログインユーザーのみコメントを許可
// → 設定 → ディスカッション → 「コメントの投稿者の登録とログインを必須にする」
add_action('init', function(): void {
if (!is_user_logged_in()) {
add_filter('comments_open', '__return_false');
}
});
ステップ5:コメントを完全に無効化する(必要な場合)
// functions.php: コメント機能を完全に無効化
// ① 新規コメントを完全にブロック
add_filter('comments_open', '__return_false');
add_filter('pings_open', '__return_false');
// ② 既存のコメント数を0として扱う
add_filter('get_comments_number', '__return_zero');
// ③ 管理画面のコメントメニューを非表示
add_action('admin_menu', function(): void {
remove_menu_page('edit-comments.php');
});
// ④ ダッシュボードのコメントウィジェットを削除
add_action('wp_dashboard_setup', function(): void {
remove_meta_box('dashboard_recent_comments', 'dashboard', 'normal');
});
// ⑤ wp-admin/comment*.php へのアクセスをリダイレクト
add_action('admin_init', function(): void {
global $pagenow;
if ($pagenow === 'edit-comments.php' || $pagenow === 'comment.php') {
wp_redirect(admin_url());
exit;
}
});
注意事項
- Akismetは商用サイトでは有料プランが必要です。無料の代替として「Antispam Bee」プラグインも有効です
- honeypotフィールドはCSS非表示のため、スクリーンリーダーでは見えてしまいます。
aria-hidden="true"とtabindex="-1"を設定して支援技術から隠すことを推奨します - コメントを完全無効化した後も、既存のコメントはデータベースに残ります。完全に削除する場合は
wp comment delete $(wp comment list --format=ids) --forceで全件削除してください
まとめ
コメントスパム対策は①wp comment list --status=spamで状況確認、②Akismetを設定してakismet_strictness=1で厳格モードに、③honeypotフィールド(非表示input)とタイムスタンプ検証でボットをトラップ、④IPベースのレート制限(30分3件まで)と禁止キーワードフィルター、⑤コメント不要ならcomments_open/__return_falseで完全無効化します。