2

I'm using a Django environment, and I want to pull stats from Steam. However, Steam's API is annoyingly stupid in that they have about 20 different URLs, the main two I want information from are:

I'm using the Python Requests library to GET the data from Steam.

import requests
import json
from xml.dom.minidom import parseString

STEAM_API_URL = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002'
STEAM_API_KEY = 'XXXXX'
STEAM_USERNAME = 'niteshade'

# Make request to steamcommunity.com with the username to get the 64-bit Steam ID
username_r = requests.get('http://steamcommunity.com/id/{0}/games?tab=all&xml=1'.format(STEAM_USERNAME))
steamid = str(parseString(username_r.text.encode('utf-8')).getElementsByTagName('steamID64')[0].firstChild.wholeText)
totalgames = parseString(username_r.text.encode('utf-8')).getElementsByTagName('game').length

data = {
    'key': STEAM_API_KEY,
    'steamids': steamid,
}

user_r = requests.get(STEAM_API_URL, params=data)
#user_r.json['response']['players'][0].update({'totalgames'.encode('utf-8'): totalgames})

When I query steamcommunity.com I get something like this back:

<gamesList>
    <steamID64>12345</steamID64>
    <steamID>aSteamID</steamID>
    <games>
        <game>
            <appID>201790</appID>
            <name>Orcs Must Die! 2</name>
            <logo>http://media.steampowered.com/steamcommunity/public/images/apps/201790/c345d9b205f349f0e7f4e6cdf8af4d0b7d242505.jpg</logo>
            <storeLink>http://steamcommunity.com/app/201790</storeLink>
            <hoursLast2Weeks>2.2</hoursLast2Weeks><hoursOnRecord>14.3</hoursOnRecord>
            <statsLink>http://steamcommunity.com/id/niteshade/stats/201790</statsLink>
            <globalStatsLink>http://steamcommunity.com/stats/201790/achievements/</globalStatsLink>
        </game>
        <game>
            <appID>113200</appID>
            <name>The Binding of Isaac</name>
            <logo>http://media.steampowered.com/steamcommunity/public/images/apps/113200/d9a7ee7e07dffed1700cb8b3b9482105b88cc5b5.jpg</logo>
            <storeLink>http://steamcommunity.com/app/113200</storeLink>
            <hoursLast2Weeks>0.2</hoursLast2Weeks>
            <hoursOnRecord>22.8</hoursOnRecord>
            <statsLink>http://steamcommunity.com/id/niteshade/stats/BindingOfIsaac</statsLink>
            <globalStatsLink>http://steamcommunity.com/stats/BindingOfIsaac/achievements/</globalStatsLink>
        </game>
        <game>
            <appID>19680</appID>
            <name>Alice: Madness Returns</name>
            <logo>http://media.steampowered.com/steamcommunity/public/images/apps/19680/16eb0cc15cde07377c0cb3bffa6d92bbc6dd72b2.jpg</logo>
            <storeLink>http://steamcommunity.com/app/19680</storeLink>
        </game>
    </games>

And from api.steampowered.com I get this:

{
    "response": {
        "players": [
            {
                "steamid": "12345",
                "communityvisibilitystate": 3,
                "profilestate": 1,
                "personaname": "aSteamID",
                "lastlogoff": 1351676021,
                "profileurl": "http:\/\/steamcommunity.com\/id\/aSteamID\/",
                "avatar": "http:\/\/media.steampowered.com\/steamcommunity\/public\/images\/avatars\/b2\/b261f66a17bfa6c95b24f8b4c6b58bb3776d57e4.jpg",
                "avatarmedium": "http:\/\/media.steampowered.com\/steamcommunity\/public\/images\/avatars\/b2\/b261f66a17bfa6c95b24f8b4c6b58bb3776d57e4_medium.jpg",
                "avatarfull": "http:\/\/media.steampowered.com\/steamcommunity\/public\/images\/avatars\/b2\/b261f66a17bfa6c95b24f8b4c6b58bb3776d57e4_full.jpg",
                "personastate": 4,
                "realname": "Real Name",
                "primaryclanid": "103582791429705688",
                "timecreated": 1250966723,
                "loccountrycode": "GB"
            }
        ]       
    }
}

Basically, to be able to get anything from api.steampowered.com, I need a Steam ID. To get that, I make the call to steamcommunity.com website which returns an XML file with the Steam ID, amongst other things. The information I need is as follows (using the names as in the XML/JSON responses):

Player

  • Steamid
  • Personaname
  • ProfileURL
  • Friends (Requires another API call, I believe)
  • Personastate
  • Total number of games
  • Avatarfull

