Reading mashabe API using urllib - python

I have this code to read Mashape.com API in python 2. how can i read it in python 3?
code
import urllib, urllib2, json
from pprint import pprint
URL = "https://getsentiment.p.mashape.com/"
text = "The food was great, but the service was slow."
params = {'text': text, 'domain': 'retail', 'terms': 1, 'categories': 1,'sentiment': 1, 'annotate': 1}
headers = {'X-Mashape-Key': YOUR_MASHAPE_KEY}
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request(URL, urllib.urlencode(params), headers=headers)
response = opener.open(request)
opener.close()
data = json.loads(response.read())
pprint(data)
i tried this code but it had following error :
import urllib.parse
import urllib.request
URL = "https://getsentiment.p.mashape.com/"
text = "The food was great, but the service was slow."
params = {'text': text, 'domain': 'retail', 'terms': 1, 'categories': 1, 'sentiment': 1, 'annotate': 1}
headers = {'X-Mashape-Key': YOUR_MASHAPE_KEY}
opener = urllib.request.build_opener(urllib.request.HTTPHandler)
request = urllib.request.Request(URL, urllib.parse.urlencode(params), headers)
response = opener.open(request)
opener.close()
data = json.loads(response.read())
print(data)
error :
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.

In this line:
request = urllib.request.Request(URL, urllib.parse.urlencode(params), headers)
Try to replace to
data = urllib.parse.urlencode(params).encode('utf-8')
request = urllib.request.Request(URL, data, headers)

Related

Why am I getting incorrect response_json from my request in python

I am trying to automate adding songs to spotify using python.
Here in the code I am trying to search for the song using the song_name and the artist name and use the spotify api to get the URI of the song. (https://developer.spotify.com/documentation/web-api/reference/search/search/)
However the response I am getting is invalid i.e it doesnt return the list of songs with uris, it just returns back the query or the request that I am sending in to the API.
e.g {'tracks': {'href': 'https://api.spotify.com/v1/search?query=track%3AYEAH+RIGHT+artist%3AJoji&type=track&offset=0&limit=20', 'items': [], 'limit': 20, 'next': None, 'offset': 0, 'previous': None, 'total': 0}}
def get_spotify_uri(self, song_name, artist):
"""Search For the Song"""
query = "https://api.spotify.com/v1/search?q=track:{}%20artist:{}&type=track".format(
song_name,
artist
)
response = requests.get(
query,
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {}".format(spotify_token)
}
)
response_json = response.json()
print(response_json)
songs = response_json["tracks"]["items"]
# only use the first song
uri = songs[0]["uri"]
return uri
Error: response
{'tracks': {'href': 'https://api.spotify.com/v1/search?query=track%3ANext+%28Album+Version%29+artist%3AThe+Weeknd&type=track&offset=0&limit=20', 'items': [], 'limit': 20, 'next': None, 'offset': 0, 'previous': None, 'total': 0}}
Traceback (most recent call last):
File "/home/nikhil/Crypy/spotifyplaylist.py", line 149, in <module>
cp.add_song_to_playlist()
File "/home/nikhil/Crypy/spotifyplaylist.py", line 124, in add_song_to_playlist
self.get_liked_videos()
File "/home/nikhil/Crypy/spotifyplaylist.py", line 77, in get_liked_videos
"spotify_uri": self.get_spotify_uri(song_name, artist)
File "/home/nikhil/Crypy/spotifyplaylist.py", line 119, in get_spotify_uri
uri = songs[0]["uri"]
I'm posting an answer because I couldn't fit the entire thing in a comment. I just wanted to say that I was successful with the barebones code below that however uses urllib, which might not be what you are looking for given that you use the requests library. Perhaps it can be useful for comparison purposes (tested in python 3.8):
import urllib.request, urllib.parse
import base64, json
# fill with your own
client_id = b"insert_here_your_client_id"
client_secret = b"insert_here_your_client_secret"
# ask for authorization
query = "https://accounts.spotify.com/api/token"
postdata = urllib.parse.urlencode({"grant_type": "client_credentials"})
postheaders = {'Authorization': "Basic "+base64.b64encode( client_id+b':'+client_secret ).decode('latin-1')}
req = urllib.request.Request(query, data=postdata.encode('latin-1'), headers=postheaders)
req = urllib.request.urlopen(req).read().decode('latin-1')
req = json.loads(req)
# do the search query
query = "https://api.spotify.com/v1/search?q=track:Castles%20artist:Freya&type=track"
req = urllib.request.Request(query, data=None, headers={'Authorization': "Bearer "+req['access_token']})
req = urllib.request.urlopen(req).read().decode('latin-1')
print(req)

