BLOGサブスレッドの日常

2016.05.02

さくっとスクレイピング

tama

月曜日担当tamaです。

5月になりましたねー。もう暑いですねー。4月5月でこんなに暑かったら12月はどれだけ(ry

スクレイピング

Webサイトからさくっと情報収集したいこと、ありますよね。
tenki.jpをスクレイピングすれば12月までのお天気もまるわかr…にはならないのですが。

具体的には前回の学生サポートサイトの元データとなる時間割情報なんかを、
学内向けの授業情報サイトからごっそり取ってきたかったりします。

じゃそもそも時間割サイトなんかいらないんじゃね?と思うじゃん?


見てこれ →

ポータルのトップに「指定日と次の日」の時間割 だけ が表示されるのです。
担当教員は授業に登録されている人が全員表示されて、課題や試験の有無はもちろんわからない。
時間割風に表示することも一覧表示することもできず、とにかく 使いにくい

おわかりいただけただろうか。今日もみっちり授業が…ギャー
(枠がズレてるのはご愛嬌。こんなの比じゃないくらいアレなバグとかてんこ盛りだから。
一般公開サイトだったらIPA凸事案も)

さてこのサイトから時間割情報をスクレイピングしたいんですが、ふたつ課題があります。

  • 要ログイン
    • ログイン画面でログイン処理をしてセッションIDを払い出させてそれを毎回のリクエストにCookieで持たせる必要がある
  • 日付選択時の画面遷移がJavaScript
    • 選択した日付をフォームデータとしてPOSTで遷移しているもよう
    • スクレイピングスクリプトで同様の処理が必要

…めんどくさい(#^ω^)

さくっと

シェルスクリプトからcurlやwgetとgrep、sedを駆使するとか、
Python等のスクリプトからHTTPリクエストを投げるとか、
スクレイピングにもいろんな手法がありますが、
今回は1回だけショットで実行できればいいのです。
こんなときいちばん手っ取り早いのは Chromeデベロッパーツール です。
(定期的にcronで実行、、などの場合はまた別のアプローチがあると思います)

やってみましょう。

まずはウィンドウ内のハンバーガーメニュー から
その他のツールデベロッパーツール を開き Console タブを開きます。
ハンバーガーメニューが見つからないときはショートカットキーで ⌘ + ⌥ + J 。
Windowsの場合は、、、えーと、 Ctrl + Shift + J らしいです。ヘー

そしておもむろに window.open()
ポップアップがブロックされても慌てず騒がず about:blank をクリックして開いてやってください。
これで準備ができました。ここで開いたウィンドウのことはしばらく忘れてください。

さっきの Console タブに戻って jQuery と入れてみてjQueryが使えればラッキー!そのままjQueryでスクレイピングしちゃえます。
Unfortunately(CodeJamでよく見る単語のひとつ)、jQueryが入っていないときは自分でinjectionします。

var s = document.createElement('script');
s.setAttribute('src', 'https://code.jquery.com/jquery-2.2.3.min.js');
document.body.appendChild(s);

jQueryが使えるようになったらスクレイピングしたい要素を右クリックして 検証 を選んだりして
Elements タブの中で目的のデータを見つけ、jQueryでそのデータを特定できるようにセレクタをこねこねします。

今回見ているところだと $('.date').closest('table') で授業情報の table にたどり着きました。
この中から必要な情報だけ取り出して、例えば console.log に吐き出してみます。
(これはあとから配列に入れてもよいのでとりあえず)

var date = '';
$('.date').closest('table').find('td.colPad').each(function(index, elem) {
    var $elem = $(elem);
    if ($elem.find('.date').length) {
        if (date) {
            // 日付が変わる時点で終了する
            return false;
        }
        date = $elem.find('.date').text();
    }
    var period = $elem.find('.jyugyoMark').text().replace(/限目/, '');
    var lesson = $elem.find('.detailArea .jugyo').text();
    console.log(date + ',' + period + ',' + lesson);
});

さてところで日付は <a class="weekDayColor" href="javascript:selectDate(6);">6</a> こんなタグになっています。
えぇ、6日も授業がありますよ平日ですから😇

Console タブで selectDate(日付); すれば別の日の授業情報が表示されますがページ遷移してしまいます。
そこで最初に window.open() した子ウィンドウ。
子ウィンドウのデベロッパーツールから opener を介して制御するとページをまたいで情報を集めてくることができます。
例えば… opener.selectDate(9);

ページ遷移に少し時間がかかることに留意して setTimeout() を使って再帰すればこんな感じ。

var procDay = function(month, day) {
    opener.selectDate(day);
    setTimeout(function() {
        var date = '';
        opener.$('.date').closest('table').find('td.colPad').each(function(index, elem) {
            var $elem = opener.$(elem);
            if ($elem.find('.date').length) {
                if (date) {
                    // 日付が変わる時点で終了する
                    return false;
                }
                date = $elem.find('.date').text();
            }
            var period = $elem.find('.jyugyoMark').text().replace(/限目/, '');
            var lesson = $elem.find('.detailArea .jugyo').text();
            if (period || lesson) {
                console.log(date + ',' + period + ',' + lesson);
            }
        });
        if (day < 31) {
            procDay(month, day + 1);
        } else if (month < 7) {
            opener.$('#form1\\:Poa00101A\\:nextMonth').click();
            setTimeout(function() { procDay(month + 1, 1); }, 2000/*ms wait*/);
        }
    }, 2000/*ms wait*/);
};

procDay(4, 1);

さくっとスクレイピング

一般公開のサイトではないので例がわかりにくい感じですが、、

  • Chromeデベロッパーツールを使うとブラウザのDOM解釈に基いてjQueryで要素特定がラクラク!
  • window.open() すればページ遷移してもデベロッパーツールのスクリプトを動かし続けられるよ

ということがわかっていただけたら今日のわたくしの役目は終了でございます。

またねー

※ スクレイピングはサイトの利用規約に違反する場合があるので十分注意してご利用ください。

この記事を書いた人

tama