Using the data for 'requests' module in python - python

I am able to load in some weather data from the requests module for python with the following code:
from pprint import pprint
import requests
r = requests.get('http://api.openweathermap.org/data/2.5/weather?q=London')
pprint(r.json())
But how do I actually use the data it produces? I cannot for the life of me find the relevant documentation or tutorial on how to do this. this is the output of the pprint:
{u'base': u'cmc stations',
u'clouds': {u'all': 0},
u'cod': 200,
u'coord': {u'lat': 42.98, u'lon': -81.23},
u'dt': 1397676977,
u'id': 6058560,
u'main': {u'humidity': 25,
u'pressure': 1024,
u'temp': 278,
u'temp_max': 283.15,
u'temp_min': 275.37},
u'name': u'London',
u'rain': {u'1h': 0.25},
u'snow': {u'3h': 0},
u'sys': {u'country': u'CA',
u'message': 0.0467,
u'sunrise': 1397644810,
u'sunset': 1397693338},
u'weather': [{u'description': u'light rain'
u'icon': u'10d',
u'id': 500,
u'main': u'Rain'}],
u'wind': {u'deg': 168.001, u'speed': 3.52}}
How could I address an item within the list? For example to print just the temp on it's own and maybe to use it as a variable. E.g.:
temp = *not sure what to put here*
print temp

