読者です 読者をやめる 読者になる 読者になる

DOM をストーカーする

dom mutationobserver tumblr

新年あけましておめでとうございます。

唐突だけど、 tumlbr の検索画面でスクロールしていくと、画面から見えなくなった部分の画像は DOM から remove されていく。 コンソールからdocument.querySelectorAll('img').length とかするとそれを確認すること出来る。

たぶん描画の負荷を減らすためなのかなーと思うけど(DOM書き換えるより display:none した方がいいような気もする?)、とにかく DOM 上からいなくなってしまうので下までスクロールして表示された画像の url を全部集めるとかが出来ない。 そこで DOM をストーキングしてみることにした。

MutationObserver

昔は DOMNodeInserted というイベントをハンドルするという方法があったようだけど、今は非推奨のようだ。MutationObserver はより新しい機能で、 DOM の挿入だけでなく属性の変更や子孫要素の挿入なども監視することが出来る。Chrome 拡張のような環境ではこちらを使っておけば良さそう。使い方はリンク先を参照。

Let's stalk Tumblr.

上にも書いたように tumblr 検索での img タグは見えなくなった時点で DOM から除去されていく。ひとしきり autopager で表示した後にページ内の画像 URL を集めるためには、消え行く img タグの url を消えない要素の data-attribute に保存してあげれば良さそうだ.

function helper(nodeList) {
    for (var i = 0; i < nodeList.length; i++) {
        var article = nodeList[i];
        var divs = article.querySelectorAll('[data-lightbox]');
        var urls = $(divs).map(function (idx, div) {
            return JSON.parse(div.getAttribute('data-lightbox'));
        }).toArray();
        article.setAttribute('data-image-urls', JSON.stringify(urls));
    }
}
var mutationObserver = new MutationObserver(function (records) {
    records.forEach(function (record) {
        if (!$(record.target).is('#search_posts'))
            return;
        helper(record.addedNodes);
    });
});
var container = document.querySelector('#search_posts');
mutationObserver.observe(container, { childList: true, subtree: true });
var articles = container.querySelectorAll('article');
helper(articles);

こんな感じで実現できる. #search_posts に検索結果が挿入されるので、ページ読み込み時と autopager による要素の追加時に必要な URL の保存処理を行う. やってる処理自体は、子孫要素からそれっぽい url を拾ってちょうど良さそうな先祖要素の data-attribute に追加するだけ。 tumblr の仕様がかわればすぐに使えなくなるようなものだけど、とりあえずストーキングは完了.

Chrome extension

以前つくった Chrome拡張 に上の機能をつけてみた. 個別の Tumblr サイトからのダウンロードはうまくいかないが Tumblr 検索から zip でガッとダウンロード出来る. 年末のイベントの画像収集などにお使いください.