プログラマでありたい

おっさんになっても、プログラマでありつづけたい

AppStoreからiOSアプリのランキングを取得する

 スマホアプリの人気の動向を知りたい場合は、AppleのAppStoreとGoogle Playを見ると思います。今回は、それを自動的に取得する方法を紹介します。

AppStoreのRSS Feed GeneratorからURL取得



 AppStoreのランキングは、RSS Feedで配信されています。また、いつから存在するのか解らないのですが、このRSS Feedを生成するGeneratorサイトがあり、任意の国/カテゴリー/データ種別用のRSSを指定できるようになっています。

f:id:dkfj:20161007073726p:plain

RSS Generator

例えば、日本での有料のiOSアプリのトップ25を取得する場合は、次のようなURLとなります。
https://itunes.apple.com/jp/rss/topgrossingapplications/limit=25/genre=6015/xml


 取得できるXMLは、次のような形です。
f:id:dkfj:20161007074216p:plain

Google スプレッドシートで取得する



 それでは、取得したデータをGoogle スプレッドシート取得してみましょう。Google スプレッドシートには、幾つか外部データを取得するセル関数が存在します。今回は、ImportFeed関数が良いでしょう。関数の詳細については、この辺りを見てください。


Google スプレッドシートの関数でWebからデータを取得する

 ImportFeedの構文は、次のようになっています。

IMPORTFEED(URL, [クエリ], [見出し], [アイテム数])

 必須はURLのみで、後はオプションです。まずは、URLのみでの取得をしてみましょう。
f:id:dkfj:20161008092711p:plain

 デフォルトでは、Title,Author,URL,Summaryの4つの項目を取得します。しかし、このデータの場合はSummaryが大きすぎて見づらいです。そこで、項目指定で取得することにします。項目は、引数"クエリ"で指定します。欲しい値は、TitleとURLです。その場合、"items title"と"items url"といったように指定します。

=IMPORTFEED("https://itunes.apple.com/jp/rss/topgrossingapplications/limit=25/genre=6015/xml","items title","true")
=IMPORTFEED("https://itunes.apple.com/jp/rss/topgrossingapplications/limit=25/genre=6015/xml","items url","true")


※本当は、1つの関数で取得したいのですが、複数項目を指定する方法が解りませんでした。誰か教えてください。

 A1,A2のセルに上の二つの関数を並べると、次のような形になります。スッキリ!!
f:id:dkfj:20161008093831p:plain

まとめ



 AppStoreのランキングについては、RSSで配信されているので簡単に取得できます。一方で、Google PlayについてはRSSが提供されていません。次回、どうやったら楽に取れるか考えてみます。

See Also:
環境構築レスでAmazonの商品レビューを取得する
Google スプレッドシートの関数でWebからデータを取得する

Google PlayからAndroidアプリのランキングを取得する

 前回、手軽にAppStoreからiOSアプリのランキングを取得する方法を紹介しました。Androidの場合は、どうしたら良いのでしょう?幾つか方法を考えてみます。対象は売上トップのAndroidアプリとして、URLは次の通りです。
https://play.google.com/store/apps/collection/topgrossing?hl=ja

  1. import.io + Google スプレッドシートのあわせ技
  2. Google スプレッドシートのIMPORTXML関数で何とかする
  3. Google Apps Scriptで頑張る
  4. みんな大好きExcelを使う

import.io + Google スプレッドシートのあわせ技



 まず試すのが、import.ioとGoogle スプレッドシートのあわせ技です。これで実現できれば、一番ラクです。

import.ioでログインし、New ExtractorでURLを指定します。すると下記のように、自動的に項目を抽出してくれます。
f:id:dkfj:20161008101245p:plain

ただ、何か辺です。どう見ても日本のランキングには見えません。恐らくIPアドレスを元に実行元の国のランキングを出しているっぽいです。残念です。

 ちなみに、取得結果をGoogle スプレッドシートに吐き出すのは簡単です。作成したEcxtactorからIntegrateタグを選び、Google Sheetsを選ぶとImportData形式の関数を吐き出してくれます。それをスプレッドシートに貼るだけです。

f:id:dkfj:20161008101257p:plain

 簡単なので、国内のデータが取れないのが残念です。
※別解として、AWSのAPI Gatewayを日本に用意して、HTTP Proxyとして返すという手はあるかも。

