2026.09.18(金) / 10:09

AIと共同制作したJavaScriptをConsoleに打ち込んで192件のコンテンツ削除を自動化した

最終更新
2026.09.19
タグ
,

Gemini Notebookの上限が来てしまったので、コンテンツを削除したい。

ノートブック数が上限に達しました。 アップグレードしてください。

しかし、問題がある。

手作業が非効率

194個のノートブックがある。

ブラウザ操作をJSで自動化できるか?

できた。

ソースコード

以下をConsoleに打ち込んだ。(うまくいかない時があった。修正版はこちら

(async () => {
  const doc = $0?.ownerDocument ?? document;

  const sleep = ms =>
    new Promise(resolve => setTimeout(resolve, ms));

  const isVisible = element =>
    element && element.getClientRects().length > 0;

  const waitFor = async (callback, timeout = 5000) => {
    const startedAt = Date.now();

    while (Date.now() - startedAt < timeout) {
      const result = callback();

      if (result) {
        return result;
      }

      await sleep(100);
    }

    return null;
  };

  const getRows = () =>
    [...document.querySelectorAll(
      'tbody.mdc-data-table__content > tr.mat-mdc-row'
    )];

  const initialCount = getRows().length;

  if (
    !confirm(
      `${initialCount}件のNotebookをすべて完全に削除しますか?`
    )
  ) {
    console.log('削除を中止しました');
    return;
  }

  let deletedCount = 0;

  while (getRows().length > 0) {
    const row = getRows()[0];

    const title =
      row.querySelector('a.project-table-title')
        ?.textContent.trim() ?? 'タイトル不明';

    console.log(`処理中: ${title}`);

    // 1. 三点メニューを開く
    const menuButton = row.querySelector(
      'button[aria-label="プロジェクトの操作メニュー"]'
    );

    if (!menuButton) {
      console.error('三点メニューが見つかりません:', title);
      break;
    }

    menuButton.click();

    // 2. メニューの表示を待つ
    const menu = await waitFor(() =>
      [...document.querySelectorAll(
        '[role="menu"], .mat-mdc-menu-content'
      )].find(isVisible)
    );

    if (!menu) {
      console.error('操作メニューが表示されません:', title);
      break;
    }

    // 3. メニュー内の削除ボタンを探す
    const deleteMenuButton = [
      ...menu.querySelectorAll(
        'button, [role="menuitem"]'
      )
    ].find(element =>
      isVisible(element) &&
      element.innerText.includes('削除')
    );

    if (!deleteMenuButton) {
      console.error(
        'メニューの「削除」が見つかりません:',
        title,
        menu.innerText
      );
      break;
    }

    deleteMenuButton.click();

    // 4. 最終確認ダイアログを待つ
    const confirmDialog = await waitFor(() => {
      const dialog = doc.querySelector(
        'confirm-dialog .dialog-container[role="dialog"]'
      );

      return isVisible(dialog) ? dialog : null;
    }, 10000);

    if (!confirmDialog) {
      console.error(
        '最終確認ダイアログが表示されません:',
        title
      );
      break;
    }

    // 5. 最終確認の削除ボタンが表示されるまで待つ
    const finalDeleteButton = await waitFor(() => {
      const buttons = [
        ...confirmDialog.querySelectorAll('button')
      ];

      return (
        buttons.find(button =>
          isVisible(button) &&
          !button.disabled &&
          button.textContent.trim() === '削除'
        ) ?? null
      );
    }, 10000);

    if (!finalDeleteButton) {
      console.error(
        '最終確認の削除ボタンが見つかりません:',
        title,
        [...confirmDialog.querySelectorAll('button')]
          .map(button => button.textContent.trim())
      );
      break;
    }

    finalDeleteButton.click();

    // 6. 対象行が一覧から消えるまで待つ
    const removed = await waitFor(
      () => (!document.contains(row) ? true : null),
      10000
    );

    if (!removed) {
      console.error(
        '削除後もNotebookが一覧に残っています:',
        title
      );
      break;
    }

    deletedCount++;

    console.log(
      `${deletedCount}/${initialCount}件削除完了: ${title}`
    );

    await sleep(500);
  }

  console.log(
    `処理終了:${deletedCount}/${initialCount}件を削除しました`
  );
})();

AI駆動開発

AIとやりとりをしながら目的のツールを作成した。

一つ一つの3点リーダークリック→削除をConsoleに入力するJSで自動化できますか?

要素のDOMを渡します。先ほどのコードで修正点があれば修正してください

エラーが出ました

最終確認が出ますので、これもソースに反映させてください

まだ最終確認ボタンが表示されます

何も起こりません

削除ボタンが見つかりません

ここから先をどうすればいいですか?

削除できました