2026年7月9日
2026年7月9日
WordPressのコメントスパムを解決する方法
はじめに
WordPressのコメント欄に毎日大量のスパムコメントが届く・Akismetプラグインを有効にしているのにスパムが通過してしまう・コメントフォームがボットに自動送信されていてサーバー負荷が高い・スパムコメントが数万件溜まってデータベースが重くなっているといった問題は、Akismetの設定不備・コメントフォームへのハニーポット未設置・comment_flood_filterの無効化・Cookieチェックの欠落が原因です。
症状・原因
- Akismetが設定されていないかAPIキーが失効している
- コメントフォームにCAPTCHAやハニーポットが設定されていない
XMLRPC経由でスパムコメントが投稿されている- コメント投稿にログイン不要・URL必須チェックなし
解決手順
ステップ1:スパム状況を診断する
# スパムコメントの件数を確認
wp comment list --status=spam --format=count
wp comment list --status=hold --format=count
wp comment list --status=approve --format=count
# スパムコメントのIPアドレス上位を確認
wp eval "
global \$wpdb;
\$ips = \$wpdb->get_results(
\"SELECT comment_author_IP, COUNT(*) as cnt
FROM {\$wpdb->comments}
WHERE comment_approved = 'spam'
GROUP BY comment_author_IP
ORDER BY cnt DESC
LIMIT 10\"
);
foreach (\$ips as \$row) {
echo \$row->comment_author_IP . ': ' . \$row->cnt . ' spam comments' . PHP_EOL;
}
"
# Akismetの設定状態を確認
wp eval "
echo 'Akismet active: ' . (is_plugin_active('akismet/akismet.php') ? 'yes' : 'no') . PHP_EOL;
echo 'Akismet API key: ' . (get_option('wordpress_api_key') ? 'set' : 'NOT SET') . PHP_EOL;
echo 'Comment status: ' . get_option('default_comment_status') . PHP_EOL;
echo 'Comment moderation: '. get_option('comment_moderation') . PHP_EOL;
echo 'Comment whitelist: ' . get_option('comment_whitelist') . PHP_EOL;
"
ステップ2:スパムコメントをクリーンアップする
# 全スパムコメントを削除
wp comment delete $(wp comment list --status=spam --format=ids) --force
# または一括削除(大量の場合)
wp eval "
global \$wpdb;
\$deleted = \$wpdb->query(
\"DELETE FROM {\$wpdb->comments} WHERE comment_approved = 'spam'\"
);
// 孤立したコメントメタも削除
\$wpdb->query(
\"DELETE pm FROM {\$wpdb->commentmeta} pm
LEFT JOIN {\$wpdb->comments} c ON c.comment_ID = pm.comment_id
WHERE c.comment_ID IS NULL\"
);
echo 'Deleted spam comments: ' . \$deleted . PHP_EOL;
"
# データベースを最適化
wp db optimize
# 古いスパムコメントを定期削除するスケジュールを設定
wp eval "
if (!wp_next_scheduled('cleanup_spam_comments')) {
wp_schedule_event(time(), 'daily', 'cleanup_spam_comments');
echo 'Daily spam cleanup scheduled' . PHP_EOL;
}
"
ステップ3:コメントフォームにスパム対策を追加する
// functions.php: ハニーポットフィールドを追加(ボット対策)
add_action('comment_form_after_fields', function(): void {
?>
<p style="display:none !important" aria-hidden="true">
<label for="website2">ウェブサイト(入力しないでください)</label>
<input type="text" name="website2" id="website2" tabindex="-1" autocomplete="off">
</p>
<?php
});
// ハニーポットフィールドに値がある場合はスパムとして拒否
add_filter('preprocess_comment', function(array $commentdata): array {
if (!empty($_POST['website2'])) {
wp_die('コメントを投稿できませんでした。', 'スパム検出', ['response' => 403]);
}
return $commentdata;
});
// コメント投稿時間チェック(5秒以内は自動送信とみなす)
add_action('comment_form', function(): void {
echo '<input type="hidden" name="comment_timestamp" value="' . time() . '">';
});
add_filter('preprocess_comment', function(array $commentdata): array {
$timestamp = (int) ($_POST['comment_timestamp'] ?? 0);
if ($timestamp > 0 && (time() - $timestamp) < 5) {
wp_die('コメントを送信するには5秒以上かかります。', 'スパム検出', ['response' => 403]);
}
return $commentdata;
});
ステップ4:コメント設定でスパムを制限する
// functions.php: コメントのスパム対策設定
// ① リンクが多いコメントをスパムとして保留
add_action('init', function(): void {
// 2個以上のリンクを含むコメントをモデレーション待ちに
update_option('comment_max_links', 2);
// スパムに使われやすいキーワードをブラックリストに追加
$blacklist = get_option('blacklist_keys', '');
$spam_keywords = ['casino', 'viagra', 'poker', 'loan', 'insurance'];
foreach ($spam_keywords as $kw) {
if (!str_contains($blacklist, $kw)) {
$blacklist .= "\n" . $kw;
}
}
update_option('blacklist_keys', trim($blacklist));
});
// ② 未ログインユーザーのコメントを制限
add_filter('comment_flood_filter', function(bool $block, int $time_lastcomment, int $time_newcomment): bool {
// 前回コメントから30秒以内の投稿をブロック
if (($time_newcomment - $time_lastcomment) < 30) {
return true;
}
return $block;
}, 10, 3);
// ③ 特定のURLパターンを含むコメントを拒否
add_filter('preprocess_comment', function(array $commentdata): array {
$content = $commentdata['comment_content'];
$patterns = [
'/\[url=/i', // BBCode風URL
'/href=["\']http/i', // HTMLリンク
'/<a\s+href/i', // HTMLアンカー
];
foreach ($patterns as $pattern) {
if (preg_match($pattern, $content) && !is_user_logged_in()) {
wp_die('このコメントは投稿できません。', 'スパム検出', ['response' => 403]);
}
}
return $commentdata;
});
ステップ5:IPブロックと長期的なスパム対策を設定する
# スパム送信元IPをWordPressのブラックリストに追加
wp eval "
\$spam_ips = ['192.0.2.1', '198.51.100.5']; // スパム送信元IP
\$current = get_option('blacklist_keys', '');
foreach (\$spam_ips as \$ip) {
if (!str_contains(\$current, \$ip)) {
\$current .= \"\\n\" . \$ip;
}
}
update_option('blacklist_keys', trim(\$current));
echo 'IPs added to blacklist' . PHP_EOL;
"
# 定期的なスパム削除スケジュールを設定
wp eval "
add_action('cleanup_spam_comments', function(): void {
global \$wpdb;
// 30日以上前のスパムコメントを削除
\$wpdb->query(
\"DELETE FROM {\$wpdb->comments}
WHERE comment_approved = 'spam'
AND comment_date < DATE_SUB(NOW(), INTERVAL 30 DAY)\"
);
});
"
// wp-config.php または functions.php: コメント機能を完全に無効化(不要な場合)
// add_action('init', function(): void {
// // 全投稿タイプでコメントを無効化
// foreach (get_post_types() as $post_type) {
// if (post_type_supports($post_type, 'comments')) {
// remove_post_type_support($post_type, 'comments');
// remove_post_type_support($post_type, 'trackbacks');
// }
// }
// // コメントフィードを無効化
// add_filter('feed_links_show_comments_feed', '__return_false');
// });
// functions.php: reCAPTCHA v3をコメントフォームに追加
add_action('wp_enqueue_scripts', function(): void {
if (is_singular() && comments_open()) {
wp_enqueue_script(
'recaptcha',
'https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY',
[],
null,
true
);
}
});
注意事項
- Akismetは商用サイトでは有料プランが必要です。無料の代替として
Antispam Beeプラグインも有効です - コメントを完全に無効化する前に、既存の承認済みコメントをエクスポートしてバックアップしてください。設定変更後は既存コメントも表示されなくなります
.htaccessでXML-RPC経由のコメント投稿をブロックすると、正規のXML-RPC利用(Jetpack等)にも影響するため注意してください
まとめ
WordPressコメントスパムの解決は①wp comment list --status=spam --format=countでスパム件数確認・スパムIPアドレス上位をDBクエリで取得・Akismet APIキーの設定状態確認、②wp comment deleteで全スパムを削除・wp db optimizeでDB最適化・wp_schedule_eventで定期クリーンアップを設定、③ハニーポットフィールドをコメントフォームに追加・コメント投稿時間チェックで5秒以内の自動送信をブロック・preprocess_commentフィルターで拒否、④comment_max_linksでリンク数制限・blacklist_keysにスパムキーワード追加・comment_flood_filterで連続投稿を30秒制限、⑤スパムIPをblacklist_keysに追加・30日以上前のスパムを定期削除・reCAPTCHA v3をコメントフォームに追加の手順で解決します。