WWW::MechanizeとWeb::Scraperでのるレージの獲得のるるをJSONに出力する。

のるるんさまから降り注ぐ大いなる愛。それがのるるです。
我々は神聖なる東急の改札をくぐり、東急の改札から帰ることによってのるるを受け取ることができるのです。
―東急の福音書 第一節

上の引用は私の脳内からの引用です。
のるレージっていうサービスがあるのですが、毎回東急を使うごとにポイントがたまって、その月にいくらポイントを貯めたかによってランクが変動していきます。
今月駅長に昇格して最終ランクまであと一歩なので、週ごとの獲得のるるをチェックしてその日の東急利用経路を変えたいのですが、東急アプリがのるレージに対して全く使い物にならないのと、毎回スマホかタブレットでのるレージのマイページにアクセスするのがめんどくさいので、のるレージの獲得のるるをJSONに出力して、そのJSONを使ってのるレージ専用アプリを作ることにしました。
Android端末でスクレーピングさせても良かったのですが、Androidで使えるWWW::Mechanize相当のライブラリが見つからなかったのでPerlでやってしまいます。

で、WWW::MechanizeとWeb::Scraperの使い方を完全に忘れててAndroidアプリ作るところまでいかなかったので、今回はJSON出力するところまで作りました。
前にAndroidアプリ作ってから1年以上間空いててこっちも完全に忘れてるので、アプリ作り終わる頃には今月終わってそうですね。

のるるを抜き出す箇所については、ChromeでUA偽装してHTML見たあと決め打ちしたので構造変わったら使えなくなります。
コードと出力したJSONは続きに。

Config::Pit – search.cpan.org
Config::Pitでパスワードを直書きしない方法もあるのですが、そこまでする必要のあるアプリじゃないので今回は割愛。

#!/usr/bin/perl

use strict;
use warnings;
use utf8;

use WWW::Mechanize;
use Web::Scraper;
use Data::Dumper;
use JSON;

#正規表現で数字だけ抜き出す
sub get_number(){
	my $element = shift;
	$element->string_value =~ /(d+)/;
	return $1;
}

#のるレージスクレーピング用にUAを偽装する。AndroidしかわからないのでNexus 7
##PC対応させてくれてもいいのにな
my $mech = new WWW::Mechanize( agent => 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03S) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19' );

#ログイン
$mech->get('https://pssl.tokyu.jp/noruleage/index/');
$mech->submit_form(
	fields => {
		mail_address => 'xxx@xxx.xxx',
		pass => 'your_pass'
    }
);
$mech->get('https://pssl.tokyu.jp/noruleage/record/');

#ひと月分ののるる合計
my $ins_scraper = scraper {
	process 'li.dd01', 'month' => sub{&get_number($_);};
	process 'li.dd02', 'obtain_noruru' => sub{&get_number($_)};
	process 'li.dd04 > a', 'url' => '@href';
};

#月ごと
my $scraper = scraper {
	process 'ul.ins', 'noruru_list[]' => $ins_scraper;
};

#その月の日ごとののるる
my $detail_ins_scraper = scraper {
	process 'li.dd01', 'day' => sub{&get_number($_)};
	process 'li.dd02', 'obtain_noruru' => sub{&get_number($_)};
};

#日ごと
my $detail_scraper = scraper {
	process 'ul.tops > li.Md', 'month' => sub{&get_number($_)};
	process 'ul.ins', 'noruru_detail_list[]'  => $detail_ins_scraper;
};

my $noruru = $scraper->scrape( $mech->content );
my $noruru_list = $noruru->{noruru_list};

#日ごとの詳細をURLから取得する
for my $detail (@$noruru_list){
	$mech->get($detail->{url});
	my $detail_noruru = $detail_scraper->scrape( $mech->content );
	$detail->{obtain_detail} = @{$detail_noruru->{noruru_detail_list}};
}

#JSON出力
my $filename = "noruru.json";
open(OUT, ">$filename");
my $json_out = encode_json($noruru_list);
print OUT $json_out;
close(OUT);

出力結果(一部)

//中略
{obtain_noruru: "230",
month: "2",
url: "/noruleage/record-detail?y=2014&m=2",
obtain_detail: [
	{
		obtain_noruru: "0",
		day: "1"
	},
//中略
	{
		obtain_noruru: "10",
		day: "28"
	}
]},
//中略

ひびやきRの香子さんが作っていたのるるんバナーが大変可愛くて、のるるんにちなんだコードを書きたかったので、書けてよかったです。