My problem is the following: I've a list of Ips that I sorted in an nparray (ip_array), then I wanna do a multiple request with all of them and saving the outputs in a single json. (the APIKEY is really the api key in the code xD)
url_auth = 'https://api.ipgeolocation.io/ipgeo?apiKey=APIKEYAPIKEYAPIKEY='
for i in np.arange(1,4):
r[i] = requests.request(method='get',url=url_auth,params={'ips':ip_array[i]}) #i tested the single request and it works in this way.
But then, i got
TypeError: 'Response' object does not support item assignment
And then, i tried replacing the last line with
r = requests.request(method='get',url=url_auth,params={'ips':ip_array[i]})
But, when i do
r.json()
I only get the last request (that is obvious).
Store response on every iteration:
url_auth = 'https://api.ipgeolocation.io/ipgeo?apiKey=APIKEYAPIKEYAPIKEY='
responses = []
for i in np.arange(1,4):
response = requests.request(method='get',url=url_auth,params={'ips':ip_array[i]})
responses.append(response.json())
responses list will contain all response objects.
Related
I have a list of LinkedIn posts IDs. I need to request share statistics for each of those posts with another request.
The request function looks like this:
def ugcp_stats(headers):
response = requests.get(f'https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&ugcPosts=List(urn%3Ali%3AugcPost%3A{shid},urn%3Ali%3AugcPost%3A{shid2},...,urn%3Ali%3AugcPost%3A{shidx})', headers = headers)
ugcp_stats = response.json()
return ugcp_stats
urn%3Ali%3AugcPost%3A{shid},urn%3Ali%3AugcPost%3A{shid2},...,urn%3Ali%3AugcPost%3A{shidx} - these are the share urns. Their number depends on number of elements in my list.
What should I do next? Should I count the number of elements in my list and somehow amend the request URL to include all of them? Or maybe I should loop through the list and make a separate request for each of the elements and then append all the responses in one json file?
I'm struggling and I'm not quite sure how to write this. I don't even know how to parse the element into the request. Although I suspect it could look something like this:
for shid in shids:
def ugcp_stats(headers):
response = requests.get(f'https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&ugcPosts=List(urn%3Ali%3AugcPost%3A & {shid})', headers = headers)
ugcp_stats = response.json()
return ugcp_stats
UPDATE - following your ansers
The code looks like this now:
link = "https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&ugcPosts=List"
def share_stats(headers, shids):
# Local variable
sample = ""
# Sample the shids in the right pattern
for shid in shids: sample += "urn%3Ali%3AugcPost%3A & {},".format(shid)
# Get the execution of the string content
response = eval(f"requests.get('{link}({sample[:-1]})', headers = {headers})")
# Return the stats
return response.json()
if __name__ == '__main__':
credentials = 'credentials.json'
access_token = auth(credentials) # Authenticate the API
headers = headers(access_token) # Make the headers to attach to the API call.
share_stats = share_stats(headers) # Get shares
print(share_stats)
But nothing seems to be happening. It finishes the script, but I don't get anything. What's wrong?
This is just a proof of what I told you earlier as comment. Now you will adapt to your needs (even I try it to do it for you) :)
Updated - Base on your feedback.
#// IMPORT
#// I'm assuming your are using "requests" library
#// PyCharm IDE show me like this library is not used, but "eval()" is using it
import requests
#// GLOBAL VARIABLES
link: str = "https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&ugcPosts=List"
#// Your function logic updated
def share_stats(sheds: list, header: dict) -> any:
# Local variable
sample = ""
# Sample the sheds in the right pattern
for shed in sheds: sample += "urn%3Ali%3AugcPost%3A & {},".format(shed)
# Get the execution of the string content
response = eval(f"requests.get('{link}({sample[:-1]})', headers = {header})")
# Return the stats as JSON file
return response.json()
#// Run if this is tha main file
if __name__ == '__main__':
#// An empty sheds list for code validation
debug_sheds: list = []
credentials: str = "credentials.json"
#// For me I get an unresolved reference for "auth", for you shod be fine
#// I'm assuming is your function for reading the file content and convert it to Python
access_token = auth(credentials) # Authenticate the API
#// Your error was from this script line
#// Error message: 'TypedDict' object is not callable
#// Your code: headers = headers(access_token)
#// When you want to get a dictionary value by a key use square brackets
headers = headers[access_token] # Make the headers to attach to the API call.
#// Here you shood ged an error/warning because you do not provided the sheds first time
#// Your code: share_stats = share_stats(headers)
share_stats = share_stats(debug_sheds, headers) # Get shares
print(share_stats)
Hello everyone here is a snippet of my nested json Response.
https://pastebin.com/qTk21iwX
What I want to accomplished to get all the "Row" data from this json response but I have yet to figure out the correct method of approaching this.
This is what I have tried is:
response = requests.get(url, headers=headers, json={"script": sql}, verify=verify).json()
print(response)
responseobject = json.dumps(response)
print(responseobject)
for object in responseobject['Result']['Results']:
print (object)
My output after running this code
TypeError: string indices must be integers
Any suggestions ?
responseobject = json.dumps(response)
Here you are turning the response object into a string. So when you do responseobject['Result'], you are indexing a string, not a dictionary.
To fix the problem, just remove responseobject = json.dumps(response) and do response['Result']['Results'] instead of responseobject['Result']['Results'].
I am trying to access an API from this website. (https://www.eia.gov/opendata/qb.php?category=717234)
I am able to call the API but I am getting only headers. Not sure if I am doing correctly or any additions are needed.
Code:
import urllib
import requests
import urllib.request
locu_api = 'WebAPI'
def locu_search(query):
api_key = locu_api
url = 'https://api.eia.gov/category?api_key=' + api_key
locality = query.replace(' ', '%20')
response = urllib.request.urlopen(url).read()
json_obj = str(response, 'utf-8')
data = json.loads(json_obj)
When I try to print the results to see whats there in data:
data
I am getting only the headers in JSON output. Can any one help me figure out how to do extract the data instead of headers.
Avi!
Look, the data you posted seems to be an application/json response. I tried to reorganize your snippet a little bit so you could reuse it for other purposes later.
import requests
API_KEY = "insert_it_here"
def get_categories_data(api_key, category_id):
"""
Makes a request to gov API and returns its JSON response
as a python dict.
"""
host = "https://api.eia.gov/"
endpoint = "category"
url = f"{host}/{endpoint}"
qry_string_params = {"api_key": api_key, "category_id": category_id}
response = requests.post(url, params=qry_string_params)
return response.json()
print(get_categories_data(api_key=API_KEY, category_id="717234"))
As far as I can tell, the response contains some categories and their names. If that's not what you were expecting, maybe there's another endpoint that you should look for. I'm sure this snippet can help you if that's the case.
Side note: isn't your API key supposed to be private? Not sure if you should share that.
Update:
Thanks to Brad Solomon, I've changed the snippet to pass query string arguments to the requests.post function by using the params parameter which will take care of the URL encoding, if necessary.
You haven't presented all of the data. But what I see here is first a dict that associates category_id (a number) with a variable name. For example category_id 717252 is associated with variable name 'Import quantity'. Next I see a dict that associates category_id with a description, but you haven't presented the whole of that dict so 717252 does not appear. And after that I would expect to see a third dict, here entirely missing, associating a category_id with a value, something like {'category_id': 717252, 'value': 123.456}.
I think you are just unaccustomed to the way some APIs aggressively decompose their data into key/value pairs. Look more closely at the data. Can't help any further without being able to see the data for myself.
I'm trying to pass a variable to the data field in requests.post() and I continue to get the error,
Error Response: {'error': {'message': 'Exception while reading request',
'detail': 'Cannod decode: java.io.StringReader#1659711'}, 'status': 'failure'}
Here is my code
#Fill array from CSV
temp=[]
for row in csv.iterrows():
index, data = row
temp.append(data.tolist())
#Create new asset for all assets in CSV
for index, row in enumerate(temp):
make = temp[index][0]
serial = str(temp[index][1])
date = str(temp[index][2])
response = requests.post(url, auth=(user, pwd), headers=headers,
data='{"asset_tag":"test1", "assigned_to":"test2",
"company":"test3", "serial_number":serial}')
I originally tried feeding it directly from the CSV using
str(temp[index][1])
This did not work, so I tried assigning str(temp[index][1]) to the variable serial and then passing the variable like that but that also results in the same error.
A point in the right direction would be great, thanks!
Instead of sending the request payload body in string, pass it in json form.
requests.post accepts string in data variable and json in json variable. I faced a same issue while trying to make my first REST call to ServiceNow instance via Python. Hope this helps.
response = requests.post(url, auth=(user, pwd), headers=headers,
json={"asset_tag":"test1", "assigned_to":"test2",
"company":"test3", "serial_number":serial})
Remove the single quotes from the following :
data='{"asset_tag":"test1", "assigned_to":"test2",
"company":"test3", "serial_number":serial}'
Use
data = {"asset_tag":"test1", "assigned_to":"test2",
"company":"test3", "serial_number":serial}
rather than passing data=data, take data as dict and pass it as json=data.
This question already has answers here:
HTTP requests and JSON parsing in Python [duplicate]
(8 answers)
Closed 7 years ago.
I am creating a Django web app.
There is a function which creates a JSON response like this:
def rest_get(request, token):
details = Links.get_url(Links, token)
result={}
if len(details)>0:
result['status'] = 200
result['status_message'] = "OK"
result['url'] = details[0].url
else:
result['status'] = 404
result['status_message'] = "Not Found"
result['url'] = None
return JsonResponse(result)
And I get the response in the web browser like this:
{"status": 200, "url": "http://www.bing.com", "status_message": "OK"}
Now from another function I want to consume that response and extract the data out of it. How do I do it?
You can use the json library in python to do your job. for example :
json_string = '{"first_name": "tom", "last_name":"harry"}'
import json
parsed_json = json.loads(json_string)
print(parsed_json['first_name'])
"tom"
Since you have created a web app. I am assuming you have exposed a URL from which you can get you JSON response, for example http://jsonplaceholder.typicode.com/posts/1.
import urllib2
import json
data = urllib2.urlopen("http://jsonplaceholder.typicode.com/posts/1").read()
parsed_json = json.loads(data)
The urlopen function sends a HTTP GET request at the given URL. parsed_json is a variable of the type map and you can extract the required data from it.
print parsed_json['userId']
1
The answer I want to suggest is a little different. In your scenario - where one function needs to be accessed from both server and client end, I would suggest provide some extra parameter and change the output based on that. This reduces overheads and unnecessary conversions.
For example, if you pass in an extra parameter and change the result like this, you don't need JSON parsing on python. Of course there are solutions to do that, but why need converting to json and then parsing back when you can avoid that totally?
def rest_get(request, token, return_json=True):
details = Links.get_url(Links, token)
result={}
if len(details)>0:
result['status'] = 200
result['status_message'] = "OK"
result['url'] = details[0].url
else:
result['status'] = 404
result['status_message'] = "Not Found"
result['url'] = None
if return_json: # this is web response, so by default return_json = True
return JsonResponse(result)
return result
Then in your python code call like this -
rest_get(request, token, return_json=False): # we are passing False, so the return type is dictionary and we can use it right away.