2026年5月21日
2026年5月21日
WordPressのデータベース内のスパムを一括削除する方法
はじめに
放置されたスパムコメントはデータベースを肥大化させ、サイトのパフォーマンスを低下させます。数万件のスパムが蓄積している場合もあり、定期的な一括削除とAkismetなどの自動スパム対策を組み合わせることが重要です。
症状・原因
- スパムコメントが数千〜数万件蓄積している
- 管理画面の「コメント」ページの読み込みが遅い
wp_commentsテーブルが数百MBになっている- スパムユーザーが大量登録されている
解決手順
ステップ1:スパムの量を把握する
# スパムコメント数を確認
wp comment list --status=spam --format=count
# ゴミ箱のコメント数を確認
wp comment list --status=trash --format=count
# コメントステータス別の件数
wp db query "SELECT comment_approved, COUNT(*) AS count
FROM wp_comments
GROUP BY comment_approved
ORDER BY count DESC;"
# スパムコメントのサイズ確認
wp db query "SELECT
comment_approved,
COUNT(*) AS count,
ROUND(SUM(LENGTH(comment_content))/1024/1024, 2) AS size_MB
FROM wp_comments
GROUP BY comment_approved;"
ステップ2:WP-CLI でスパムを一括削除する
# ① スパムコメントを一括削除
wp comment delete $(wp comment list --status=spam \
--field=comment_ID --format=ids) --force
# 件数が多い場合は分割して削除(1000件ずつ)
wp comment list --status=spam --field=comment_ID \
--format=ids --number=1000 | xargs wp comment delete --force
# ② ゴミ箱のコメントを削除
wp comment delete $(wp comment list --status=trash \
--field=comment_ID --format=ids) --force
# ③ 未承認コメントを削除(オプション)
wp comment delete $(wp comment list --status=hold \
--field=comment_ID --format=ids) --force
# ④ 古いスパムを自動削除(30日以上前)
wp eval '
$args = ["status" => "spam", "date_query" => [["before" => "30 days ago"]]];
$comments = get_comments($args);
foreach ($comments as $c) wp_delete_comment($c->comment_ID, true);
echo count($comments) . " spam comments deleted.\n";
'
ステップ3:SQL で直接大量削除する
-- バックアップ取得後に実行すること
-- ① スパムコメントを全削除
DELETE FROM wp_comments WHERE comment_approved = 'spam';
-- ② 関連する commentmeta も削除(孤立レコード)
DELETE FROM wp_commentmeta
WHERE comment_id NOT IN (SELECT comment_ID FROM wp_comments);
-- ③ ゴミ箱のコメントを削除
DELETE FROM wp_comments WHERE comment_approved = 'trash';
-- ④ 1年以上前の未承認コメントを削除
DELETE FROM wp_comments
WHERE comment_approved = '0'
AND comment_date < DATE_SUB(NOW(), INTERVAL 1 YEAR);
-- ⑤ スパムユーザーを削除(メール確認なし・投稿0件のユーザー)
DELETE FROM wp_users WHERE ID IN (
SELECT u.ID FROM wp_users u
LEFT JOIN wp_posts p ON p.post_author = u.ID AND p.post_status = 'publish'
WHERE p.ID IS NULL
AND u.user_registered < DATE_SUB(NOW(), INTERVAL 30 DAY)
AND u.user_email LIKE '%spam%'
);
ステップ4:スパムユーザーを一括削除する
# スパムユーザーの確認
wp user list --role=subscriber --format=count
# 投稿がないサブスクライバーを確認
wp user list --role=subscriber \
--fields=ID,user_login,user_email,user_registered | head -20
# 特定条件のユーザーを削除(投稿0件・登録30日以上前)
wp user list --role=subscriber \
--field=ID --format=ids | while read user_id; do
post_count=$(wp post list --author=$user_id --format=count 2>/dev/null)
if [ "$post_count" -eq "0" ]; then
wp user delete $user_id --yes --reassign=1
echo "Deleted user: $user_id"
fi
done
# Akismet が記録したスパムメタデータを削除
wp db query "DELETE FROM wp_commentmeta
WHERE meta_key IN ('akismet_result', 'akismet_history',
'akismet_as_submitted', 'akismet_user')
AND comment_id IN
(SELECT comment_ID FROM wp_comments WHERE comment_approved = 'spam');"
ステップ5:スパムの自動定期削除を設定する
// functions.php: スパムコメントを定期的に自動削除
add_action('daily_spam_cleanup', 'auto_delete_spam');
function auto_delete_spam(): void {
// 30日以上前のスパムを削除
$comments = get_comments([
'status' => 'spam',
'date_query' => [['before' => '30 days ago']],
'number' => 500, // 1回あたり最大500件
]);
$deleted = 0;
foreach ($comments as $comment) {
if (wp_delete_comment($comment->comment_ID, true)) {
$deleted++;
}
}
// ゴミ箱のコメントも削除
$trash = get_comments([
'status' => 'trash',
'date_query' => [['before' => '7 days ago']],
'number' => 500,
]);
foreach ($trash as $comment) {
wp_delete_comment($comment->comment_ID, true);
}
if ($deleted > 0) {
error_log("[Spam Cleanup] Deleted $deleted spam comments");
}
}
if (!wp_next_scheduled('daily_spam_cleanup')) {
wp_schedule_event(strtotime('tomorrow 03:00:00'), 'daily', 'daily_spam_cleanup');
}
注意事項
- スパムコメントを削除する前に、誤判定がないか少量サンプルを確認してください。Akismetが正常なコメントをスパム判定することがあります
wp_usersテーブルのユーザー削除は慎重に行ってください。投稿者として紐付いた投稿がある場合、--reassignオプションで別ユーザーに再割り当てしないと投稿者情報が失われます- 大量削除後は
OPTIMIZE TABLE wp_commentsを実行してテーブルのオーバーヘッドを解消することを推奨します
まとめ
DB内スパム削除は①wp comment list --status=spam --format=countとinformation_schemaで件数・サイズを把握、②wp comment delete $(wp comment list --status=spam --field=comment_ID --format=ids) --forceで一括削除、③DELETE FROM wp_comments WHERE comment_approved='spam'と孤立commentmetaの削除をSQL直接実行、④投稿0件のサブスクライバーユーザーをwp user deleteで整理、⑤wp_schedule_eventで30日超スパムの毎日自動削除とOPTIMIZE TABLEでテーブル最適化を実施します。