Используя запросы, чтобы сделать несколько тысяч запросов get для sourceforge, получим "Максимальное количество попыток превышено с помощью URL"
Я очень новичок во всем этом; Мне нужно получить данные о нескольких тысячах проектов sourceforge для статьи, которую я пишу. Все данные свободно доступны в формате json по адресу http://sourceforge.net/api/project/name/[project name]/json. У меня есть список из нескольких тысяч этих URL-адресов, и я использую следующий код.
import grequests
rs = (grequests.get(u) for u in ulist)
answers = grequests.map(rs)
Используя этот код, я могу получить данные для любых 200 или около того проектов, которые мне нравятся, т.е. rs = (grequests.get(u) for u in ulist[0:199])
работает, но как только я перейду, все попытки встретятся с
ConnectionError: HTTPConnectionPool(host='sourceforge.net', port=80): Max retries exceeded with url: /api/project/name/p2p-fs/json (Caused by <class 'socket.gaierror'>: [Errno 8] nodename nor servname provided, or not known)
<Greenlet at 0x109b790f0: <bound method AsyncRequest.send of <grequests.AsyncRequest object at 0x10999ef50>>(stream=False)> failed with ConnectionError
Затем я не могу сделать больше запросов, пока не выйду из python, но как только я перезапущу python, я смогу сделать еще 200 запросов.
Я пытался использовать grequests.map(rs,size=200)
но это, похоже, ничего не делает.
2 ответа
Итак, я отвечаю здесь, может быть, это поможет другим.
В моем случае это было не ограничение скорости целевым сервером, а нечто гораздо более простое: я не закрывал отклики явно, поэтому они оставляли сокет открытым, и у процесса python заканчивались файловые дескрипторы.
Мое решение (не знаю наверняка, какой из них исправил проблему - теоретически любой из них должен был) было:
Задавать
stream=False
вgrequests.get
:rs = (grequests.get(u, stream=False) for u in urls)
Звоните явно
response.close()
после того, как я прочитал response.content:responses = grequests.map(rs) for response in responses: make_use_of(response.content) response.close()
Примечание: просто уничтожить response
объект (присвоение None
к нему, звоня gc.collect()
) было недостаточно - это не закрыло обработчики файлов.
Это можно легко изменить, чтобы использовать любое количество подключений.
MAX_CONNECTIONS = 100 #Number of connections you want to limit it to
# urlsList: Your list of URLs.
results = []
for x in range(1,pages+1, MAX_CONNECTIONS):
rs = (grequests.get(u, stream=False) for u in urlsList[x:x+MAX_CONNECTIONS])
time.sleep(0.2) #You can change this to whatever you see works better.
results.extend(grequests.map(rs)) #The key here is to extend, not append, not insert.
print("Waiting") #Optional, so you see something is done.