私はこれらすべてに非常に慣れていません。私が書いている論文のために、数千のsourceforgeプロジェクトに関するデータを取得する必要があります。データはすべて、URLhttp://sourceforge.net/api/project/name/ [プロジェクト名]/jsonで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)
を使ってみましたが、何も起こらないようです。
だから、私はここで答えています、多分それは他の人を助けるでしょう。
私の場合、宛先サーバーによるレート制限ではありませんでしたが、もっと単純なものでした。応答を明示的に閉じなかったため、ソケットを開いたままにして、pythonプロセスを実行しました。ファイルハンドルが不足しています。
私の解決策(どちらが問題を修正したかはわかりません-理論的にはどちらかが解決すべきです)は次のとおりでした:
_stream=False
_を_grequests.get
_に設定します。
_rs = (grequests.get(u, stream=False) for u in urls)
_
Response.contentを読んだ後、明示的にresponse.close()
を呼び出します。
_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.