0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Stravaから zoom 12 以上のheatmapタイルを取得する

Last updated at Posted at 2019-09-25

ブラウザでタイルを取得する

stravaからglobal heat mapのデータを頂く で言及しましたが
StravaのHeatmapタイルでZoom 12以上を指定すると
認証(authentication)が必要である旨が表示されます。

$ curl https://heatmap-external-b.strava.com/tiles/ride/hot/12/3636/1610.png
authentication is now required for data access beyond zoom level 12, please login to strava.com and then visit /auth

Stravaにログインした後に
指示の通り /auth を訪れると cookie をセットした旨のメッセージが表示され
タイル取得の準備が完了となります。

https://heatmap-external-b.strava.com/auth にブラウザでアクセス

Logged in as AthleteId(XXXXXXX), cloudfront cookies set

※IDは伏せました

未ログイン時は

not logged in

多くのcookieを保存しているようですが、
タイル取得に必要なものは以下の3つのようです。

  • CloudFront-Key-PairId
  • CloudFront-Policy
  • CloudFront-Signature

2019-09-19 14:47(JST) の取得で、expireは
2019-09-26 05:47(UTC) = 14:47(JST) に設定されているので賞味期限は7日間
(結構長いじゃん!)

この状態でタイルを取得します。
URLが異なっている (tiles-auth) なので気を付けてください。

URLの例
https://heatmap-external-b.strava.com/tiles-auth/ride/hot/12/3636/1610.png
https://heatmap-external-b.strava.com/tiles-auth/ride/hot/13/7272/3220.png
https://heatmap-external-c.strava.com/tiles-auth/ride/hot/13/7272/3220.png?px=256

自動化の方針

課題は Strava にログインし、必要なcookieを取得する事

方針は色々ありますが...

  1. curlで突破
  2. mechanizeなどのスクレイピングで突破 --> cookie保存 --> そのcookieをcurlに食わす
  3. mechanizeなどのスクレイピングで突破 --> そのまま png (= tile) も取得

今回は 3 でやってみます

自動ログイン&タイル取得コード (Perl)

Perl + Mechanize で組んでみました
試行錯誤のあとの残るコードですが、主要部分を以下に示します

ポイントとなると思われる部分をコメントで記述してあります。
それぞれのポイントの解説はコードの後に。

()
use IO::Socket::SSL qw( SSL_VERIFY_NONE );
use IO::Socket::SSL qw( debug4 ); # ★ポイント(1)★ SSLのハンドシェイクのデバッグに有効
...
my $URL_STRAVA_LOGIN     = "https://www.strava.com/login";
my $URL_STRAVA_TILE_AUTH = "https://heatmap-external-b.strava.com/auth";
my $URL_STRAVA_TILE_PNG  = "https://heatmap-external-b.strava.com/tiles-auth/ride/hot/15/29088/12880.png";

...

### Mechanize Object Creation
my $mech = WWW::Mechanize->new(
	cookie_jar => {},
	autocheck  => 1,
	ssl_opts   => { 
		#verify_hostname => 0,    # 0 = disable SSL host check
		#SSL_verify_mode => SSL_VERIFY_NONE, 
		#SSL_version     => 'TLSv1_2',  # SSL version TLSv1/TLSv1_1/TLSv1_2
		#SSL_hostname    => 'www.strava.com',
		SSL_hostname    => 'heatmap-external-b.strava.com', # ★ポイント(2)★ SSL_hostnameの設定!!
	},
);
# $mech->proxy(['http', 'https'], undef);
$mech->agent_alias('Linux Mozilla');

...

### Strava login page
$mech->get($URL_STRAVA_LOGIN);
print_result($mech); # print_resultは自前の関数。なくてもよい

### input Strava's credential (user/pass) # ★ポイント(3)★ Facebook連動ログインはあきらめた
$mech->submit_form(
	form_number => 1,
	fields      => {
		email => $user,
		password => $pass,
	}
);

...

### Strava auth for tile
$mech->get($URL_STRAVA_TILE_AUTH); # ★ポイント(4)★ タイルのauth urlに一度訪問する
print_result($mech);

### Strava tile
$mech->get($URL_STRAVA_TILE_PNG); # ★ポイント(5)★ authタイル取得URLは "tiles-auth" なので注意!
open(OUT, "> tile.png");
print OUT $mech->content;
close(OUT);

()

ポイント(1) SSLのハンドシェイクのデバッグに有効

コードが動作した後は不要ですが、デバッグ中は有効にしておくと
SSLのハンドシェイクのどこで失敗したかがわかるので非常に有効でした。

use IO::Socket::SSL qw( debug4 ); # ★ポイント(1)★ SSLのハンドシェイクのデバッグに有効

ポイント(2) SSL_hostnameの設定 【重要】

一番のポイントでした
これがないと 14094410 エラーが発生してアクセスできません。
解決の手がかりはこちらでした。
OpenSSL APIメモ(handshake failure)
SNIへの対応が必要です。
具体的にはサーバ側にhostnameをわたす必要があります。
Mechanize(というか IO::Socket::SLL)での指定は以下になります。

my $mech = WWW::Mechanize->new(
	cookie_jar => {},
	autocheck  => 1,
	ssl_opts   => { 
		#verify_hostname => 0,    # 0 = disable SSL host check
		#SSL_verify_mode => SSL_VERIFY_NONE, 
		#SSL_version     => 'TLSv1_2',  # SSL version TLSv1/TLSv1_1/TLSv1_2
		#SSL_hostname    => 'www.strava.com',
		SSL_hostname    => 'heatmap-external-b.strava.com', # ★ポイント(2)★ SSL_hostnameの設定!!
	},
);

その他オプションについてはこちらを参照のこと
https://metacpan.org/pod/IO::Socket::SSL

ポイント(3) Facebook連動ログインはあきらめ、Strava user/pass でログイン

Facebookのページに飛んだあとどうしてもスマホにPINコードが飛んでこず
Facebookアカウントでのログインはあきらめました。
Stravaにパスワード設定して、email + passでログイン

$mech->submit_form(
	form_number => 1,
	fields      => {
		email => $user,
		password => $pass,
	}
);

ポイント(4) タイルのauth urlに一度訪問する

Strava様の指示通りに...

my $URL_STRAVA_TILE_AUTH = "https://heatmap-external-b.strava.com/auth";
$mech->get($URL_STRAVA_TILE_AUTH); # ★ポイント(4)★ タイルのauth urlに一度訪問する

ポイント(5) authタイル取得URLは "tiles-auth" なので注意

Zoom = 11までのタイルとはURLが異なるので注意してください

my $URL_STRAVA_TILE_PNG  = "https://heatmap-external-b.strava.com/tiles-auth/ride/hot/15/29088/12880.png";
$mech->get($URL_STRAVA_TILE_PNG); # ★ポイント(5)★ authタイル取得URLは "tiles-auth" なので注意!

以上です

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?