I'm attempting to format json from the Roblox API. I have a names.txt that stores all of the names. This is how the file looks
rip_robson0007
Abobausrip
app_58230
kakoytochelik123
Ameliathebest727
Sherri0708
HixPlayk
mekayla_091
ddddorffg
ghfgrgt7nfdbfj
TheWolfylikedog
paquita12345jeje
hfsgfhsgfhgfhds
It stores a bunch of usernames seperated by a new line. The code is suppose to use the names and for each name get the JSON from this endpoint https://api.roblox.com/users/get-by-username?username={name} & format it as I have in my code. It always returns error 429 and doesn't save any of the data.
This is the code:
import json
import requests
import time
# Read the names from the text file
with open("./txt/names.txt", "r") as f:
names = f.read().split("\n")
# Initialize an empty dictionary to store the users
users = {}
# Iterate through the names
for name in names:
time.sleep(5)
response = requests.get(f"https://api.roblox.com/users/get-by-username?username={name}")
# Check the status code of the response
if response.status_code != 200:
print(f"Failed to get data for {name}: {response.status_code}")
continue
# Try to parse the response as JSON
try:
user_data = response.json()
except ValueError:
print(f"Failed to parse JSON for {name}")
continue
# Extract the necessary information from the response
user_id = user_data["Id"]
username = user_data["Username"]
avatar_uri = user_data["AvatarUri"]
avatar_final = user_data["AvatarFinal"]
is_online = user_data["IsOnline"]
# Add the user's information to the dictionary
users[user_id] = {
"Id": user_id,
"Username": username,
"AvatarUri": avatar_uri,
"AvatarFinal": avatar_final,
"IsOnline": is_online
}
# Save the dictionary to a JSON file
with open("users.json", "w") as f:
json.dump(users, f)
You can often overcome this with judicious use of proxies.
Start by getting a list of proxies from which you will make random selections. I have a scraper that acquires proxies from https://free-proxy-list.net
My list (extract) looks like this:-
http://103.197.71.7:80 - no
http://163.116.177.33:808 - yes
'yes' means that HTTPS is supported. This list currently contains 95 proxies. It varies depending on the response from my scraper
So we start by parsing the proxy list. Subsequently we choose proxies at random before trying to access the Roblox API. This may not run quickly because the proxies are not necessarily reliable. They are free after all.
from requests import get as GET, packages as PACKAGES
from random import choice as CHOICE
from concurrent.futures import ThreadPoolExecutor as TPE
PACKAGES.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL:#SECLEVEL=1'
ROBLOX_API = 'https://api.roblox.com/users/get-by-username'
TIMEOUT = 1
def get_proxies():
http, https = list(), list()
with open('proxylist.txt') as p:
for line in p:
proxy_url, _, supports_https = line.split()
_list = https if supports_https == 'yes' else http
_list.append(proxy_url)
return http, https
http, https = get_proxies()
def process(name):
params = {'username': name.strip()}
while True:
try:
proxy = {'http': CHOICE(http), 'https': CHOICE(https)}
(r := GET(ROBLOX_API, params=params, proxies=proxy, timeout=TIMEOUT)).raise_for_status()
if (j := r.json()).get('success', True):
print(j)
break
except Exception as e:
pass
with open('names.txt') as names:
with TPE() as executor:
executor.map(process, names)
In principle, the while loop in process() could get stuck so it might make sense to limit the number of retries.
This produces the following output:
{'Id': 4082578648, 'Username': 'paquita12345jeje', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 2965702542, 'Username': 'mekayla_091', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 4079018794, 'Username': 'app_58230', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 3437922948, 'Username': 'kakoytochelik123', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 4082346906, 'Username': 'Abobausrip', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 2988555289, 'Username': 'HixPlayk', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 3286921649, 'Username': 'Sherri0708', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 1441252794, 'Username': 'ghfgrgt7nfdbfj', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 4088896225, 'Username': 'ddddorffg', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 3443374919, 'Username': 'TheWolfylikedog', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 3980932331, 'Username': 'Ameliathebest727', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 3773237135, 'Username': 'rip_robson0007', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
{'Id': 4082991447, 'Username': 'hfsgfhsgfhgfhds', 'AvatarUri': None, 'AvatarFinal': False, 'IsOnline': False}
I am using simplejwt to get an access and refresh tokens. In a view I need to create a dict, where the both will be stored as well as access token claims and another additional data. Everything works but by some reason when the refrsh token is added to dict, it returns its decoded value, but not the token.
my views.py
#csrf_exempt
##api_view(('GET',))
def check_token(request):
token_refresh = RefreshToken.for_user(request.user)
print('REFRESH', token_refresh)
token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
data = {'token': token, 'refresh_token': token_refresh}
try:
valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
data['uui'] = valid_data['user_id']
data['validUntil'] = valid_data['exp']
data['clientId'] = 'default'
print(data)
return JsonResponse(data)
except ValidationError as v:
print("Validation error", v)
print('REFRESH', token_refresh) returns the token:
'REFRESH eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI...'
but data object returns:
{'token': 'eyJ0eXAiOiJKV1QiLCJhbGci...', 'refresh_token': {'token_type': 'refresh', 'exp': 1628664751, 'jti': '38f0e3a4d7bb452681834a6b149aa496', 'user_id': 'None'}, 'uui': 1, 'validUntil': 1628059131, 'clientId': 'default'}
my ideal result:
{'token': 'eyJ0eXAiOiJKV1QiLCJhbGci...', 'refresh_token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI...', 'uui': 1, 'validUntil': 1628059131, 'clientId': 'default'}
if you want to create tokens manually for user in djangorestframework-simplejwt you can do this:
from rest_framework_simplejwt.tokens import RefreshToken
def get_tokens_for_user(user):
refresh = RefreshToken.for_user(user)
return {
'refresh': str(refresh),
'access': str(refresh.access_token),
# Add additional fields here
}
now you can use this function in your views.
I am calling the Giphy API using another wrapper API which returns a list of dictionaries. I am having hard times to serialize the data to return it to AJAX.
The data is returned as InlineResponse200 with three properties.
(docu)
The problem is that my view is not able to return the JSON properly:
# Traceback
[2020-06-23 14:58:54,086] log: ERROR - Internal Server Error: /get_gifs/
Traceback (most recent call last):
File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Jonas\Desktop\finsphere\finsphere\blog\views.py", line 234, in get_gifs
return JsonResponse(api_response.data[0])
File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\http\response.py", line 554, in __init__
raise TypeError(
TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
[23/Jun/2020 14:58:54] "POST /get_gifs/ HTTP/1.1" 500 17874
If I add safe=False it returns TypeError: Object of type Gif is not JSON serializable
I don't get this since api_response.data[0] is a cristal clear dictionary.
Desired outcome: Get the Giphy object logged in the success function of Ajax.
AJAX
(function($) {
$('#btnSearch').on('click', function(e) {
var query = $('#search').val();
console.log(query);
e.preventDefault();
$.ajax({
type: 'post',
async: true,
url: '/get_gifs/',
data: {
'query': query,
'csrfmiddlewaretoken': window.CSRF_TOKEN // from blog.html
},
success: function(response) {
},
error: function(xhr, status, error) {
// shit happens friends!
}
});
});
}(jQuery));
(Inserted my original -free- API key for reproduction)
Views.py
def get_gifs(request):
# create an instance of the API class
api_instance = giphy_client.DefaultApi()
# API Key
api_key = 'NGSKWrBqtIq1rFU1Ka11D879Y1u4Igia'
# Search term
q = request.POST.get('query')
print(q)
# Query parameters
limit = 2
offset = 0
rating = 'g'
lang = 'en'
fmt = 'json'
try:
# Search Endpoint
api_response = api_instance.gifs_search_get(api_key, q, limit=limit, offset=offset, rating=rating, lang=lang, fmt=fmt)
pprint(api_response)
except ApiException as e:
print("Exception when calling DefaultApi->gifs_search_get: %s\n" % e)
return JsonResponse(api_response.data[0])
API fetched object (pprint api_response)
{'data': [{'bitly_gif_url': 'https://gph.is/g/EJWjdvN',
'bitly_url': 'https://gph.is/g/EJWjdvN',
'content_url': '',
'create_datetime': None,
'embed_url': 'https://giphy.com/embed/J0JGg6doLfmV0yZmIB',
'featured_tags': None,
'id': 'J0JGg6doLfmV0yZmIB',
'images': {'downsized': {'height': '250',
'size': '350582',
'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
'width': '478'},
'downsized_large': {'height': '250',
'size': '350582',
'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
'width': '478'},
'preview_gif': {'height': '134',
'size': '49623',
'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy-preview.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.gif',
'width': '256'}},
'import_datetime': '2020-06-15 10:01:39',
'is_anonymous': None,
'is_community': None,
'is_featured': None,
'is_hidden': None,
'is_indexable': None,
'is_realtime': None,
'is_removed': None,
'is_sticker': False,
'rating': 'g',
'slug': 'MITEF-mitefarab-asc2020-J0JGg6doLfmV0yZmIB',
'source': 'www.mitefarab.org',
'source_post_url': 'www.mitefarab.org',
'source_tld': '',
'tags': None,
'trending_datetime': '0000-00-00 00:00:00',
'type': 'gif',
'update_datetime': None,
'url': 'https://giphy.com/gifs/MITEF-mitefarab-asc2020-J0JGg6doLfmV0yZmIB',
'user': {'avatar_url': 'https://media2.giphy.com/avatars/MITEF/8FTlysEjtXzx.jpg',
'banner_url': '',
'display_name': 'MITEF Pan Arab',
'profile_url': 'https://giphy.com/MITEF/',
'twitter': None,
'username': 'MITEF'},
'username': 'MITEF'},
{'bitly_gif_url': 'https://gph.is/g/ZdxQQpP',
'bitly_url': 'https://gph.is/g/ZdxQQpP',
'content_url': '',
'create_datetime': None,
'embed_url': 'https://giphy.com/embed/hTJF0O4vDkJsUi1h8Q',
'featured_tags': None,
'id': 'hTJF0O4vDkJsUi1h8Q',
'images': {'downsized': {'height': '480',
'size': '310971',
'url': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
'width': '480'},
'preview': {'height': '480',
'mp4': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy-preview.mp4?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.mp4',
'mp4_size': '15536',
'width': '480'},
'preview_gif': {'height': '480',
'size': '22387',
'url': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy-preview.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.gif',
'width': '480'}},
'import_datetime': '2019-07-19 22:27:40',
'is_anonymous': None,
'is_community': None,
'is_featured': None,
'is_hidden': None,
'is_indexable': None,
'is_realtime': None,
'is_removed': None,
'is_sticker': False,
'rating': 'g',
'slug': 'RecargaPay-cashback-recargapay-paguetudopelocelular-hTJF0O4vDkJsUi1h8Q',
'source': 'www.recargapay.com.br',
'source_post_url': 'www.recargapay.com.br',
'source_tld': '',
'tags': None,
'trending_datetime': '0000-00-00 00:00:00',
'type': 'gif',
'update_datetime': None,
'url': 'https://giphy.com/gifs/RecargaPay-cashback-recargapay-paguetudopelocelular-hTJF0O4vDkJsUi1h8Q',
'user': {'avatar_url': 'https://media0.giphy.com/avatars/RecargaPay/msKTiPaVkvqd.png',
'banner_url': 'https://media0.giphy.com/headers/RecargaPay/kg023vdaAaWA.gif',
'display_name': 'RecargaPay',
'profile_url': 'https://giphy.com/RecargaPay/',
'twitter': None,
'username': 'RecargaPay'},
'username': 'RecargaPay'}],
'meta': {'msg': 'OK',
'response_id': '65bc1664c2b17e3e4b60d88c736d0c6b5a39d682',
'status': 200},
'pagination': {'count': 2, 'offset': 0, 'total_count': 10}}
I go though your code everything is correct except return JsonResponse(api_response.data[0]) in your views
JsonResponse:
The first parameter, data, should be a dict instance. If the safe parameter is set to False, it can be any JSON-serializable object. official documentation link
When you say
1. safe=True
return JsonResponse(api_response.data[0])
TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
The error is obvious api_response.data[0] is not dict, see point 2 error
2
safe=False
return JsonResponse(api_response.data[0], safe=False)
TypeError: Object of type Gif is not JSON serializable
The data api_response.data[0] you provide to JsonResponse is not a dict type object actually, that's why you got error for first point.
when you say safe=False JsonResponse is trying to serialize object but that object is not json serializable, you can trace-back error
File "....\Python\Python38\lib\json\encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Gif is not JSON serializable
Can be followed the link to see which object can be Json serializable
Coming back to your error.
I don't get this since api_response.data[0] is a cristal clear dictionary.
type of api_response and api_response.data[0]
type(api_response)
<class 'giphy_client.models.inline_response_200.InlineResponse200'>
type(api_response.data[0])
<class 'giphy_client.models.gif.Gif'>
You can follow for giphy_client documentation link for more-details
Solution:
result = api_response.data[0].to_dict() ## NOTE to_dict function of giphy_client.models.gif.Gif
return JsonResponse(result)
render(request, template_name, context=None, content_type=None, status=None, using=None)
render() Combines a given template with a given context dictionary
and returns an HttpResponse object with that rendered text.
You can either use Django defaults JsonResponse class or Django REST framework Response class to return JSON responses.
from django.http import JsonResponse
return JsonResponse(data=api_response.data)
from rest_framework.response import Response
return Response(data=api_response.data)
tried it on the ipython shell and it works just fine.
In [15]: response = Response(api_response.data[0])
In [16]: response
Out[16]: <Response status_code=200, "text/html; charset=utf-8">
response.data gives me the serialized response.
Python has a built in function for converting dicts to json.
import json
data = api_response.data
return render(request, json.dumps(data))
If you use that in your return statement it should return json.
I am trying to retrieve data from the first available date to present date from an API. I've tried using min and max in parameter.
def getcomplete(cid, pid, tag, type):
api_endpoint = ''
headers = {'token': get_token()['access_token'], 'Content-Type': 'application/json'}
params = {'cid': str(cid),
'from-date': datetime.datetime.min,
'to-date': datetime.datetime.max,
'tag': str(tag),
'type': str(type),
'pid': str(pid)
}
r = requests.post(url=api_endpoint, headers=headers, params=params)
return r.json()
getcomplete(10,12,'x','y')
This returns {'status': 'success', 'message': 'success', 'data': []}.
Is there anything wrong with the written function.
Thanks
Pythons min() and max() have an optional default parameter. This will prevent them from throwing errors
min("", default="")
I have the following the following code
response = requests.get(url, headers=headers)
response_dict = response.json()
print(response_dict)
user_name = response_dict['data']['username']
password = response_dict['data']['password']
My print returns:
{'request_id': 'hidden', 'lease_id': 'hidden', 'renewable': True, 'lease_duration': 3600, 'data': {'password': 'hidden', 'username': 'hidden'}, 'wrap_info': None, 'warnings': None, 'auth': None}
I get a key error
'data': KeyError
What seems to be the mistake here?
The issue was with my VPC once the code was pushed to a lambda, I did not have permission to move forward with requests sometimes due to race condition.