I am trying to make an API call that pulls the value of a column within a spreadsheet and sends it as a param within the API call.
I've done this successfully before with this code, but that was for integer values. Now I need to do it with text and they are stored as Dict values which give me an error.
Here is what I'm trying to use:
for i in range(10):
r = requests.post(
url = "DummyAPIEndpoint",
headers = {
'Authorization': 'ApiKey DummyKey',
'Content-Type' : 'application/json'
},
params = {
{
'data' : mt.iloc [i,0]
}
}
)
print(r)
When my values are all integers, the mt.iloc [i,0] pulls every entry in the first column and fires an API call with that value under 'data'. However, since this content is text, I get the error:
TypeError: unhashable type: 'dict'
I understand why I'm getting this error, I'm just not sure what to do about it.
How can I add the text value of the column within the spreadsheet as the param "data"?
The code has params in an extra set of braces.
This is interpreted as a dict.
You don't want that.
You'll want to remove the extra braces like this:
for i in range(10):
r = requests.post(
url = "DummyAPIEndpoint",
headers = {
'Authorization': 'ApiKey DummyKey',
'Content-Type' : 'application/json'
},
params = {
'data' : mt.iloc [i,0]
}
)
print(r)
Related
Trying to retrieve data via the EIA data API (v2): https://www.eia.gov/opendata/documentation.php.
I'm able to use the API dashboard to return data:
https://www.eia.gov/opendata/browser/electricity/retail-sales?frequency=monthly&data=price;revenue;sales;&start=2013-01
But when I attempt to retrieve within Python using the attached documentation, I don't appear to be returning any values when using the same parameters.
url = 'https://api.eia.gov/v2/electricity/retail-sales/data/?api_key=' + API_KEY
params = {
"frequency": "monthly",
"data": [
"revenue",
"sales",
"price"
],
"start": "2013-01"
}
if x.status_code == 200:
print('Success')
else:
print('Failed')
res = x.json()['response']
data = res['data']
If I print the url created by the GET method, and compare to API url included in the dashboard, the issue appears to be in the way the GET method is attempting to retrieve items from the data parameter:
Works
https://api.eia.gov/v2/electricity/retail-sales/data/?frequency=monthly&data[0]=price&data[1]=revenue&data[2]=sales&start=2013-01&sort[0][column]=period&sort[0][direction]=desc&offset=0&length=5000
Doesn't work (returned by GET method):
https://api.eia.gov/v2/electricity/retail-sales/data/?api_key=MY_API&frequency=monthly&data=revenue&data=sales&data=price&start=2013-01
Can anyone provided guidance on how to coerce the GET method to pass my data parameters in the same way as the API dashboard appears to?
Your data in params not formatted correctly in url. Try this if you want the url to be formed as in your working version:
url = 'https://api.eia.gov/v2/electricity/retail-sales/data/?api_key=' + API_KEY
data = [
"revenue",
"sales",
"price"
]
params = {
"frequency": "monthly",
"start": "2013-01"
}
for index in range(0, len(data)):
params[f"data[{index}]"] = data[index]
response = requests.get(url, params = params)
But if the server is adequate, then square brackets in the name of the data[] parameter are enough:
url = 'https://api.eia.gov/v2/electricity/retail-sales/data/?api_key=' + API_KEY
params = {
"frequency": "monthly",
"data[]": [
"revenue",
"sales",
"price"
],
"start": "2013-01"
}
JSON return from spotify api. Example:
{
"tracks": {
"href": "https://api.spotify.com/v1/search?query=Stero+Hearts&type=track&offset=0&limit=1",
"items": [
{
"album": {
"album_type": "album",
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/4IJczjB0fJ04gs4uvP0Fli"
},
"href": "https://api.spotify.com/v1/artists/4IJczjB0fJ04gs4uvP0Fli",
"id": "4IJczjB0fJ04gs4uvP0Fli",
"name": "Gym Class Heroes",
"type": "artist",
"uri": "spotify:artist:4IJczjB0fJ04gs4uvP0Fli"
}
]
}
}
]
}
}
Broken Code
import requests, json
spotifytrack = input("Name of Song?\\n")
link = "https://api.spotify.com/v1/search?q=" + spotifytrack + "&type=track&limit=1"
token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
header = {
"Authorization": "Bearer {}".format(token),
"Content-Type": "application/json",
"Accept": "application/json",
}
auth_response = requests.get(link, headers=header)
pretty_response = json.dumps(auth_response.json(), indent=4)
data_by_user = {}
for d in auth_response:
data_by_user[d["artist"]] = d
print(data_by_user["uri"])
"""
def find_track_from_json(auth_response, artist):
return [p for p in auth_response if p["artist"] == artist][0]["uri"]
urii = find_track_from_json(auth_response, "uri")
print(urii)
x = load.json(auth_response.json())
print("Here is the data whic we have imported\n")
print(pretty_response)
print(x["name"])
print(x["uri"])
print(x["spotify"])
"""
Errors noticed:
File "spotify.py", line 19, in <module>
data_by_user[d["artist"]] = d
TypeError: byte indices must be integers or slices, not str
The aim is to convert word search to link in a cli application.
I tried load.json which i saw in some website and also tried def.
I expected the program to find out the artist name and uri from the json and print it in the cli interface.
You are iterating over the encoded json string:
auth_response = requests.get(link, headers=header)
for d in auth_response:
Python is complaining that you aren't providing a numerical index, which is correct as auth_response is just a string!
You should call json.loads to decode the string, and then you can iterate over it.
auth_response = requests.get(link, headers=header)
decoded_auth_response = json.loads(auth_response)
data_by_user = {}
for d in decoded_auth_response:
data_by_user[d["artist"]] = d
As you haven't provided the full json output from the API call I'm not sure what data is actually in decoded_auth_response, and you haven't described what your expected output would look like, so you may need to do some more work to find the correct data in each iteration.
The result from requests.get() is a requests.Response object. As far as I can see you want to iterate over the response body which is JSON. The requests.Response object has a .json() method which returns a dict from the response JSON.
Looking at the response you would probably want to iterate over resp_json['tracks']['items'] which is a list.
So to summarize your code should look something like this:
auth_response = requests.get(link, headers=header)
items = auth_response.json()['tracks']['items']
for d in items:
print(d)
I'm getting a JSON data from RESTCONF HTTPS request, using the following code
https_request = 'https://' + host + '/restconf/data/' + operation
headers = {'Content-type': 'application/yang-data+json', 'Accept': 'application/yang-data+json'}
r = requests.get(https_request, auth=(user, password), headers=headers, verify=False)
print r.json()
The data I got is the following:
{
"Cisco-IOS-XE-segment-routing:ipv4": {
"prefixes": [
{
"ipprefix": "1.1.1.1/32",
"index": {
"range-start": 333,
"range": 1
}
}
]
}
}
Basically, I want to return the field's "range-start" value which is 333. I tried the following but it did not work.
for element in r:
id = element['range-start']
print(id)
Is there anyway to get that value?
From Python Console:
>>> import json
... data = json.loads('{"Cisco-IOS-XE-segment-routing:ipv4": {"prefixes": [{"ipprefix": "1.1.1.1/32", "index": {"range-start": 333, "range": 1}}]}}')
... print(data['Cisco-IOS-XE-segment-routing:ipv4']['prefixes'][0]['index']['range-start'])
333
>>>
You need to start at the beginning of the JSON and work your way to the key you want. To do this you need to start at Cisco-IOS-XE-segment-routing:ipv4.
prefixes = r.json()["Cisco-IOS-XE-segment-routing:ipv4"]["prefixes"]
id = prefixes[0]["index"]["range-start"]
If there are multiple prefixes you can loop over them and access each range-start.
Since you are looping over elements, I would suggest this approach using a helper function:
def get_id(element):
prefixes = r.json()["Cisco-IOS-XE-segment-routing:ipv4"]["prefixes"]
id = prefixes[0]["index"]["range-start"]
return id
Then you can do, as in your question:
for element in r:
id = get_id(element)
print(id)
Here's my function which connects to an API:
def order_summary():
"""Get order summary for a specific order"""
# Oauth2 params
headerKey = api_login()
headers = {'Authorization': headerKey}
# Payload params
payloadOrderSum = {
"domainId": 15,
"domainName": "SGL",
"orderId": 3018361
}
# API response
orderSumResp = requests.post(url + "order/summary", data=payloadOrderSum, headers=headers)
print(orderSumResp.content)
The API expects a JSON array as Payload Params which essentially looks like that:
[
{
"domainId": 0,
"domainName": "string",
"orderId": 0
}
]
The other endpoints I coded for on this API didn't need for the params to be an array so I could just use them as is and send them as a dictionary and it worked.
I've tried a couple things using the JSON library but I can't seem to get it to work. I saw that the JSonEncoder converts lists and tuples to JSON arrays but I couldn't figure it out.
Not sure what other info I could provide but just ask if there are any.
Thanks!
Wrap payloadOrderSum into a list:
payloadOrderSum = {
"domainId": 15,
"domainName": "SGL",
"orderId": 3018361
}
orderSumResp = requests.post(url + "order/summary", json=[payloadOrderSum], headers=headers)
Note that I used json kwarg instead of data (added in version 2.4.2).
dump your dict with json.dumps requests-doc
r = requests.post(url, data=json.dumps(payload))
It could help if you specify what you tried with the JSON library.
However, you might wanna try this if you haven't already done so:
import json
payloadOrderSum = json.dumps(
{
"domainId": 15,
"domainName": "SGL",
"orderId": 3018361
}
)
I am trying to automate some queries to a API using Python. The problem is that the request needs to be created in a special way, and I just cant make it work. This is the part of the string I am having problems creating.
payload = "{\n \"filter\": {\n \"name\":[\"name1\", \"name2\"]\n }"
Where name1 and name2 is variable and is created from a list. The way I tried to do it was just to first create a function to create the
[\"name1\", \"name2\"]
This is the function
def create_string(list_of_names):
#Creates the string of line items we want data from
start = '[\\"%s\\"' % list_of_names[0]
for i in list_of_names[1 : ]:
start += ', \\"%s\\"' %(i)
start += "]"
return start
list_of_names = ['name1', 'name2']
And then just using the %s part to add it into the string.
payload = "{\n \"filter\": {\n \"name\":%s\n }" % create_string(list_of_names)
This doesnt work, and I can think this has something to do with how the \ is used in Python.
The create_string function creates different output depening on if I am printing it or not.
a = create_string(list_of_names)
print(a)
Creates the string I need to pass in using %s
[\"name1\", \"name2\", \"name3\"]
And just a outputs
'[\\"name1\\", \\"name2\\", \\"name3\\"]'
So my problem is then how to pass the print(a) part into the payload string. Does anyone have some sort of solution to this?
Instead of creating your payload by hand, first create a python dictionary and use the json-module to convert it to a string:
payload = {"filter": {"name": list_of_names]}}
payload = json.dumps(payload)
or with your more complex dictionary:
payload = {
"filter": {
"date": "pastThirtyDays",
"lineitem": {
"buyType": "RTB",
"name": list_of_names,
}
},
"metrics": ["cost"],
"dimensions": ["date", "lineItem"],
}
payload = json.dumps(payload)