てくてくテック

気ままに開発のメモを書いていこうと思います。主にSwiftかと。

Reporterを使ってiTunes ConnectのSales and Trendsを自動で取得する - 解析編

はじめに

今回はReporterを使ってiTunes ConnectのSales and Trendsを自動で取得する - 設計編におけるdaily reportの"iTunes Connectから取得"と"インストール数の取得"のサンプルを実装しようと思います。最終的な実装とはちょっと違いますが基本は同じです。

環境

環境 version
OS OS X EL Capitan 10.11.6
ruby 2.3.1(rbenv)

実装方針

  1. シェルコマンドを実行してreporterを実行
  2. Zlib::GzipReaderを使ってgzファイルを解凍
  3. ターゲットとしているアプリかつProduct typeのunitsをかき集める

シェルコマンドを実行してreporterを実行

reporter自体はjavaで実行なのでrubyからシェルコマンドを実行する仕組みを実装します。Rubyで外部コマンドを実行して結果を受け取る方法あれこれを見るといろいろあるみたいですけど一番簡単そうなバッククォートで良さそうです。

date = "20161101"
report_xml = `java -jar Reporter.jar p=Reporter.properties m=Robot.XML Sales.getReport <vendor id>, Sales, Summary, Daily, #{date}` 

Zlib::GzipReaderを使ってgzファイルを解凍

サンプル見るのが早いかと思います。

require 'zlib'

date = "20161101"
file_name = "S_D_<vendor id>_#{date}.txt.gz"

Zlib::GzipReader.open(file_name){|gz|
# 最初のlineはムシ
gz.gets

while s = gz.gets
    p s
}

ターゲットとしているアプリかつProduct typeのunitsをかき集める

今回は簡略化のため一つのアプリに限定してます。
ここで問題となるのが、取得できるデータが各アプリのインストール毎という形式ではなく、各アプリのProduct Typeや地域毎という感じで別れてしまっていることです。今回は、ターゲットとしたアプリの全地域でのインストール数を取得するという方針でいきます。

require 'zlib'

# http://help.apple.com/itc/appssalesandtrends/#/itc0c699d615
# アップデートとかを集計しないため
TargetProductIds = ["1", "1F", "1T"].freeze
TargetBundleId = "hogehoge".freeze

date = "20161101"
file_name = "S_D_<vendor id>_#{date}.txt.gz"
app_unitis = 0

Zlib::GzipReader.open(file_name){|gz|
    # 最初のlineはムシ
    gz.gets

    while s = gz.gets
        # tsvでタグ区切りなので
        rows = s.split("\t")

        # 正確にはSKUだったけどほとんどの場合bundle_idと同じにするだろうからこのままでorz
        bundle_id = rows[2]
        units = rows[7].to_i
        product_type_id = rows[6]

        if !TargetProductIds.include?(product_type_id)
            next
        end

        if bundle_id == TargetBundleId
            app_units += units
        end
    end
}

p app_units

コード全部

require 'rexml/document'
require 'zlib'
# http://help.apple.com/itc/appssalesandtrends/#/itc0c699d615
# アップデートとかを集計しないため
TargetProductIds = ["1", "1F", "1T"].freeze
TargetBundleId = "hogehoge".freeze
VendorId = 1111111.freeze

date = "20161101"
report_xml = `java -jar Reporter.jar p=Reporter.properties m=Robot.XML Sales.getReport #{VendorId}, Sales, Summary, Daily, #{date}` 

report_result = REXML::Document.new(get_report_xml)
unless report_result.elements['Error/Code'].nil?
    p get_report_result.elements['Error/Code'].text
    p get_report_result.elements['Error/Message'].text
    # TODO: きちんと例外処理
    raise "Reporterのダウンロードに失敗しました"
end

file_name = "S_D_#{VendorId}_#{date}.txt.gz"
app_unitis = 0

Zlib::GzipReader.open(file_name){|gz|
    # 最初のlineはムシ
    gz.gets

    while s = gz.gets
        # tsvでタグ区切りなので
        rows = s.split("\t")

        # 正確にはSKUだったけどほとんどの場合bundle_idと同じにするだろうからこのままでorz
        bundle_id = rows[2]
        units = rows[7].to_i
        product_type_id = rows[6]

        if !TargetProductIds.include?(product_type_id)
            next
        end

        if bundle_id == TargetBundleId
            app_units += units
        end
    end
}

p app_units