memorandums

日々の作業ログです。

はてなブックマークに登録したブックマークを全削除するスクリプト

発端

転職を機にSNSくらいは少しかじっておいた方がいいな。。。と思いまして、15年くらい前にはてなダイヤリーを利用しはじめました。

その後、共有ブックマークサービスが脚光を浴びた時期くらいからはてなブックマークを利用するようになりました。

最近は、Webページの保存はPocketを利用しているのでブックマークする機会はほとんどなくなりました。

現在、はてなブログを利用させていただいているのですが、エントリーに対してコメントなどがつくとメールがくるんですね。

で、最近、なぜか利用していないはずのはてなブックマークがお気に入りされた。。。というメール通知がくるようになり、気持ち悪いなぁ。。。と思っていました。以下のようなメールです。。。毎日のように送られてきます。

f:id:ke_takahashi:20191102115920p:plain

調べたこと

意図も原因もよくわかりませんが、とにかく削除しないと。。。と思いまして、全削除のメニューを探すと。。。できないとか。日付をみると2年前。。。はてなさん、大丈夫でしょうか?

bookmark.hatenastaff.com

で、APIを叩けばいいんだろう。。。とは思いましたが、面倒なので誰か作ってないかな。。。と思いましたら2件見つかりまして。

はてなブックマーク全削除|kawax|pixivFANBOX

はてブ整理~はてなブックマーク一括整理

やってみたんですが。。。なぜか500番がでまして。。。進行しません。

現時点で5000件くらいのブックマークが登録されていたので、これを手で削除してたら。。。考えたくありませんね。

操作を記録して再生すればいいんじゃね。。。と思いまして、Seleniumでやろうとしたけど設定が面倒そう。。。もっと簡単なのがないかな。。。と探したら、以下の記事が見つかりました。

qiita.com

お、これは行けそう!GreaseMonkeyChrome版らしい。GreaseMonkeyは触ったことがあるのでなんとなく想像できます。

単純にはいきませんでしたが、あれこれ調べたり試したりしました。調べたことは以下です。あとで思い出すためにメモしておきます。

  • 削除ボタンのエレメントをどう取得するか調べました。はてブでは1ページあたり20件のブックマークが表示されるので1ページに複数のエレメントが存在します。querySelectAllを使えばいいってことらしい。いろいろと試行錯誤して「buttonタグ、かつ、centerarticle-reaction-deleteクラス」であればいいようで。
  • buttonエレメントが取得できたら、あとは、clickメソッドを呼べばいいわけですが、確認ダイアログがでます。削除操作なので確認するのは当然といえば当然。。。でも、このボタンも自動押下するのは面倒だな。。。と調べてみると、window.confirmをオーバーライドすればいいってわかりましたので、単純にtrueを返すようにしました。
  • とりあえず、上記の2点でページ内の削除ボタンを自動押下して削除できるようになったのですが、ページをリロードする必要があります。これも面倒。。。じゃ、自動リロードすればいいじゃん。。。ということで、これは懐かしいsetTimeout関数で対応しました。

で、どうすればいいの?

Chrome拡張機能Tampermonkeyをインストールします。

インストールが完了したら、自分のはてブのページを開いてからChromeの右上のTampermonkeyのアイコンをクリックして「新規スクリプトを追加」を選択します。すると以下のようなエディタ画面が表示されます。

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://b.hatena.ne.jp/ご自身のはてなID/bookmark
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Your code here...
})();

「// ==/UserScript==」より下のコードを削除して、以下のコードに置き換えます。★部分はご自身のはてなIDで置き換えてください。もしかすると。。。あとあと考えると「@match」があるのでこのif文はいらないような気もしますが。。。

(async() => {

    setTimeout("location.reload()",3000);

    window.confirm=function(){
        return true;
    };

    const href = location.href;
    // 引数の秒数分待つ
    const wait = ( /** @type {number} */ second) => new Promise((resolve) => setTimeout(() => resolve(), second * 1000))
    await wait(1)
    if (href.includes("https://b.hatena.ne.jp/★/bookmark")) {
        var buttonList = /** @type {HTMLButtonElement} */ (document.querySelectorAll("button.centerarticle-reaction-delete"));
       buttonList.forEach(function(button) {
          button.click();
          wait(0.3);
        });
    }
})();

ページのリロード間隔や、if文に入る前のページロード待ち用のwait(1)、ブックマークを削除したあとにサーバーの応答待ちのためのwait(0.3)などの数値はご自身のPCのスペックやネットワーク回線速度に応じて調整してください。処理落ちすると「削除できませんでした」というダイアログがでて面倒なことになりますので。。。

5000件を全削除するのに30分くらいかかったでしょうか。。。でも、こういう操作が自動化される様子をみるのはなかなか嬉しいもので。。。コンピュータパワーというかプログラミングパワーって感じですね。

Tips: Chromeで画像をロードする時間がもったいないのでChromeの設定画面で「すべての画像を表示しない」としておくと無駄な帯域を消費しなくていいかもしれません。

ちなみに削除している様子をキャプチャしてみました。

youtu.be

プログラミングを学んで、面倒なことはコンピュータにやらせて、がんばっている様子をコーヒーを飲みながら観察しましょう☺️

では!

追記

全ブックマークを削除したかと思いきや。。。 UIがおかしくなり。。。結局、4件残っている。。。気に入られているという情報も消えない。どうすればいいんでしょうね。。。

f:id:ke_takahashi:20191102124558p:plain