Now that you have the results:
results = r.json()
just access it like any other Python dict:
main = results['main'] # Get the 'main' key's value out of results
temp = main['temp'] # Get the 'temp' key's value out of main
print temp
or more tersely (and the way you'd almost always write this in real life):
print results['main']['temp']

Related

Convert JSON to CSV with Python 3

I need to get some data from the Meetup API, convert the JSON I get into a CSV, all of that in Python 3. I've never worked with JSON or Python, so I've run into some issues. Getting the data is not a problem, but I can't seem to parse the JSON object into a proper CSV file. My code, anonymized:
import json
import requests
import csv
def main():
# initialize variables
output_file = 'result_meetup.csv'
api_key = "YOUR_MEETUP_API_KEY"
params = {'key': api_key}
url_path = 'http://api.meetup.com/pro/:URLNAME/groups'
# get data from API, parse to JSON
data = requests.get(url_path, params=params)
data_parsed = data.json()
length_data = len(data_parsed) - 1
data_to_file = open(output_file, 'w')
csv_writer = csv.writer(data_to_file)
for i in range(0, length_data):
meetup = data_parsed[i]
csv_writer.writerow([meetup])
data_to_file.close()
if __name__ == "__main__":
main()
Now, as you can see, I write into the CSV as a list. This leads to a really ugly output, looking like this (again, the values in caps are anonymized):
{u'rsvps_per_event': 0.0, u'organizers': [{u'permission': u'organizer', u'name': u'NAME', u'member_id': ID}], u'repeat_rsvpers': 0, u'topics': [{u'lang': u'en_US', u'id': ID, u'urlkey': u'socialnetwork', u'name': u'Social Networking'}, {u'lang': u'en_US', u'id': ID, u'urlkey': u'education', u'name': u'Education'}, {u'lang': u'en_US', u'id': ID, u'urlkey': u'newtech', u'name': u'New Technology'}, {u'lang': u'en_US', u'id': ID, u'urlkey': u'business-referral-networking', u'name': u'Business Referral Networking'}], u'upcoming_events': 0, u'gender_female': 0.3499999940395355, u'pro_join_date': DATE, u'id': ID, u'category': [{u'shortname': u'career-business', u'sort_name': u'Career & Business', u'id': 2, u'name': u'Career & Business'}], u'city': u'CITY', u'member_count': 73, u'lon': LON, u'organizer_photo': {u'thumb_link': u'LINK.JPEG', u'base_url': u'URL', u'id': ID, u'type': u'member', u'photo_link': u'LINK.JPEG', u'highres_link': u'LINK.JPEG'}, u'average_age': 35.555599212646484, u'status': u'Active', u'description': u'DESCRIPTION' u'founded_date': DATE, lat': LAT, u'urlname': u'NAME', u'gender_male': 0.6000000238418579, u'name': u'NAME', u'country': u'Portugal', u'gender_unknown': 0.05000000074505806, u'past_events': 0, u'gender_other': 0.0, u'past_rsvps': 0}
So basically, the whole JSON object in a single CSV field, with weird 'u's, in lists and so on. However, if I don't write it as a list, I only get the fields of the JSON object, without the data, so it would just be 'Organizers', 'Name' etc, without the actual name.
As I said, I am a python beginner and haven't found any libraries to help me with it, but I'm sure they exist. Any help is really appreciated, and it would be great if it was Python3 compatible.
Edit: What I would like it to look like in the end:
I get multiple Meetup groups in the reply, all having the same structure as shown above. Therefore, the description of the value should be listed just once, as a header, and the values listed beneath (new lines and pipes indicating a new field of a csv sheet):
RSVPs_per_event | Organizer | ID
5 | Tom | 1
20 | Jack | 2
35 | Anne | 3
To convert the json data to csv you need to extract keys and write them in header and then work on the values. This might help you:
data_parsed = json.loads(Data)
header = data_parsed[0].keys()
csv_writer.writerow(header)
for i in range(0,length_data)
meetup = data_parsed[i].values()
csv_writer.writerow([meetup])
If anyone else has the same problem, I solved it, not very elegantly, but I needed the data. The JSON was too nestled and complex to parse, so now I just read the fields I need from the data.
import json
import requests
import csv
def main():
# initialize variables
output_file = 'result_meetup.csv'
api_key = "YOUR_API_KEY"
params = {'key': api_key}
url_path = 'http://api.meetup.com/pro/:URLNAME/groups'
# get data from API, parse to JSON
data = requests.get(url_path, params=params)
data_parsed = data.json()
length_data = len(data_parsed) - 1
data_to_file = open(output_file, 'w', newline='')
csv_writer = csv.writer(data_to_file, delimiter=";")
csv_writer.writerow(["id","name","city","country","member count","average age","founded_date","past_rsvps","rsvps_per_event","repeat_rsvpers","gender_unknown","gender_female","gender_male","gender_other"])
for i in range(0, length_data):
meetup = data_parsed[i]
id = meetup['id']
name = meetup['name']
city = meetup['city']
country = meetup['country']
member_count = meetup['member_count']
average_age = meetup['average_age']
founded_date = meetup['founded_date']
past_rsvps = meetup['past_rsvps']
rsvps_per_event = meetup['rsvps_per_event']
repeat_rsvpers = meetup['repeat_rsvpers']
gender_unknown = meetup['gender_unknown']
gender_female = meetup['gender_female']
gender_male = meetup['gender_male']
gender_other = meetup['gender_other']
csv_writer.writerow([id,name,city,country,member_count,average_age,founded_date,past_rsvps,rsvps_per_event,repeat_rsvpers,gender_unknown,gender_female,gender_male,gender_other])
data_to_file.close()
if __name__ == "__main__":
main()

python 2.7 urllib2.Request KeyError

I'm successfully filling a json.load(response) request and able to navigate/see the result and appears to be what I am expecting. However, I'm getting a KeyError as I try to access attributes. In this instance I need to set a local variable to the "SHORT_NAME" attribute.
{u'fieldAliases': {u'SHORT_NAME': u'SHORT_NAME', u'OBJECTID':
u'OBJECTID'}, u'fields': [{u'alias': u'OBJECTID', u'type':
u'esriFieldTypeOID', u'name': u'OBJECTID'}, {u'alias': u'SHORT_NAME',
u'length': 50, u'type': u'esriFieldTypeString', u'name':
u'SHORT_NAME'}], u'displayFieldName': u'LONG_NAME', u'features':
[{u'attributes': {u'SHORT_NAME': u'Jensen Beach to Jupiter Inlet',
u'OBJECTID': 17}}]}
My python code to access the above:
reqAp = urllib2.Request(queryURLAp, paramsAp)
responseAp = urllib2.urlopen(reqAp)
jsonResultAp = json.load(responseAp) #all good here! above example is what this contains
#trying to set variable to the SHORT_NAME attribute
for featureAp in jsonResultAp['features']:
aqp = feature['attributes']['SHORT_NAME']
#this fails with: "KeyError: 'SHORT_NAME'"
It's obvious that "SHORT_NAME" is there so I'm not quite sure what I'm doing incorrectly.
Thanks for any feedback!
Change:
aqp = feature['attributes']['SHORT_NAME']
To:
aqp = featureAp['attributes']['SHORT_NAME']

Storing Python dictionary data into a csv

I have a list of dicts that stores Facebook status data (Graph API):
len(test_statuses)
3
test_statuses
[{u'comments': {u'data': [{u'created_time': u'2016-01-27T10:47:30+0000',
u'from': {u'id': u'1755814687982070', u'name': u'Fadi Cool Panther'},
u'id': u'447173898813933_447182555479734',
u'message': u'Sidra Abrar'}],
u'paging': {u'cursors': {u'after': u'WTI5dGJXVnVkRjlqZFhKemIzSTZORFEzTVRneU5UVTFORGM1TnpNME9qRTBOVE00T1RFMk5UQT0=',
u'before': u'WTI5dGJXVnVkRjlqZFhKemIzSTZORFEzTVRneU5UVTFORGM1TnpNME9qRTBOVE00T1RFMk5UQT0='}},
u'summary': {u'can_comment': False,
u'order': u'ranked',
u'total_count': 1}},
u'created_time': u'2016-01-27T10:16:56+0000',
u'id': u'5842136044_10153381090881045',
u'likes': {u'data': [{u'id': u'729038357232696'},
{u'id': u'547422955417520'},
{u'id': u'422351987958296'},
{u'id': u'536057309903473'},
{u'id': u'206846772999449'},
{u'id': u'1671329739783719'},
{u'id': u'991398107599340'},
{u'id': u'208751836138231'},
{u'id': u'491047841097510'},
{u'id': u'664580270350825'}],
u'paging': {u'cursors': {u'after': u'NjY0NTgwMjcwMzUwODI1',
u'before': u'NzI5MDM4MzU3MjMyNjk2'},
u'next': u'https://graph.facebook.com/v2.5/5842136044_10153381090881045/likes?limit=10&summary=true&access_token=521971961312518|121ca7ef750debf4c51d1388cf25ead4&after=NjY0NTgwMjcwMzUwODI1'},
u'summary': {u'can_like': False, u'has_liked': False, u'total_count': 13}},
u'link': u'https://www.facebook.com/ukbhangrasongs/videos/447173898813933/',
u'message': u'Track : Ik Waar ( Official Music Video )\nSinger : Falak shabir ft DJ Shadow\nMusic by Dj Shadow\nFor more : UK Bhangra Songs',
u'shares': {u'count': 7},
u'type': u'video'},
{u'comments': {u'data': [],
u'summary': {u'can_comment': False,
u'order': u'chronological',
u'total_count': 0}},
u'created_time': u'2016-01-27T06:15:40+0000',
u'id': u'5842136044_10153380831261045',
u'likes': {u'data': [],
u'summary': {u'can_like': False, u'has_liked': False, u'total_count': 0}},
u'message': u'I want to work with you. tracks for flicks',
u'type': u'status'}]
I need to extract each status text and the text of each comment under the status, which I can do by appending them to separate lists e.g.,:
status_text = []
comment_text = []
for s in test_statuses:
try:
status_text.append(s['message'])
for c in s['comments']['data']:
comment_text.append(c['message'])
except:
continue
This gives me two lists of separate lengths len(status_text) = 2, len(comment_text) = 49.
Unfortunately that's a horrible way of dealing with the data since I cannot keep track of what comment belongs to what status. Ideally I would like to store this as a tree structure and export in into a cvs file, but I can't figure out how to do it.
Probable data acv data structure:
Text is_comment
status1 0
status2 0
statusN 0
comment1 status1
comment2 status1
commentN statusN
Why do you need this to be in a CSV? It is already structured and ready to be persisted as JSON.
If you really need the tabular approach offered by CSV, then you have to either denormalize it, or use more than one CSV table with references from one to another (and again, the best approach would be to put the data in an SQL database which takes care of the relationships for you)
That said, the way to denormalize is simply to save the same status text to each row where a comment is - that is: record you CSV row in the innermost loop with your approach:
import csv
status_text = []
comment_text = []
writer = csv.writer(open("mycsv.csv", "wt"))
for s in test_statuses:
test_messages.append(s['message'])
for c in s['comments']['data']:
test_comments.append(c['message'])
writer.writerow((s['message'], c['message']))
Note that you'd probably be better by writing the status idto each row, and create a second table with the status message where the id is the key (and put it in a database instead of various CSV files). And then, again, you are probably better of simply keeping the JSON. If you need search capabilities, use a JSON capable database such as MongoDB or PostgreSQL

"TypeError: string indices must be integers not str" seting a var from a dictionary key

I grab info from an API call that comes in the form of a dictionary. I need to grab a specific key and set a variable to it. Easy enough but observe. The code below is only to the processes involved.
totalEntries = 0 # global var
api_data = requests.get(apiEndpoint).json()
def populateVars():
global totalEntries
totalEntries = api_data['total_entries']
output of the api_data just for giggles:
{u'per_page': 100, u'total_entries': 1, u'current_page': 1, `u'restaurants': [{u'city': u'Abilene', u'reserve_url': u'http://www.opentable.com/single.aspx?rid=152869', u'name': u'Copper Creek Fine Texas Dining', u'area': u'Dallas - Fort Worth', u'country': u'US', u'price': 2, u'phone': u'3256924424', u'state': u'TX', u'postal_code': u'79602', u'address': u'4401 Loop 322', u'lat': 32.397913, u'image_url': u'https://www.opentable.com/img/restimages/152869.jpg', u'lng': -99.716776, u'mobile_reserve_url': u'http://mobile.opentable.com/opentable/?restId=152869', u'id': 152869}]}`
and again the error:
totalEntries = api_data['total_entries']
TypeError: string indices must be integers, not str
Why is this happening? What is the fix?
As jonsharpe already pointed out, your api_data is a string, which can only be indexed by integers.
Instead of using:
api_data = requests.get(apiEndpoint).json()
consider using json.load:
resp = requests.get(apiEndpoint)
api_data = json.loads(resp.text)

Can't get dictionary value from key in unicode dictionary

The following code stores a unicode dictionary in the variable webproperties_list:
webproperties_list = service.management().webproperties().list(
accountId='~all').execute()
profile_id = webproperties_list.get(u'defaultProfileId')
print profile_id
For some reason the .get() on the key of u'defaultProfileId' is giving me None, even though I know it is in the response. I also tried the get without the u and I still get a None response:
profile_id = webproperties_list.get('defaultProfileId')
Do I need to do something to the dict before I get the value from the key, or am I doing something else wrong entirely?
UPDATE:
Here is the response I get:
{u'username': u'removed', u'kind': u'analytics#webproperties', u'items': [{u'profileCount': 1, u'kind': u'analytics#webproperty', u'name': u'removed', u'level': u'STANDARD', u'defaultProfileId': u'removed'.....
I need to retrieve the value of u'defaultProfileId'
Not really sure how to get a value from a key that is in a dict within a list within a dict...
To figure out how to access it, it sometimes helps to go step by step:
>>> d
{u'username': u'removed', u'items': [{u'profileCount': 1, u'defaultProfileId': u'removed', u'kind': u'analytics#webproperty', u'name': u'removed', u'level': u'STANDARD'}], u'kind': u'analytics#webproperties'}
>>> d['items']
[{u'profileCount': 1, u'defaultProfileId': u'removed', u'kind': u'analytics#webproperty', u'name': u'removed', u'level': u'STANDARD'}]
>>> d['items'][0]
{u'profileCount': 1, u'defaultProfileId': u'removed', u'kind': u'analytics#webproperty', u'name': u'removed', u'level': u'STANDARD'}
>>> d['items'][0]['defaultProfileId']
u'removed'

Categories

Resources