我有一个scraper(基于Python 3.4.2和asyncio / aiohttp libs)和一堆链接(> 10K)来检索一些少量数据。 刮刀代码的一部分:
@asyncio.coroutine
def prepare(self, links):
semaphore = asyncio.Semaphore(self.limit_concurrent)
tasks = []
result = []
tasks = [self.request_data(link, semaphore) for link in links]
for task in asyncio.as_completed(tasks):
response = yield from task
if response:
result.append(response)
task.close()
return result
@asyncio.coroutine
def request_data(self, link, semaphore):
...
with (yield from semaphore):
while True:
counter += 1
if counter >= self.retry:
break
with aiohttp.Timeout(self.timeout):
try:
response = yield from self.session.get(url, headers=self.headers)
body = yield from response.read()
break
except asyncio.TimeoutError as err:
logging.warning('Timeout error getting {0}'.format(url))
return None
except Exception:
return None
...
如果它试图向格式错误的URL发出请求,我会收到这样的消息:
Future exception was never retrieved
future: <Future finished exception=gaierror(11004, 'getaddrinfo failed')>
Traceback (most recent call last):
File "H:\Python_3_4_2\lib\concurrent\futures\thread.py", line 54, in run
result = self.fn(*self.args, **self.kwargs)
File "H:\Python_3_4_2\lib\socket.py", line 530, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11004] getaddrinfo failed
尝试从session.get产生响应时发生错误。据我所知,异常从未被asyncio消耗,所以它不是“喋喋不休”。
首先,我尝试通过try / except:
简单地包装请求try:
response = yield from self.session.get(url, headers=self.headers)
except Exception:
return None
这不起作用。
然后我read here关于链接协程以捕获异常但这对我来说也不起作用。在一段时间后,我仍然会收到这些消息和脚本崩溃。
所以我的问题 - 如何以正确的方式处理此异常?
答案 0 :(得分:2)
不是您问题的答案,但可能是您问题的解决方案,取决于您是否只想让代码正常工作。
我会在请求之前验证URL。我有很多令人头疼的事情,试图收集一些数据,所以我决定先解决这些问题,并将错误的网址报告给日志。
您可以使用django的正则表达式或其他代码来执行此操作,因为它可以公开使用。
在这个问题中,一个人为django提供了验证正则表达式。 Python - How to validate a url in python ? (Malformed or not)