我想为动态等待的抓取工具创建自定义请求管理器 我的爬虫需要向禁止来自同一IP地址的并行请求的站点发出请求。如果发生这种阻塞请求返回HTTP错误代码403,503,429等 如果出现错误,我想等一段时间再重复一次请求。但是为了简化解析器,他们只需调用get并接收正确的页面 我想使用 aiohttp 和 async Python 3.5 的语法,因此我的解析器类可以使用 async with 我的请求者类如果使用 aiohttp.ClientSession ,就会这样:
# 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.ClientSession ,那么响应是 aiohtpp.ClientResponse ,其中 __ aenter__ 和 __ aexit __ 方法,因此 async with 按预期工作。
但是,如果我将请求者类放在中间,它就不再起作用了。
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>
看起来像这样。
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
根据我的理解 self.session.get 是协程功能所以我等待它。结果是 aiohttp.ClientResponse ,其中 __ aenter __ 或 __ aexit __ 。但是如果返回解析器的 async with 的代码块返回奇数错误。
与 aiohttp.ClientSession 一样,您能说出我需要替换为请求者类的内容吗?