Google スプレッドシートのIMPORTXML関数で何とかする


 それでは、次にGoogle スプレッドシートのImportXML関数です。先程の実行元IPがあるので、そもそもGoogle スプレッドシートがどこで実行されているか確認する必要があります。httpサーバーを立ててアクセスし、ログからIPアドレスを取得します。その結果を、IPアドレスの素性が解るサイトで検索します。

f:id:dkfj:20161008105657p:plain

 見事にアメリカのカリフォルニアからのアクセスです。残念ながら、何とかなりませんでした。こちらも、Proxy的なモノを用意してとかなら何とか出来るかもしれませんが、一般的では無くなるので、止めておきます。

Google Apps Scriptで頑張る


 次に、Google Apps Scriptで頑張れるか確認してみます。前回と同様に、IPアドレスの素性を調べます。

f:id:dkfj:20161008110017p:plain

 今度は、アメリカのヴァージニア州でした。こちらは、GAEで動いているんだなと、変に納得してしまいます。と言う事で、Google Apps Scriptでも頑張れませんでした。

みんな大好きExcelを使う



 クラウド上のサービスが駄目なら、ローカルから実行すれば良いじゃないか。ということで、みんな大好きなExcelを使ってみましょう。Excelから外部データを取得するには、大きく2つの手段があります。

1. WebService関数を使う
2. VBA+IEでスクレイピング機能

 まず簡単なWebService関数を使ってみましょう。この関数は、URLを指定するだけというお手軽な関数です。

f:id:dkfj:20161008113245p:plain

 エラーが出ています。この関数の弱点として、文字数制限があります。元々Excelのセルの制限に、32,767文字というものがあります。それに引きづられて、関数の取得できる文字列のMaxも32,767文字に制限されています。最近のHTMLだと、殆どの場合が超えてしまいます。RSSとか取得するには、良いんですけどね。今回は使えません。残念。

 仕方がないので、VBA+IEで行ってみましょう。処理の概要としては、VBAからInternetExplorerを立ち上げ、HTMLElementCollectionで必要な部分のHTML要素を抜き出すという方法です。この方法の詳細は、こちらをご参照ください。

Excel VBA+IEでのスクレイピング


 取得方法としては、"card no-rationale square-cover apps small"というclass名指定するとランキングのリストが取得します。そこから、子のオブジェクトを指定するという形になります。その結果をシートに保存します。面倒くさいですね。

Option Explicit
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private objIE As InternetExplorer

Sub main()
    Set objIE = New InternetExplorer
    Dim url
    Dim baseUrl
    
    baseUrl = "https://play.google.com"
    url = baseUrl & "/store/apps/collection/topgrossing?hl=ja"
    objIE.Visible = True
    objIE.Navigate2 (url)
    
    '読み込み完了待ち
    While objIE.readyState <> READYSTATE_COMPLETE Or objIE.Busy = True
        DoEvents
        Sleep 100
    Wend
    Sleep 100
    
    Dim objDoc As HTMLElementCollection
    Set objDoc = objIE.document
    Dim element As IHTMLElement
    Dim title
    Dim path
    Dim row
    row = 1
    
    For Each element In objDoc.getElementsByClassName("card no-rationale square-cover apps small")
        title = element.Children(0).Children(2).Children(1).innerText
        path = element.Children(0).Children(2).Children(1).getAttribute("href")
    
        Worksheets(1).Cells(row, 1) = title
        Worksheets(1).Cells(row, 2) = baseUrl & path
        
        row = row + 1
    Next element
    
    objIE.Quit
    Set objIE = Nothing
End Sub

取得結果は、次のような形になります。
f:id:dkfj:20161008132611p:plain

まとめ


 まさかのExcelを使う羽目になってしまいました。クラウド上のWebサービスは便利なのですが、実行元の制限ができません。クライアント側のIPアドレスによって、国を判別するという処理には極めて弱くなります。AWSのAPI GatewayのHTTP Proxyを使うとか、回避方法は色々あるのですが本筋ではないので省略します。とりあえずIPアドレスを元に判別という処理は、なくしてほしいですねと勝手な願いで終わりとさせて頂きます。

See Also:
AppStoreからiOSアプリのランキングを取得する
環境構築レスでAmazonの商品レビューを取得する
Google スプレッドシートの関数でWebからデータを取得する