I am following along with Python for Data Analysis and am on Chapter 6 looking at using APIs.
I wish to connect to sources provided by National Grid on their Data Portal. They provide a number of URLs (e.g. several found here, https://data.nationalgrideso.com/ancillary-services/obligatory-reactive-power-service-orps-utilisation). I want to read these directly into pandas rather than download the Excel/csv file and then open that.
I am receiving the error message
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
after attempting the following:
import requests
import codecs
import json
url = 'https://data.nationalgrideso.com/backend/dataset/7e142b03-8650-4f46-8420-7ce1e84e1e5b/resource/a61c6c26-62ec-41e1-ae25-ed95f4562274/download/reactive-utilisation-data-apr-2020-mar-2022.csv'
resp = request.get(url)
decoded_data = codecs.decode(resp.text.encode(), 'utf-8-sig')
data = json.loads(decoded_data)
I understand that I need to use 'utf-8-sig' due to a particular BOM appearing on the first line otherwise.
I have looked at answers regarding the same error message but nothing is working for me at present. The API is working in the browser and I am receiving a response of 200 and data is being returned. Perhaps I am missing something more fundamental in the approach?
Related
I am currently working in python's requests library and accessing Salesforce API. I have successfully
Accessed the access_token from Salesforce API
Obtained the Session_ID
Now I need to do a upsert operation in salesforce using requests.put in text/csv format (as requested by the API developer)
Please see below for the code snippet and I have not shown the above two steps of the code
# Data for upsert operation
data = {
"Name":["ABC"],
"Model_Score__c":['Low'],
"Email__c":['Y'],
"Call__c":['N'],
"Processing_Date__c":['2022-02-24']
}
dfData = pd.DataFrame(data)
dfData_csv = dfData.to_csv(index=False, encoding='utf8')
# Headers to be sent with the put request
header = {}
header['Authorization'] = 'Bearer xxxxxx...xxxx'
header['Content-Type']='text/csv'
header['Connection'] = 'keep-alive'
header['Accept-Encoding'] = 'gzip, deflate, br'
# Points to the URL where we need to perform the operation and test_api_url is a sandbox url
put_url = test_api_url+f'/{session_id}/batches'
# Calling the put request
put_call_response = requests.put(put_url, data=dfData_csv, headers=header)
I get the following error
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Please note that I am able to test it successfully in Postman and please see below the data sent in the body of the postman put request. I have also sent the raw text as shown below using python but I still get the same error
"Name",Model_Score__c,Email__c,Call__c,Processing_Date__c
"ABC",Low,Y,N,2022-02-24
Any help is much appreciated.
It appears that you are trying to use the Bulk API (the REST API does not accept CSV data), but you're calling the wrong endpoint and haven't performed any of the required setup to do so.
put_url = test_api_url+f'/{session_id}/batches'
Never, ever put your session id in a URL! In any case, it's not the right URL for the Bulk API.
If you're trying to work with the more recent Bulk API 2.0, you want to do an ingest operation. (Detail).
With Bulk API 1.0, you'd do a more complex sequence of creating a job, adding batches, closing the job and monitoring.
I recommend reading the entire Bulk API Developer Guide. These APIs are complex and tricky.
Actually my answer was correct. The reason why I was getting the error is because I was executing the below statement. My bad for not posting the below line of code in my question.
print(put_call_response.json())
The above print statement was throwing the error because I was trying to parse an object that is not of json type. If I check the status_code, I was getting 201 (which means successfully updated the record) and when I checked the backend, it was reflecting as well.
print(put_call_response.status_code)
I am using the Censys api in python to programmatically look through host and grab information about them. Censys website says it returns Json formatted data and it looks like Json formatted data but, I cant seem to figure out how to tun the api response into a json object. However, if i write the json response to a json file and load it. It works fine Any ideas?
Update: Figured out issue is with nested json that the api returns. Looking for libraries to flatten it.
Main.py
c = censys.ipv4.CensysIPv4(api_id=UID, api_secret=SECRET)
for result in c.search("autonomous_system.asn:15169 AND tags.raw:iot", max_records=1):
hostIPS.append(result["ip"]);
for host in hostIPS:
for details in c.view(host):
# test = json.dumps(details)
# test = json.load(test)
# data = json.load(details)
data = json.loads(details)
print(data)
You don't need to convert it to an object, it's already json.loaded. See the implementation here: https://github.com/censys/censys-python/blob/master/censys/base.py
I am new to python code. We are requesting the GitHub URL and Response is JSON. We have to parse the Json to filter out the labels that need to store in the CSV format as specific labels. We have authentication token that we use it for request of the URL. could you please provide the coding the above scenario
Your question is very general and since you didn't include any code, it seems like you are just looking for a straightforward answer.
I can't give you that, but the below code should get you started on converting a json into a python object, looking for a specific keyword label and writing it to a cvs file.
import json
x = json.loads(your_json_object)
for label in x:
with open('your_file.csv', 'w') as file:
for label in x:
file.write("{}, ".format(label))
I'm trying to download a file from a website but it looks like it is detecting urllib and doesn't allow it to download (I'm getting the error "urllib.error.HTTPError: HTTP Error 403: Forbidden").
How can I fix this? I found on the internet that I had to add a header but the answers weren't going the way I need (It was using Request and I didn't find anything about an argument to add in urllib.request.urlretrieve() for a header)
I'm using Python 3.6
Here's the code:
import urllib.request
filelink = 'https://randomwebsite.com/changelog.txt'
filename = filelink.rsplit('/', 1)
filename = str(filename[1])
urllib.request.urlretrieve(filelink, filename)
I want to include a header to give me the permission to download the file but I need to keep a line like the last one, using the two variables (one for the link of the file and one for the name that depends of the link).
Thanks already for your help !
Check the below link:
https://stackoverflow.com/a/7244263/5903276
The most correct way to do this would be to use the urllib.request.urlopen function to return a file-like object that represents an HTTP response and copy it to a real file using shutil.copyfileobj.
I'm trying to scrape data from Verizon's buyback pricing site. I found the source of the information while going through "Net" requests in my browser. The site is in JSON format, but nothing I do will let me download that data https://www.verizonwireless.com/vzw/browse/tradein/ajax/deviceSearch.jsp?act=models&car=Verizon&man=Apple&siz=large
I can't remember everything I've tried, but here are the issues I'm having. Also, I'm not sure how to insert multiple code blocks.
import json,urllib,requests
res=urllib.request.urlopen(url)
data=json.loads(res)
TypeError: the JSON object must be str, not 'bytes'
import codecs
reader=codecs.getreader('utf-8')
obj=json.load(reader(res))
ValueError: Expecting value: line 1 column 1 (char 0)
#this value error happens with other similar attempts, such as....
res=requests.get(url)
res.json()#Same error Occurs
At this point I've researched many hours and can't find a solution. I'm assuming that the site is not formatted normally or I'm missing something obvious. I see the JSON requests/structure in my web developer tools.
Does anybody have any ideas or solutions for this? Please let me know if you have questions.
You need to send a User-Agent HTTP header field. Try this program:
import requests
url='https://www.verizonwireless.com/vzw/browse/tradein/ajax/deviceSearch.jsp?act=models&car=Verizon&man=Apple&siz=large'
# Put your own contact info in next line
headers = {'User-agent':'MyBot/0.1 (+user#example.com)'}
r = requests.get(url, headers=headers)
print(r.json()['models'][0]['name'])
Result:
iPhone 6S