はじめに

こんにちは。あやかです。

Google Workspaceを契約したので、個人のGmailアカウントからワークスペースアカウントへ写真のアップロード先を変更することにしました。 新しいアカウントへの移行が完了したら、Google Oneを解約したかったので、旧アカウントの写真を全削除する必要がありました。

問題は、その枚数。写真とビデオを合わせて1.7万枚弱ありました。

手動削除は現実的じゃない

Googleフォトを開いて、削除しようと思ったんですが、写真一つ一つにチェックボックスがあって、これを手でポチポチ選択していくのは明らかに無理。

日付ごとの「すべて選択」もあるにはあるんですが、1.7万枚ともなると、それでも相当な手間です。

というわけで、スクリプトで自動化することにしました。

解決策:JavaScriptで自動化

今回使ったのは、ブラウザの開発者ツールで直接JavaScriptを実行する方法です。 SeleniumやPuppeteerのような外部ツールは使わず、シンプルにブラウザ上で完結させました。

動作環境

今回確認した環境は以下の通りです。

  • OS: macOS 26.2
  • ブラウザ: Google Chrome 143.0.7499.193(arm64)
  • 実行日: 2026年1月

Googleフォトの仕様が変更された場合、このスクリプトが動かなくなる可能性がありますので、あくまで参考としてご覧ください。

スクリプト全文

以下が実際に使用したスクリプトです。

async function selectAllMediaWithScroll(targetCount = 2000) {
    console.log(`${targetCount}個のメディアを選択します(スクロールしながら)...`);
    
    let selectedCount = 0;
    let noNewItemsCount = 0;
    const maxNoNewItemsAttempts = 3;
    
    while (selectedCount < targetCount && noNewItemsCount < maxNoNewItemsAttempts) {
        // 未選択のチェックボックスを取得
        const allCheckboxes = Array.from(document.querySelectorAll('[role="checkbox"][aria-checked="false"]'));
        
        // 日付グループを除外
        const mediaCheckboxes = allCheckboxes.filter(cb => {
            const label = cb.getAttribute('aria-label');
            return label && !label.includes('すべて選択');
        });
        
        if (mediaCheckboxes.length === 0) {
            console.log('これ以上選択可能なメディアが見つかりません');
            break;
        }
        
        // 今回選択する数を決定
        const remainingCount = targetCount - selectedCount;
        const batchSize = Math.min(100, remainingCount, mediaCheckboxes.length);
        
        console.log(`選択中... ${selectedCount}/${targetCount} (今回: ${batchSize}個)`);
        
        // バッチで選択
        let batchSelected = 0;
        for (let i = 0; i < batchSize; i++) {
            if (mediaCheckboxes[i].getAttribute('aria-checked') === 'false') {
                mediaCheckboxes[i].click();
                batchSelected++;
                await new Promise(r => setTimeout(r, 30));
            }
        }
        
        selectedCount += batchSelected;
        
        // 新しいアイテムが選択できなかった場合
        if (batchSelected === 0) {
            noNewItemsCount++;
        } else {
            noNewItemsCount = 0;
        }
        
        // まだ目標に達していない場合はスクロール
        if (selectedCount < targetCount) {
            // 最後に選択した要素までスクロール
            if (mediaCheckboxes[batchSize - 1]) {
                mediaCheckboxes[batchSize - 1].scrollIntoView({ 
                    behavior: 'smooth', 
                    block: 'center' 
                });
                await new Promise(r => setTimeout(r, 1500)); // 読み込み待ち
            }
            
            // さらに下にスクロールして新しいアイテムを読み込む
            window.scrollBy(0, 500);
            await new Promise(r => setTimeout(r, 1000));
        }
    }
    
    // 最終確認
    await new Promise(r => setTimeout(r, 500));
    const finalCount = document.querySelectorAll('[role="checkbox"][aria-checked="true"]').length;
    
    console.log(`✓ 完了!${finalCount}個を選択しました`);
    console.log('「ゴミ箱に移動」ボタンを手動でクリックしてください');
}

// 実行
selectAllMediaWithScroll();

スクリプトの主要なポイント

バッチ処理の理由

100個ずつ選択しているのは、画面上にロードされている分しか操作できないからです。 最初は1000個にしようかとも思ったんですが、結局スクロール操作が必要になるので、100個くらいが扱いやすいと判断しました。

待ち時間の調整

クリック間隔を30ms、スクロール後を1000-1500msに設定しています。 これは感覚で決めた値で、環境によってはもっと短くできるかもしれません。

ただ、スクロール後の待ち時間は、新しい画像がロードされるのを待つ必要があるので、ある程度の余裕を持たせた方が安全です。

「すべて選択」の除外

日付ごとの「すべて選択」チェックボックスも取得されてしまうと、選択済みの写真を再度クリックしてチェックを外してしまうという問題がありました。

効率化を追求するなら、日付ごとの選択も活用できるとよかったんですが、1回しか使わないスクリプトなので、シンプルに除外することにしました。

targetCountの試行錯誤

最初は500個に設定していたんですが、削除操作が頻繁に必要になって面倒でした。 1000個に増やしてもまだ余裕がありそうだったので、最終的に2000個に落ち着きました。

2000個というのは、削除処理がギリギリ完了できるラインだと思います。 これより多くすると、Google側の削除処理が追いつかなくなる可能性があります。

実行方法

  1. Googleフォトを開く
  2. 開発者ツールを開く
  3. コンソールタブにスクリプトを貼り付けて実行
  4. スクリプトが完了したら、「ゴミ箱に移動」ボタンを手動でクリック
  5. 削除が完了するまで待つ
  6. 残りの写真があれば、手順3から繰り返す

削除ボタンのクリックも自動化できなくはないんですが、スクリプトが複雑になるのと、誤操作のリスクを考えて手動のままにしました。

実行結果

1.7万枚の削除に、スクリプトを10回実行しました。 2000個ずつ選択する設定にしていても、実際には2000個きっちり選択されないこともあったので、回数が増えました。

スクリプトの作成から全削除完了まで、トータルで約1時間かかりました。 手動でやっていたら、おそらく丸一日かかっていたと思うので、十分に時短できたと思います。

注意事項

バックアップは必須

削除は不可逆的な操作です。 今回の場合、新しいアカウントへの移行が完了していることを確認してから実行しました。

必ずバックアップを取ってから実行してください。

スクリプト実行は自己責任で

このスクリプトは私の環境で動作したものですが、すべての環境での動作を保証するものではありません。 実行する際は、自己責任でお願いします。

特に、Googleフォトの仕様が変更された場合、動作しなくなる可能性があります。

ブラウザやネットワーク環境による影響

ブラウザの性能やネットワーク速度によっては、待ち時間を調整する必要があるかもしれません。 最初は少ない枚数で試して、動作を確認してから本番実行することをおすすめします。

おわりに

Googleフォトの大量削除という、地味に面倒な作業をスクリプトで自動化した話でした。

こういう「1回しか使わないかもしれないけど、手動でやるには多すぎる」という作業は、意外とスクリプトで解決できることが多いです。

同じような状況に直面している方の参考になれば嬉しいです。

もちろん、数百枚程度なら手動でやった方が早いこともあるので、状況に応じて判断してくださいね。