Hello Wor.log

IT系大学生4人による備忘録のようなもの

PGLのポケモンデータ集計【python】

こんばんは、cppxのP2です。
今回は、前回の記事のコードを少し変更してpglのルールごとのポケモンデータ(json形式)を全取得をします。 その後、取得したデータ内の「倒したポケモン」に出現した回数と「倒されたポケモン」に出現した回数を数え上げて、「倒しやすく、倒されにくい」っぽいポケモンを探したいと思います。
環境はUbuntu上でpythonは3系

ルールごとのデータの全取得

import requests
from time import sleep
import json

url = "https://3ds.pokemon-gl.com/frontendApi/gbu/getSeasonPokemonDetail"
headers = {
"Host": "3ds.pokemon-gl.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0",
"Accept": "*/*",
"Accept-Language": "ja,en-US;q=0.7,en;q=0.3",
"Accept-Encoding": "gzip, deflate, br",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"Referer": "https://3ds.pokemon-gl.com/battle/",
"Content-Length": "287",
"Cookie": "site=1; language_id=1; region=0; _ga=GA1.2.580975419.1428913003; __ulfpc=201504131716426123; __utma=234147713.580975419.1428913003.1478879399.1479779450.3; __utmz=234147713.1478879399.2.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); s_fid=289F92E7E204472A-0769DD1F44BC4871; JSESSIONID=5F24620B34540182F0F1BC00A84A37CA; AWSELB=C95303410E583113FAF27D987FE57908F5BE8EE44B6EBF706FE32F03B8330D7D6AD01D27A6F20CC82C78B897C0BDF400DADB24277E7E8E3D98F717A77FD139BBF11516937C2B9D32F765752A4099B015B3E471B8C9; NO_MEMBER_DATA=%7B%22language_id%22%3A1%2C%22site%22%3A1%2C%22region%22%3A0%7D; s_cc=true; _gat=1",
"Connection": "keep-alive",
}

payload = {
    "languageId":1,
    "seasonId":204,
    "battleType":1,
    "timezone":"JST",
    "pokemonId":"1-0",
    "displayNumberWaza":10,
    "displayNumberTokusei":3,
    "displayNumberSeikaku":10,
    "displayNumberItem":10,
    "displayNumberLevel":10,
    "displayNumberPokemonIn":10,
    "displayNumberPokemonDown":10,
    "displayNumberPokemonDownWaza":10,
    "timeStamp":1490804393369
}

pokemonId = "1-0"
while True:
    payload["pokemonId"] = pokemonId
    r = requests.post(url, headers=headers, data=payload)
    j = r.json()
    if len(j["rankingPokemonDown"]) == 10 and len(j["rankingPokemonSufferer"]) == 10:
        f = open(pokemonId + ".json", 'w')
        json.dump(j,f)
        f.close()
        sleep(0.5)
    pokemonId = j["nextPokemonId"]
    if pokemonId == "1-0":
        break

url,headers,payloadの値は、
firefoxのネットワークモニターで確認できるxhrリクエストに使用されていた
要求URLとヘッダー、パラメータを使用しました。

payloadの各キーについて

  • seasonId
    レーティングバトルのシーズン(20X)
  • battleType
    各ルールに対応する(シングル:1, ダブル:2, スペシャル:5, WCS:6)
  • pokemonId
    図鑑番号-フォルム
  • displayNumber○○
    取得する○○データの数

ソースコードについて

while文でレスポンスのnextPokemonIdが1-0になるまで
つまりマギアナ(801-0)のnextPokemonIdまたは異常値のnextPokemonIdまで回す。
payloadのpokemonIdを更新しながらpostリクエストを投げ続け、
レスポンスをjsonに変換し、倒したポケモンと倒されたポケモンの情報が10体取得できていれば、
jsonファイルとして保存している。

jsonディレクトリの作成とjsonファイルの移動

作業ディレクトリで、mkdir jsonをしてjsonを置いておくディレクトリを作成する。
その後、mv *.json ./jsonjsonファイルを移動させる。

データの集計

import os
import json
from collections import Counter
files = os.listdir("./json/")
cnt_dat = Counter()

for file in files:
    f = open("./json/" + file, "r")
    json_dict = json.load(f)
    if len(json_dict["rankingPokemonDown"]) == 10 and len(json_dict["rankingPokemonSufferer"]):
        for p in [json_dict["rankingPokemonDown"][x]["name"] for x in range(len(json_dict["rankingPokemonDown"]))]:
            cnt_dat[p] += 1
        for p in [json_dict["rankingPokemonSufferer"][x]["name"] for x in range(len(json_dict["rankingPokemonSufferer"]))]:
            cnt_dat[p] -= 1


