Developer's Blog

iTunes Connect に自動ログインして情報を取得する

こんにちはこんにちは! エンジニア川端です。
プロダクトの開発ではなく、裏方的なことをやってます。
今日は、普段私が担当している、表に出てこないお話をさせてください。
iPhone アプリ開発者の方にはおなじみの「iTunes Connect」。
App Store で公開するアプリケーションを申請したり、公開日を設定したり、iPhone アプリに関する色んなことができるサイトですが、公開後のダウンロード数の確認などでアクセスすることが多いのではないでしょうか。
ログインして情報を得て、関係者に回覧して……毎日十数分の作業とはいえ、本来やるべきこと (情報を材料に、次の計画をたてる等) に注力したい。なんとかならないかな。
「やりましょう!」


やりたいことは、ダウンロード数等の日時集計レポート CSV をダウンロードすることです。
「Sales Report」をクリックするとダウンロードできるファイルを、1 日 1 回自動でダウンロードします。
CSVをダウンロード

perl get_itunesconnect_csvgz.pl 2011-06-01| zcat > 2011-06-01.csv

みたいな感じで保存できるようにしておけば、後は毎日寝てる間に実行しておくだけ。社内システムへの取り込みも自動化して、朝出社したら閲覧できる状態……なんですけどね。
iTunes Connect のサイトって、見た目はページ遷移しなくて、裏でバンバンリクエストが飛んで処理してる感じなんで、調査しながら、ちょっと泣きそうになりました。
まぁ、できあがったプログラム見てしまうとなんてこたぁないんですけど。

use utf8;
use strict;
use warnings;
use Config::Pit;
use WWW::Mechanize;
$Config::Pit::verbose = 0;
{
my $date = shift || '';
die 'usage: ',$0,' YYYY-MM-DD'
unless ($date and $date =~ /^\d{4}-\d{2}-\d{2}$/);
my($y,$m,$d) = split /-/, $date;
my $key = 'https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/';
my $common_url = 'https://reportingitc.apple.com/sales.faces';
pit_switch('itunes_connect');
my $conf = pit_get( $key );
my $w = WWW::Mechanize->new( cookie_jar => {} );
# login
$w->get( $key );
$w->submit_form(
form_name => 'appleConnectForm',
fields => {
theAccountName => $conf->{username},
theAccountPW => $conf->{password},
}
);
my $view_state;          # j_idxxxxx:j_idxxxxx
my $default_vendor_page; # j_id_jsp_xxxxxxxxx_2
my $ajax_request;        # j_id_jsp_xxxxxxxxx_?
# view "Sales and Trends" dashboard
$w->get('https://reportingitc.apple.com/');
($view_state = $w->content()) =~ s|^.*id="javax.faces.ViewState" value="([^"]+)".*$|$1|s;
($default_vendor_page = $w->content() ) =~ s|^.*defaultVendorPage:(j_id_jsp_[^:"]+)".*$|$1|s;
($ajax_request = $default_vendor_page) =~ s|_2$|_0|;
$w->post('https://reportingitc.apple.com/vendor_default.faces',{
'AJAXREQUEST' => $ajax_request,
'defaultVendorPage' => 'defaultVendorPage',
'javax.faces.ViewState' => $view_state,
'defaultVendorPage:'.$default_vendor_page => 'defaultVendorPage:'.$default_vendor_page,
} );
# select 'Sales' Tab
my $common_query = {
'theForm' => 'theForm',
'theForm:xyz' => 'notnormal',
'theForm:vendorType' => 'Y',
'theForm:optInVar' => 'A',
'theForm:optInVarRender' => 'false',
'theForm:wklyBool' => 'false',
'theForm:datePickerSourceSelectElementSales' => $m.'/'.$d.'/'.$y,
#			'theForm:weekPickerSourceSelectElement' => # その週の日曜日。デイリーレポート取得時は、いらないっぽい
};
$w->get( $common_url );
($view_state = $w->content()) =~ s|^.*id="javax.faces.ViewState" value="([^"]+)".*$|$1|s;
($default_vendor_page = $w->content() ) =~ s|^.*'theForm:(j_id_jsp_(?:\d)+_6)'.*$|$1|s;
($ajax_request = $default_vendor_page) =~ s|_6$|_2|;
$w->post( $common_url, {
%$common_query,
'AJAXREQUEST' => 'theForm:'.$ajax_request,
'javax.faces.ViewState' => $view_state,
'theForm:'.$default_vendor_page => 'theForm:'.$default_vendor_page,
} );
# get csv file
($view_state = $w->content()) =~ s|^.*id="javax.faces.ViewState" value="([^"]+)".*$|$1|s;
$w->post( $common_url, {
%$common_query,
'javax.faces.ViewState' => $view_state,
'theForm:downloadLabel2' => 'theForm:downloadLabel2',
'dailyName' => 'dailyName'
} );
print $w->content(); # gz
}
exit;

15 分の作業を 10 分に短縮するのは慣れれば自然とそうなるし、10 分を 5 分にするのも工夫すればなんとかなりそう。でも、5 分を 0 分にするのは難しい。
難しいけど、30 人の 5 分を 0 分にできれば。50 人の 5 分を 0 分にできれば。10000 人の 5 分を 0 分にできれば。
……というような事を考えながら、作業に勤しむ毎日です。
そんな地味なエンジニアも所属するフェンリル、これからも応援よろしくお願いします!

Copyright © 2019 Fenrir Inc. All rights reserved.