Converting list to python array [duplicate]

I need to POST a JSON from a client to a server. I'm using Python 2.7.1 and simplejson. The client is using Requests. The server is CherryPy. I can GET a hard-coded JSON from the server (code not shown), but when I try to POST a JSON to the server, I get "400 Bad Request".
Here is my client code:
data = {'sender': 'Alice',
'receiver': 'Bob',
'message': 'We did it!'}
data_json = simplejson.dumps(data)
payload = {'json_payload': data_json}
r = requests.post("http://localhost:8080", data=payload)
Here is the server code.
class Root(object):
def __init__(self, content):
self.content = content
print self.content # this works
exposed = True
def GET(self):
cherrypy.response.headers['Content-Type'] = 'application/json'
return simplejson.dumps(self.content)
def POST(self):
self.content = simplejson.loads(cherrypy.request.body.read())
Any ideas?
Starting with Requests version 2.4.2, you can use the json= parameter (which takes a dictionary) instead of data= (which takes a string) in the call:
>>> import requests
>>> r = requests.post('http://httpbin.org/post', json={"key": "value"})
>>> r.status_code
200
>>> r.json()
{'args': {},
'data': '{"key": "value"}',
'files': {},
'form': {},
'headers': {'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'close',
'Content-Length': '16',
'Content-Type': 'application/json',
'Host': 'httpbin.org',
'User-Agent': 'python-requests/2.4.3 CPython/3.4.0',
'X-Request-Id': 'xx-xx-xx'},
'json': {'key': 'value'},
'origin': 'x.x.x.x',
'url': 'http://httpbin.org/post'}
It turns out I was missing the header information. The following works:
import requests
url = "http://localhost:8080"
data = {'sender': 'Alice', 'receiver': 'Bob', 'message': 'We did it!'}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
r = requests.post(url, data=json.dumps(data), headers=headers)
From requests 2.4.2 (https://pypi.python.org/pypi/requests), the "json" parameter is supported. No need to specify "Content-Type". So the shorter version:
requests.post('http://httpbin.org/post', json={'test': 'cheers'})
Which parameter between data / json / files you need to use depends on a request header named Content-Type (you can check this through the developer tools of your browser).
When the Content-Type is application/x-www-form-urlencoded, use data=:
requests.post(url, data=json_obj)
When the Content-Type is application/json, you can either just use json= or use data= and set the Content-Type yourself:
requests.post(url, json=json_obj)
requests.post(url, data=jsonstr, headers={"Content-Type":"application/json"})
When the Content-Type is multipart/form-data, it's used to upload files, so use files=:
requests.post(url, files=xxxx)
The better way is:
url = "http://xxx.xxxx.xx"
data = {
"cardno": "6248889874650987",
"systemIdentify": "s08",
"sourceChannel": 12
}
resp = requests.post(url, json=data)
headers = {"charset": "utf-8", "Content-Type": "application/json"}
url = 'http://localhost:PORT_NUM/FILE.php'
r = requests.post(url, json=YOUR_JSON_DATA, headers=headers)
print(r.text)
Works perfectly with python 3.5+
client:
import requests
data = {'sender': 'Alice',
'receiver': 'Bob',
'message': 'We did it!'}
r = requests.post("http://localhost:8080", json={'json_payload': data})
server:
class Root(object):
def __init__(self, content):
self.content = content
print self.content # this works
exposed = True
def GET(self):
cherrypy.response.headers['Content-Type'] = 'application/json'
return simplejson.dumps(self.content)
#cherrypy.tools.json_in()
#cherrypy.tools.json_out()
def POST(self):
self.content = cherrypy.request.json
return {'status': 'success', 'message': 'updated'}
With current requests you can pass in any data structure that dumps to valid JSON , with the json parameter, not just dictionaries (as falsely claimed by the answer by Zeyang Lin).
import requests
r = requests.post('http://httpbin.org/post', json=[1, 2, {"a": 3}])
this is particularly useful if you need to order elements in the response.
I solved it this way:
from flask import Flask, request
from flask_restful import Resource, Api
req = request.json
if not req :
req = request.form
req['value']
It always recommended that we need to have the ability to read the JSON file and parse an object as a request body. We are not going to parse the raw data in the request so the following method will help you to resolve it.
def POST_request():
with open("FILE PATH", "r") as data:
JSON_Body = data.read()
response = requests.post(url="URL", data=JSON_Body)
assert response.status_code == 200

Python: how to send html-code in a POST request

I try to send htm-code from python script to Joomla site.
description = "<h1>Header</h1><p>text</p>"
values = {'description' : description.encode(self.encoding),
'id = ' : 5,
}
data = urlencode(values)
binData = data.encode(self.encoding)
headers = { 'User-Agent' : self.userAgent,
'X-Requested-With' : 'XMLHttpRequest'}
req = urllib2.Request(self.addr, binData, headers)
response = urllib2.urlopen(req)
rawreply = response.read()
At Joomla-server I got the same string but without html:
$desc = JRequest::getVar('description', '', 'POST');
What's wrong?
You should use requests
pip install requests
then
import requests
description = "<h1>Header</h1><p>text</p>"
values = dict(description='description',id=5)
response = requests.post(self.addr,data=values)
if response.ok:
print response.json()
or if joomla didnt return json
print response.content
JRequest::getVar or JRequest::getString filter HTML code. But it can be turned off:
$desc = JRequest::getVar('description', '', 'POST', 'string', JREQUEST_ALLOWHTML);

Python 'requests' module and encoding?

I am doing a simple POST request using the requests module, and testing it against httpbin
import requests
url = 'http://httpbin.org/post'
params = {'apikey':'666666'}
sample = {'sample': open('test.bin', 'r')}
response = requests.post( url, files=sample, params=params, verify=False)
report_info = response.json()
print report_info
I have an issue with the encoding. It is not using application/octet-stream and so the encoding is not correct. From the headers, I see:
{
u'origin': u'xxxx, xxxxxx',
u'files': {
u'sample': u'data:None;base64,qANQR1DBw..........
So, I get data:None instead of data:application/octet-stream when I try with curl. The file size and encoding is incorrect.
How can I force or check that it is using application/octet-stream?
Sample taken from http://www.python-requests.org/en/latest/user/quickstart/#custom-headers
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> headers = {'content-type': 'application/json'}
>>> r = requests.post(url, data=json.dumps(payload), headers=headers)
You might want to change the headers to
headers = {'content-type': 'application/octet-stream'}
response = requests.post( url, files=sample, params=params, verify=False,
headers = headers)

REST post using Python-Request

Why doesn't this simple code POST data to my service:
import requests
import json
data = {"data" : "24.3"}
data_json = json.dumps(data)
response = requests.post(url, data=data_json)
print response.text
And my service is developed using WCF like this :
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/test", ResponseFormat =
WebMessageFormat.Json,RequestFormat=WebMessageFormat.Json)]
string test(string data );
Note: If is remove the input parameter data everything works fine, what may be the issue.
You need to set the content type header:
data = {"data" : "24.3"}
data_json = json.dumps(data)
headers = {'Content-type': 'application/json'}
response = requests.post(url, data=data_json, headers=headers)
If I set url to http://httpbin.org/post, that server echos back to me what was posted:
>>> import json
>>> import requests
>>> import pprint
>>> url = 'http://httpbin.org/post'
>>> data = {"data" : "24.3"}
>>> data_json = json.dumps(data)
>>> headers = {'Content-type': 'application/json'}
>>> response = requests.post(url, data=data_json, headers=headers)
>>> pprint.pprint(response.json())
{u'args': {},
u'data': u'{"data": "24.3"}',
u'files': {},
u'form': {},
u'headers': {u'Accept': u'*/*',
u'Accept-Encoding': u'gzip, deflate, compress',
u'Connection': u'keep-alive',
u'Content-Length': u'16',
u'Content-Type': u'application/json',
u'Host': u'httpbin.org',
u'User-Agent': u'python-requests/1.0.3 CPython/2.6.8 Darwin/11.4.2'},
u'json': {u'data': u'24.3'},
u'origin': u'109.247.40.35',
u'url': u'http://httpbin.org/post'}
>>> pprint.pprint(response.json()['json'])
{u'data': u'24.3'}
If you are using requests version 2.4.2 or newer, you can leave the JSON encoding to the library; it'll automatically set the correct Content-Type header for you too. Pass in the data to be sent as JSON into the json keyword argument:
data = {"data" : "24.3"}
response = requests.post(url, json=data)

Categories

Resources