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=countinformation_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でテーブル最適化を実施します。

お気軽にご相談ください

お見積りへ お問い合わせへ