首页 > 解决方案 > 使用 python 与 JSON 交互的更快方法

问题描述

我刚刚开始练习使用 JSON 文件并与 API 进行交互,在这种情况下,我正在与游戏的 API(Riot API)进行交互。我有一个带有我的比赛历史的 JSON,它看起来像这样(我刚刚复制了 3 场比赛,真实文件更长):

{
    "matches": [
        {
            "platformId": "EUW1",
            "gameId": 4733037811,
            "champion": 111,
            "queue": 420,
            "season": 13,
            "timestamp": 1596031907965,
            "role": "DUO_SUPPORT",
            "lane": "BOTTOM"
        },
        {
            "platformId": "EUW1",
            "gameId": 4732867446,
            "champion": 25,
            "queue": 420,
            "season": 13,
            "timestamp": 1596022617021,
            "role": "DUO_SUPPORT",
            "lane": "BOTTOM"
        },
        {
            "platformId": "EUW1",
            "gameId": 4732833555,
            "champion": 111,
            "queue": 420,
            "season": 13,
            "timestamp": 1596020420595,
            "role": "DUO_SUPPORT",
            "lane": "BOTTOM"
        },
        {
            "platformId": "EUW1",
            "gameId": 4731796980,
            "champion": 53,
            "queue": 420,
            "season": 13,
            "timestamp": 1595967793994,
            "role": "DUO_SUPPORT",
            "lane": "BOTTOM"
        },

但是,我想要更多关于我的游戏的信息,我需要使用该游戏搜索特定游戏。包含特定游戏信息的 JSON 如下所示(由于 JSON 的大小,我删除了每个玩家的一些不必要的统计信息):

{
    "gameId": 4733037811,
    "platformId": "EUW1",
    "gameCreation": 1596031907965,
    "gameDuration": 1624,
    "queueId": 420,
    "mapId": 11,
    "seasonId": 13,
    "gameVersion": "10.15.330.344",
    "gameMode": "CLASSIC",
    "gameType": "MATCHED_GAME",
    "participants": [
        {
            "participantId": 1,
            "teamId": 100,
            "championId": 61,
            "stats": {
                "participantId": 1,
                "win": true,
                "kills": 14,
                "deaths": 0,
                "assists": 7,
                "totalDamageDealt": 167616,
                "magicDamageDealt": 149177,
                "physicalDamageDealt": 10740,
                "trueDamageDealt": 7698,
                "totalDamageDealtToChampions": 22933,
                "magicDamageDealtToChampions": 21067,
                "physicalDamageDealtToChampions": 1208,
        },
        {
            "participantId": 2,
            "teamId": 100,
            "championId": 21,
            "stats": {
                "participantId": 2,
                "win": true,
                "kills": 2,
                "deaths": 3,
                "assists": 6,
                "totalHeal": 1742,
                "totalUnitsHealed": 2,
                "damageSelfMitigated": 7396,
                "damageDealtToObjectives": 19128,
                "damageDealtToTurrets": 4817,
        },
        {
            "participantId": 3,
            "teamId": 100,
            "championId": 432,
            "stats": {
                "participantId": 3,
                "win": true,
                "kills": 1,
                "deaths": 4,
                "assists": 14,
                "largestKillingSpree": 0,
                "trueDamageDealt": 3202,
                "largestCriticalStrike": 0,
                "totalDamageDealtToChampions": 7395,
                "magicDamageDealtToChampions": 5286,
        {
            "participantId": 4,
            "teamId": 100,
            "championId": 122,
            "stats": {
                "participantId": 4,
                "win": true,
                "kills": 7,
                "deaths": 2,
                "assists": 6,
                "largestKillingSpree": 5,
                "largestMultiKill": 2,
                "killingSprees": 1,
        {
            "participantId": 5,
            "teamId": 100,
            "championId": 79,
            "stats": {
                "participantId": 5,
                "win": true,
                "kills": 1,
                "deaths": 3,
                "assists": 9,
                "largestKillingSpree": 0,
                "largestMultiKill": 1,
                "killingSprees": 0,
                "longestTimeSpentLiving": 422,
                "totalDamageDealt": 143803,
                "magicDamageDealt": 104935,
                "physicalDamageDealt": 31981,
                "trueDamageDealt": 6886,
        },
        {
            "participantId": 6,
            "teamId": 200,
            "championId": 111,
            "stats": {
                "participantId": 6,
                "win": false,
               "kills": 1,
                "deaths": 5,
                "assists": 7,
                "largestKillingSpree": 0,
                "largestMultiKill": 1,
                "longestTimeSpentLiving": 460,
                "totalDamageDealt": 26611,
                "magicDamageDealt": 9267,
                "physicalDamageDealt": 11730,
                "trueDamageDealt": 5613,
                "largestCriticalStrike": 0,
        },
        {
            "participantId": 7,
            "teamId": 200,
            "championId": 56,
            "stats": {
                "participantId": 7,
                "win": false,
                "kills": 3,
                "deaths": 2,
                "assists": 3,
                "totalDamageDealt": 140699,
                "magicDamageDealt": 5378,
                "physicalDamageDealt": 131565,
                "trueDamageDealt": 3755,
                "largestCriticalStrike": 0,
                "totalDamageDealtToChampions": 6557,
                "magicDamageDealtToChampions": 455,
                "physicalDamageDealtToChampions": 5549,
                "trueDamageDealtToChampions": 552,
                "totalHeal": 12548,
                "totalUnitsHealed": 1,
                "damageSelfMitigated": 13095,
                "damageDealtToObjectives": 8279,
                "damageDealtToTurrets": 791,
        },
        {
            "participantId": 8,
            "teamId": 200,
            "championId": 55,
            "stats": {
                "participantId": 8,
                "win": false,
                "kills": 3,
                "deaths": 5,
                "assists": 1,
                "largestKillingSpree": 2,
                "largestMultiKill": 2,
                "killingSprees": 1,
                "longestTimeSpentLiving": 599,
                "doubleKills": 1,
                "tripleKills": 0,
                "quadraKills": 0,
                "pentaKills": 0,
                "unrealKills": 0,
                "totalDamageDealt": 98182,
                "magicDamageDealt": 82014,
                "physicalDamageDealt": 15485,
                "trueDamageDealt": 682,
                "largestCriticalStrike": 0,
                "totalDamageDealtToChampions": 8542,
                "magicDamageDealtToChampions": 6674,
                "physicalDamageDealtToChampions": 1185,
                "trueDamageDealtToChampions": 682,
        },
        {
            "participantId": 9,
            "teamId": 200,
            "championId": 429,
            "stats": {
                "participantId": 9,
                "win": false,
                "kills": 4,
                "deaths": 9,
                "assists": 3,
                "longestTimeSpentLiving": 489,
                "totalDamageDealt": 83886,
                "magicDamageDealt": 2860,
                "physicalDamageDealt": 77851,
                "trueDamageDealt": 3175,
                "largestCriticalStrike": 290,
                "totalDamageDealtToChampions": 16216,
                "magicDamageDealtToChampions": 1500,
                "physicalDamageDealtToChampions": 14715,
                "trueDamageDealtToChampions": 0,
        },
        {
            "participantId": 10,
            "teamId": 200,
            "championId": 68,
            "stats": {
                "participantId": 10,
                "win": false,
                "kills": 1,
                "deaths": 4,
                "assists": 0,
                "totalDamageDealt": 88848,
                "magicDamageDealt": 73156,
                "physicalDamageDealt": 11816,
                "trueDamageDealt": 3875,
                "largestCriticalStrike": 0,
                "totalDamageDealtToChampions": 12531,
                "magicDamageDealtToChampions": 11890,
                "physicalDamageDealtToChampions": 640,
                "trueDamageDealtToChampions": 0,
            },
        }
    ],
}

如您所见,在显示比赛详细信息的 JSON 文件中,它显示了每个球员的统计数据。为了获取我的信息,我遍历了每个玩家,直到找到在那场比赛中扮演我的英雄的那个人,这显示在我过去比赛的 JSON 文件中。

因此,我所做的整个过程是:遍历每场比赛,保持“gameId”和“champion”的值,然后我用gameId搜索JSON文件,并循环遍历这个JSON的所有玩家,直到找到我的“冠军”,以便获取有关多少杀戮,死亡的信息......我在那场比赛中有多少。这是我的代码:

URL = "https://" + server + ".api.riotgames.com/lol/match/v4/matchlists/by-account/" + account_id + "?api_key=" + ApiKey
response = requests.get(URL)
old_games_json = response.json()
old_games_json = old_games_json['matches']

for index in range(len(old_games_json)):
    champion = (old_games_json[index]['champion'])
    
    gameid = (old_games_json[index]['gameId'])
    
    URL = "https://" + server + ".api.riotgames.com/lol/match/v4/matches/" + str(gameid) + "?api_key=" + ApiKey
    
    response = requests.get(URL)
    game_json = response.json()
    
    for player in range(len(game_json['participants'])):
        if (game_json['participants'][player]['championId']) == champion:
            win = game_json['participants'][player]['stats']["win"]
            kills = game_json['participants'][player]['stats']["kills"]
            deaths = game_json['participants'][player]['stats']["deaths"]
            assists = game_json['participants'][player]['stats']["assists"]

问题是我在一个循环中循环,这需要大量时间来运行脚本。我的问题是,有什么方法可以让这个过程更快?

感谢您花时间阅读这篇文章。

标签: pythonjsonperformancememory-efficient

解决方案


您可以使用 for-comprehension 构建字典champion_stats,如下所示(以线性时间)。之后的主循环将只是线性时间(显示在底部)。请注意,数据已被简化。

old_games_json = {
    "matches": [
        {
            "platformId": "EUW1",
            "gameId": 4733037811,
            "champion": 111,
        },
        {
            "platformId": "EUW1",
            "gameId": 4732867446,
            "champion": 25
        },
        {
            "platformId": "EUW1",
            "gameId": 4731796980,
            "champion": 53
        }
    ]
}

game_json = {
    "gameId": 4733037811,
    "platformId": "EUW1",
    "gameCreation": 1596031907965,
    "gameDuration": 1624,
    "queueId": 420,
    "mapId": 11,
    "seasonId": 13,
    "gameVersion": "10.15.330.344",
    "gameMode": "CLASSIC",
    "gameType": "MATCHED_GAME",
    "participants": [
        {
            "participantId": 1,
            "teamId": 100,
            "championId": 111,
            "stats": {"win": 11}
        },
        {
            "participantId": 2,
            "teamId": 100,
            "championId": 53,
            "stats": {"win": 131}
        },
        {
            "participantId": 3,
            "teamId": 100,
            "championId": 25,
            "stats": {"win": 211}
        }
    ]
}

champion_stats = dict((participant['championId'], participant['stats']) for participant in game_json['participants'])

for match in old_games_json['matches']:
    champion_id = match['champion']
    stats = champion_stats[champion_id]
    # do stuff here with stats
    print(stats)

输出

{'win': 11}
{'win': 211}
{'win': 131}

推荐阅读