for key, value in sorted(cnt_dat.items(), key=lambda x:x[1], reverse=True):
    print(key, value)

os.listdir()でjsonディレクトリのファイル名一覧を取得して、for文で回す。
jsonファイルを開いて、倒されたポケモンと倒したポケモンの数が10なら、倒されたポケモンに出てきたポケモンのカウントを+1して、倒したポケモンに出てきたポケモンのカウントを-1する。
この処理によって、「倒しやすく、倒されにくい」ポケモンのカウントが高くなるはず?
最後に、カウントした結果を降順でソートしてprintで出力している。

実行結果

ギルガルド 106
ボーマンダ 101
カプ・テテフ 98
ミミッキュ 55
リザードン 55
ゲッコウガ 40
ヘラクロス 40
メタグロス 37
カプ・コケコ 35
アシレーヌ 27
ガルーラ 27
ルカリオ 22
ボルトロス 15
クチート 14
カイリュー 7
フェローチェ 4
カミツルギ 3
ヘルガー 2
オニゴーリ 2
ペリッパー 1
ジバコイル 1
カビゴン 1
ガラガラ 1
キングドラ 1
ユレイドル 1
メブキジカ 1
ハガネール 1
ルチャブル 1
ペンドラー 1
シャンデラ 1
マニューラ 1
サザンドラ 1
シャワーズ 1
トゲデマル 1
アーケオス 1
フーディン 1
オニシズクモ 1
チャーレム 1
クワガノン 0
ドラミドロ 0
ゴウカザル 0
ロトム 0
トゲキッス 0
エーフィ 0
マッシブーン 0
サンダー 0
ベトベトン 0
カプ・ブルル 0
パンプジン 0
マリルリ 0
グソクムシャ 0
オオスバメ -1
バルジーナ -1
ブーバーン -1
ホルード -1
ドダイトス -1
スイクン -1
バンバドロ -1
ニドキング -1
ラグラージ -1
ルンパッパ -1
ジュカイン -1
ナマコブシ -1
ラッキー -1
ワルビアル -1
ブラッキー -1
ファイヤー -1
カメックス -1
クレセリア -1
コータス -1
ユキメノコ -1
ドサイドン -1
カエンジシ -1
メテノ -1
カイロス -1
ハピナス -1
リーフィア -1
ドラピオン -1
ファイアロー -1
イーブイ -1
オーロット -1
エンテイ -1
ニンフィア -1
クレベース -1
ムクホーク -1
トリトドン -1
バクオング -1
ゴチルゼル -1
レジアイス -1
バイバニラ -1
ナマズン -1
ローブシン -1
ヒヒダルマ -1
エンペルト -1
モロバレル -1
ミズゴロウ -1
ルナトーン -1
ユキノオー -1
ラティアス -2
クレッフィ -2
ドリュウズ -2
ハッサム -2
デンジュモク -2
マフォクシー -2
キリキザン -2
ミロカロス -3
サメハダー -3
エアームド -3
キュウコン -3
ポリゴンZ -3
ラティオス -4
ヌメルゴン -4
ウツロイド -4
バンギラス -5
グライオン -8
パルシェン -8
ドヒドイデ -10
フシギバナ -10
テッカグヤ -12
ジャローダ -18
ウルガモス -21
ランドロス -22
ガブリアス -24
バシャーモ -24
ヒードラン -26
キノガッサ -26
カプ・レヒレ -28
ゲンガー -33
ポリゴン2 -36
マンムー -38
ギャラドス -62
ナットレイ -94
カバルドン -116

実行結果を見ると、
耐性が優秀なポケモンや素早さが高く火力の高いポケモンが上の方に多く、
起点作りなどの補助型や、4倍弱点を持っているポケモンなどが下の方に多いので、
人間的な感覚としてもまあまあ納得できる結果になったと思う?

課題としては、0付近のポケモンに使用率が低いポケモンと使用率が高いポケモンが混在していると同じ0付近でも意味が変わってしまう。
また、今回はただ単に倒されたポケモンと倒したポケモンに出現した回数を数えただけなので、より多い"種類"のポケモンに強いかどうかしか読み取れない気がする。
使用率ランキングや倒された・倒したポケモンに出現した際の順位を考慮できるとよさそう。