I'm trying to do a little code that gets the emails (and other things in the future) from an API. But I'm getting "TypeError: list indices must be integers or slices, not str" and I don't know what to do about it. I've been looking at other questions here but I still don't get it. I might be a bit slow when it comes to this.
I've also been watching some tutorials on the tube, and done the same as them, but still getting different errors. I run Python 3.5.
Here is my code:
from urllib.request import urlopen
import json, re
# Opens the url for the API
url = 'https://jsonplaceholder.typicode.com/posts/1/comments'
r = urlopen(url)
# This should put the response from API in a Dict
result= r.read().decode('utf-8')
data = json.loads(result)
#This shuld get all the names from the the Dict
for name in data['name']: #TypeError here.
print(name)
I know that I could regex the text and get the result that I want.
Code for that:
from urllib.request import urlopen
import re
url = 'https://jsonplaceholder.typicode.com/posts/1/comments'
r = urlopen(url)
result = r.read().decode('utf-8')
f = re.findall('"email": "(\w+\S\w+)', result)
print(f)
But that seems like the wrong way to do this.
Can someone please help me understand what I'm doing wrong here?
data is a list of dicts, that's why you are getting TypeError while iterating on it.
The way to go is something like this:
for item in data: # item is {"name": "foo", "email": "foo#mail..."}
print(item['name'])
print(item['email'])
#PiAreSquared's comment is correct, just a bit more explanation here:
from urllib.request import urlopen
import json, re
# Opens the url for the API
url = 'https://jsonplaceholder.typicode.com/posts/1/comments'
r = urlopen(url)
# This should put the response from API in a Dict
result= r.read().decode('utf-8')
data = json.loads(result)
# your data is a list of elements
# and each element is a dict object, so you can loop over the data
# to get the dict element, and then access the keys and values as you wish
# see below for some example
for element in data: #TypeError here.
name = element['name']
email = element['email']
# if you want to get all names, you should do
names = [element['name'] for element in data]
# same to get all emails
emails = [email['email'] for email in data]
Related
Sorry for my limited python knowledge.
I was using this code:
import requests
symbols = ["XYZW","XYZW","ABC"]
for s in symbols:
url = 'https://www.alphavantage.co/query?function=BALANCE_SHEET&symbol={}&apikey=apikey'.format(s)
r = requests.get(url)
data = r.json()
And expected an output of the three different dictionaries, but only got the ABC's data.
Am I supposed to loop it? I'm not sure how to. And why did it give me the last in the list? Does it sort alphabetically?
Use a list to store the value on each iteration, and then loop through them to print the results.
import requests
symbols = ["XYZW","XYZW","ABC"]
urls = []
for s in symbols:
urls.append('https://www.alphavantage.co/query?function=BALANCE_SHEET&symbol={}&apikey=apikey'.format(s))
for url in urls:
r = requests.get(url)
data = r.json()
print(data)
you reset the url every iteration of your for loop. Therefore you are only requesting the last url in the list.
I have a list of API links, and I'm trying to get the data from these API links.
If my list of API links looks like this:
api_links = ['https://api.blahblah.com/john', 'https://api.blahblah.com/sarah', 'https://api.blahblah.com/jane']
How can I get a list of loaded data from these API links? I'm getting an error message when doing this code:
response_API = requests.get([(x) for x in api_links])
Which is preventing me from loading the data here:
data = response_API.text
data_lst = json.loads(data)
Where am I going wrong?
change
response_API = requests.get([(x) for x in api_links])
to
response_API = [requests.get(x) for x in api_links]
responce_api will be a dict of requests object.
The function requests.get take as first argument an URL, not a list of them.
You want to call this function several times with one string, instead of one time with a list of strings.
Like this with a for loop :
for api_link in api_links:
response_API = requests.get(api_link)
data = response_API.text
data_lst = json.loads(data)
# Process further the data for the current api_link
The use of comprehension lists may not be a good idea here, as the process to do on each API link is not trivial.
I'm trying to scrape a site, when I run the following code without region_id=[any number from one to 32] I get a [500], but if I set region_id=1 I'll get only a first page by default (on the url it is pagina=&), pages are up to 500; is there a command or parameter for retrieving every page (every possible value of pagina=), avoiding for loops?
import requests
url = "http://www.enciclovida.mx/explora-por-region/especies-por-grupo?utf8=%E2%9C%93&grupo_id=Plantas®ion_id=&parent_id=&pagina=&nombre="
resp = requests.get(url, headers={'User-Agent':'Mozilla/5.0'})
data = resp.json()
Even without a for loop, you are still going to need iteration. You could do it with recursion or map as I've done below, but the iteration is still there. This solution has the advantage that everything is a generator, so only when you ask for a page's json from all_data will url be formatted, the request made, checked and converted to json. I added a filter to make sure you got a valid response before trying to get the json out. It still makes every request sequentially, but you could replace map with a parallel implementation quite easily.
import requests
from itertools import product, starmap
from functools import partial
def is_valid_resp(resp):
return resp.status_code == requests.codes.ok
def get_json(resp):
return resp.json()
# There's a .format hiding on the end of this really long url,
# with {} in appropriate places
url = "http://www.enciclovida.mx/explora-por-region/especies-por-grupo?utf8=%E2%9C%93&grupo_id=Plantas®ion_id={}&parent_id=&pagina={}&nombre=".format
regions = range(1, 33)
pages = range(1, 501)
urls = starmap(url, product(regions, pages))
moz_get = partial(requests.get, headers={'User-Agent':'Mozilla/5.0'})
responses = map(moz_get, urls)
valid_responses = filter(is_valid_response, responses)
all_data = map(get_json, valid_responses)
# all_data is a generator that will give you each page's json.
I am trying to make an API request to itunes to get songs by a particular artist and great a dictionary in JSON format with those songs. My below code is not returning any errors, but I am not sure where I am going wrong. Any help would be great. Also, I put comments next to some of the lines to help to further explain.
import json
import requests
def get_from_itunes(artist,songs):
base_url = "http://itunes.apple.com/search"
params_dict = {"term":bon+iver, "entity": music}
resp = requests.get(base_url, params=params_dict)
structured_resp_text = resp.text
python_obj_data_from_itunes = json.loads(structured_resp_text)
# the python object is a dictionary
itunes_dict_keys = python_obj_data_from_itunes.keys() # These keys are lists
for key in itunes_dict_keys:
print key # it's unicode. I have no clue how to proceed from here.
# I should be getting a dictionary
# And then getting to the key Track Name
file_obj = open("itunes_file.txt", "w") #wrote a file containing a JSON formatted string
# and then pasted that into the JSON editor
file_obj.write(python_obj_data_from_itunes + "\n")
file_obj.close()
return get_from_itunes()
I'm pretty new.
I wrote this python script to make an API call from blockr.io to check the balance of multiple bitcoin addresses.
The contents of btcaddy.txt are bitcoin addresses seperated by commas. For this example, let it parse this.
import urllib2
import json
btcaddy = open("btcaddy.txt","r")
urlRequest = urllib2.Request("http://btc.blockr.io/api/v1/address/info/" + btcaddy.read())
data = urllib2.urlopen(urlRequest).read()
json_data = json.loads(data)
balance = float(json_data['data''address'])
print balance
raw_input()
However, it gives me an error. What am I doing wrong? For now, how do I get it to print the balance of the addresses?
You've done multiple things wrong in your code. Here's my fix. I recommend a for loop.
import json
import urllib
addresses = open("btcaddy.txt", "r").read()
base_url = "http://btc.blockr.io/api/v1/address/info/"
request = urllib.urlopen(base_url+addresses)
result = json.loads(request.read())['data']
for balance in result:
print balance['address'], ":" , balance['balance'], "BTC"
You don't need an input at the end, too.
Your question is clear, but your tries not.
You said, you have a file, with at least, more than registry. So you need to retrieve the lines of this file.
with open("btcaddy.txt","r") as a:
addresses = a.readlines()
Now you could iterate over registries and make a request to this uri. The urllib module is enough for this task.
import json
import urllib
base_url = "http://btc.blockr.io/api/v1/address/info/%s"
for address in addresses:
request = urllib.request.urlopen(base_url % address)
result = json.loads(request.read().decode('utf8'))
print(result)
HTTP sends bytes as response, so you should to us decode('utf8') as approach to handle with data.