Games

  • AppID
  • Name
  • Logo
  • hoursLast2Weeks

For total number of games, I thought I'd simply just count the number of <game> nodes in the XML file returned by steamcommunity.com. It worked, in that I was able to count them, but I can't seem to add a totalgames field to the JSON response from api.steampowered.com. Secondly, not all <game> nodes have <hoursLast2Weeks> child nodes, I only want the ones that do. Thirdly, I want to just get the player's friends total. I'm not kidding myself, I know I'll have to use another GET, but the problem is adding it to the JSON.

My main issue is trying to add to the JSON response, I've looked at other examples on SO, tried to follow them but I'm not sure where I'm going wrong here. Any help would be greatly appreciated.

Community
  • 1
  • 1
Hassan Khan
  • 766
  • 3
  • 9
  • 21
  • 1
    It's probably a good idea to break up your problem into separate questsions. For example, narrow the scope of this question to adding a node to JSON response. Create new questions for the second and third issues. Just a suggestion, may help simplify and improve responses. – Bryan Nov 01 '12 at 15:28
  • If anyone could just show me how to add a node to the JSON response, I'd be happy to do the rest myself. Sorry for the lengthy post, just needed to get it off my chest :) – Hassan Khan Nov 01 '12 at 15:32
  • Usually we see a very specific question with no context, which makes it difficult to help. It's refreshing to see the full explanation of a problem in your post :). Do you want the `totalgames` added to top level `response`, or one for each `players` element? – Bryan Nov 01 '12 at 15:44
  • Sorry, forgot to mention that. Yes, I would like it to add to each `player` element. – Hassan Khan Nov 01 '12 at 16:01

2 Answers2

5

Changing json data is pretty simple:

jsondata = json.loads(json_input_string)
jsondata['newkey'] = new_value
json_output_string = json.dumps(jsondata)
cwied
  • 96
  • 2
  • Already tried that, the last line of the Python code that's commented out was supposed to be doing that: ``user_r.json['response']['players'][0].update({'totalgames'.encode('utf-8'): totalgames})`` I have also tried ``user_r.json['response']['players'][0]['totalgames'] = totalgames`` too – Hassan Khan Nov 01 '12 at 16:02
1

To satisfy adding totalgames to each element in players response:

import json
response = '{"response": {"players": [{"steamid": "12345","communityvisibilitystate": 3,"profilestate": 1,"personaname": "aSteamID","lastlogoff": 1351676021,"profileurl": "http:\/\/steamcommunity.com\/id\/aSteamID\/","avatar": "http:\/\/media.steampowered.com\/steamcommunity\/public\/images\/avatars\/b2\/b261f66a17bfa6c95b24f8b4c6b58bb3776d57e4.jpg","avatarmedium": "http:\/\/media.steampowered.com\/steamcommunity\/public\/images\/avatars\/b2\/b261f66a17bfa6c95b24f8b4c6b58bb3776d57e4_medium.jpg","avatarfull": "http:\/\/media.steampowered.com\/steamcommunity\/public\/images\/avatars\/b2\/b261f66a17bfa6c95b24f8b4c6b58bb3776d57e4_full.jpg","personastate": 4,"realname": "Real Name","primaryclanid": "103582791429705688","timecreated": 1250966723,"loccountrycode": "GB"}]}}'
data = json.loads(response)
for player in data["response"]["players"]:
    # add code to get game count by player here                  
    # set to zero for this example
    totalgames = 0
    player["totalgames"] = totalgames

print json.dumps(data, sort_keys=True, indent=4)
Bryan
  • 17,112
  • 7
  • 57
  • 80
  • Quick question: Why is there an 'r' preceding the JSON? Also, data is supposed to be of type `dict`, and the code you gave me works fine on its own. When I try it with my own code, it still does nothing. I checked to see if the response is returned as a type `dict`, and it is as well. – Hassan Khan Nov 01 '12 at 16:55
  • Got it to work :) Turns out the response object can't be changed. What you want to do is receive the input as a string and then use ``json.loads`` on it. You **cannot** modify the response directly (even if you make it return a JSON by using ``response.json``) – Hassan Khan Nov 01 '12 at 17:20
  • See [this answer](http://stackoverflow.com/questions/2081640/what-exactly-do-u-and-rstring-flags-in-python-and-what-are-raw-string-litte) for explanation of `r'...'`. In looking at the response, the backslashes in URLs are already escaped, so it's not required. I've removed it from the example. – Bryan Nov 01 '12 at 18:18