2016-05-30 9 views
2

私は、動的待ちでクローラ用のカスタムリクエストマネージャを作成したいと思います。
私のクローラは、同じIPアドレスからの並列要求を禁止するサイトへのリクエストを行う必要があります。このようなブロッキングが発生した場合、HTTPエラーコード403,503,429などで返されます。
エラーが発生した場合は、しばらくお待ちください。しかしパーサーの簡潔さのために、彼らは単に正しいページを取得して受け取るように呼び出します。
私は私のパーサクラスは、彼らがこのようaiohttp.ClientSessionを使用した場合、私の依頼者クラスと同じ道をで非同期を使用することができますのPython 3.5 構文でaiohttpと新しい非同期を使用します:
aiohttpのデリゲート/ネストされた非同期コンテキストマネージャを作成するには?

# somewhere in a parser 
async def get_page(self, requester, page_index): 
    async with requester.get(URL_FMT.format(page_index)) as response: 
    html_content = await response.read() 
    result = self.parsing_page(html_content) 
    return result 

依頼者aiohttp.Clieある場合ntSessionは、その後、応答__aenter____aexit__メソッドを持ってaiohtpp.ClientResponse、期待どおりに動作しとそう非同期ある
私がリクエスタクラスを真ん中に置くと、もう動作しません。

Traceback (most recent call last): 
    File "/opt/project/api/tornado_runner.py", line 6, in <module> 
    from api import app 
    File "/opt/project/api/api.py", line 20, in <module> 
    loop.run_until_complete(session.login()) 
    File "/usr/local/lib/python3.5/asyncio/base_events.py", line 337, in run_until_complete 
    return future.result() 
    File "/usr/local/lib/python3.5/asyncio/futures.py", line 274, in result 
    raise self._exception 
    File "/usr/local/lib/python3.5/asyncio/tasks.py", line 239, in _step 
    result = coro.send(None) 
    File "/opt/project/api/viudata/session.py", line 72, in login 
    async with self.get('https://www.viudata.com') as resp: 
AttributeError: __aexit__ 
Unclosed client session 
client_session: <aiohttp.client.ClientSession object at 0x7f44f61ef240> 

これは次のようです。私の理解self.session.getから

class Requester: 
    def __init__(self, session: aiohttp.ClientSession): 
    self.session = session 

    async def get(self, *args, **kwargs): 
    is_result_successful = False 
    while not is_result_successful: 
     response = await self.session.get(*args, **kwargs) 
     if response.status in [503, 403, 429]: 
      await self.wait_some_time() 
     else: 
      is_result_successful = True 
    return response 

ので、私はそれを待っていますコルーチン機能です。結果はaiohttp.ClientResponseで、__aenter__または__aexit__です。しかし、それを返す場合パーサーのコード非同期とブロック戻り奇妙なエラー。

は私がaiohttp.ClientSessionと同じように私の依頼者クラスにに交換する必要が何を言うことはできますか?

+0

[mcve]を使用して*「それはもう機能していません」*に展開できますか? – jonrsharpe

答えて

1

async withプロトコルをサポートするための追加コードを記述する必要があります。

インスピレーションのためにclient.request()_RequestContextManagerを参照してください。

+0

私が始める必要があるポイント私に感謝します。しかし、新しい構文砂糖が解決するよりも多くの問題を作り出すことは非常に悲しいことです。特にシンプルなデコレータを実装するため。 – Tarhan

+0

通常のpython関数はコンテキストマネージャでもありません。関数とコンテキストマネージャの両方として機能させるには、いくつかのトリックを行う必要があります。 –

関連する問題