Я отлаживал часами, почему мой код случайно разбивается с этой ошибкой: JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Это код, который у меня есть:
while True:
try:
submissions = requests.get('http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since).json()['submission']['records']
break
except requests.exceptions.ConnectionError:
time.sleep(100)
И я отлаживаю, печатая requests.get(url)
и requests.get(url).text
и я столкнулся со следующими "специальными" случаями:
requests.get(url)
возвращает успешный ответ 200 и requests.get(url).text
возвращает html. Я читал в Интернете, что это не requests.get(url).json()
при использовании requests.get(url).json()
, потому что он не сможет прочитать html, но как-то он не сломается. Почему это?
requests.get(url)
возвращает успешный ответ 200, а requests.get(url).text
находится в формате json. Я не понимаю, почему, когда он идет на requests.get(url).json()
она ломается с JSONDecodeError?
Точное значение requests.get(url).text
для случая 2:
{
"submission": {
"columns": [
"pk",
"form",
"date",
"ip"
],
"records": [
[
"21197",
"mistico-form-contacto-form",
"2018-09-21 09:04:41",
"186.179.71.106"
]
]
}
}
Глядя на документацию по этому API, кажется, что единственные ответы в формате JSON, поэтому получение HTML странно. Чтобы увеличить вероятность получения ответа JSON, вы можете настроить заголовок "Принять" на "application/json".
Я пробовал многократно запрашивать этот API с параметрами и не сталкивался с JSONDecodeError
. Вероятно, эта ошибка является результатом другой ошибки на стороне сервера. Чтобы справиться с этим, за except
того, в json.decoder.JSONDecodeError
в дополнение к ConnectionError
ошибка, которую вы в настоящее время, за except
и обрабатывать эту ошибку таким же образом, как ConnectionError
.
Вот пример с учетом всего этого:
import requests, json, time, random
def get_submission_records(client, since, try_number=1):
url = 'http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since
headers = {'Accept': 'application/json'}
try:
response = requests.get(url, headers=headers).json()
except (requests.exceptions.ConnectionError, json.decoder.JSONDecodeError):
time.sleep(2**try_number + random.random()*0.01) #exponential backoff
return get_submission_records(client, since, try_number=try_number+1)
else:
return response['submission']['records']
Я также обернут эта логика в рекурсивной функции, а не использовать во while
цикла, потому что я думаю, что это семантический яснее. Эта функция также ждет, прежде чем повторять попытку с помощью экспоненциального отсрочка (ожидание в два раза больше после каждого отказа).
Изменить: для Python 2.7 ошибка при попытке разобрать bad json - это ValueError
, а не JSONDecodeError
import requests, time, random
def get_submission_records(client, since, try_number=1):
url = 'http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since
headers = {'Accept': 'application/json'}
try:
response = requests.get(url, headers=headers).json()
except (requests.exceptions.ConnectionError, ValueError):
time.sleep(2**try_number + random.random()*0.01) #exponential backoff
return get_submission_records(client, since, try_number=try_number+1)
else:
return response['submission']['records']
поэтому просто измените это, except
строки, чтобы включить ValueError
вместо json.decoder.JSONDecodeError
.
json.loads(requests.get(url).text)
?