Почему запросы "API" возвращают "Нет" в запросах, в то время как "обычная очистка веб-страниц" дает ответ 200
ПРИМЕР:
Приведенный ниже код способен получить несколько веб-результатов с помощью греквестов, но почему на самом деле он терпит неудачу с "совершением простых вызовов API"
КОД:
import grequests
links = [
'https://api.github.com/users?since=135',
'http://www.google.com',
'https://api.github.com/users?since=135',
'http://www.google.com'
]
a = (grequests.get(i) for i in links)
p = grequests.map(a)
print(p)
Почему, черт возьми, это не выход: (Ответ [200], Ответ [200], Ответ [200], Ответ [200])
Но: (Нет, Ответ [200], Нет, Ответ [200])
... просто пропускает вызовы API по назначению):
1 ответ
Если библиотека запросов (используемая grequests) возвращает
None
в качестве ответа (по любой причине) grequests позволяет вам обрабатывать это так, как вы хотите, вызывая функцию обратного вызова обработчика исключений, которую вы создаете, а затем переходите к
map
.
Из
grequests.py
(в
map
метод):
for request in requests:
if request.response is not None:
ret.append(request.response)
elif exception_handler and hasattr(request, 'exception'):
ret.append(exception_handler(request, request.exception))
elif exception_handler and not hasattr(request, 'exception'):
ret.append(exception_handler(request, None))
else:
ret.append(None)
Что здесь происходит? Перед выполнением этого блока grequests вызовет все запросы, и теперь мы просматриваем результаты. По каждому запросу:
- Если вы получите
response
, верни это. - Если обработчик исключений зарегистрирован и
request
имеетexception
определены, вызовите обработчик и передайте емуrequest
иexception
. - Если обработчик исключений зарегистрирован и
request
не имеетexception
определены, вызовите обработчик и передайте емуrequest
. - Если
response
былоNone
, но обработчик не зарегистрирован, возвратNone
Последний случай приводит к потере данных, но ее можно предотвратить с помощью обратного вызова, который правильно обрабатывает исключение. Что именно
exception_handler
does - это то, что вам нужно определить, а затем включить следующее:
response = grequests.map(request_getters, exception_handler=my_handler)
что сделает обработчик, зависит от вас, но, возможно, это будет полезно:
MAX_PARALLEL_REQUESTS = 2
links = [
'https://api.github.com/users?since=135',
'http://www.google.com',
'https://api.github.com/users?since=135',
'http://www.google.com'
]
def my_handler(request, exception):
links.append(request.url)
print(f"exception thrown by grequests: \n{exception}")
return request
while links:
a = (grequests.get(links.pop(0)) for _ in range(MAX_PARALLEL_REQUESTS))
p = grequests.map(a, exception_handler=my_handler)
print(p)
Это выдает фиксированное количество URL-адресов из
links
перечислить каждую итерацию
while
петля. Если какой-либо из этих запросов не удастся,
my_handler
вызывается, который добавляет неудачный URL обратно в
links
список для переработки.
В конце концов я понял, что все, что мне нужно, это жестко закодировать его с помощью циклов, а не с помощью греквестов.
Вот
:
import requests, time
links = [
'https://api.github.com/users?since=135',
'http://www.google.com',
'https://api.github.com/users?since=135',
'http://www.google.com'
]
sd = []
for i in links:
try:
d = requests.get(i)
time.sleep(1)
sd.append(d)
except:
sd.append(False)
print(sd)
#note that time.sleep(*) is only optional.
... не знаю, почему Грекест ведет себя так.