web-dev-qa-db-ja.com

grequestsを使用してsourceforgeに数千のgetリクエストを作成し、「URLで最大再試行回数を超えました」を取得します

私はこれらすべてに非常に慣れていません。私が書いている論文のために、数千の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)を使ってみましたが、何も起こらないようです。

22
crf

だから、私はここで答えています、多分それは他の人を助けるでしょう。

私の場合、宛先サーバーによるレート制限ではありませんでしたが、もっと単純なものでした。応答を明示的に閉じなかったため、ソケットを開いたままにして、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()を呼び出す)だけでは不十分でした-これはファイルハンドラーを閉じませんでした。

24
Virgil

これは、必要な数の接続を使用するように簡単に変更できます。

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. 
2
MaikelDotUk