异步网页爬虫与同步版本耗时相同的问题排查
问题分析与解决方案
你的异步代码没体现性能优势,核心原因是所有网络IO操作都是同步阻塞的,导致asyncio的事件循环无法并发执行任务,最终和同步版本的执行逻辑完全一致。
具体问题点:
- 同步HTTP请求阻塞事件循环:
get_html_data用的是requests.get,这是同步阻塞调用。在异步函数里执行这类同步IO时,整个事件循环会被挂起,直到请求完成,其他异步任务根本没机会执行,本质上还是串行运行。 - 同步方法阻塞异步流程:
__get_function_data是普通同步方法,内部调用了同步的get_html_data;而get_info虽然标记为async,但里面直接调用这个同步方法,同样会阻塞事件循环,无法实现任务切换。 - (次要问题)
data变量作用域错误:__get_functions里定义的data,在get_info里直接data.append会报错(除非是全局变量),这会导致数据无法正确收集。
修复方案:
- 替换为异步HTTP库:用
aiohttp替代requests,实现异步网络请求。 - 改造IO相关方法为异步:
- 把
get_html_data改成异步方法,使用aiohttp.ClientSession发起请求。 - 把
__get_function_data改成异步方法,内部await异步的get_html_data。 - 在
get_info里await __get_function_data(href),确保异步流程不被阻塞。
- 把
- 修正数据收集的作用域问题:比如把
data作为参数传递给get_info,或者用类的实例变量存储。
示例修正后的关键代码片段:
# 异步获取HTML文本 async def get_html_data(cls, url, session): async with session.get(url, headers=HEADERS) as response: return await response.content.read() # 异步获取二级页面数据 async def __get_function_data(self, href, session): html = await self.get_html_data(href, session) soup = bs4.BeautifulSoup(html, self.PARSER_MODE) # 后续解析逻辑保持不变 data = [self.check_each_info(soup, key) for key in [ "FUNCTION_DESCRIPTION", "FUNCTION_SYNTAX", "VERSION", "ARGS", "RETURN"]] clean_data = [*map(self.get_clean_text, data)] return dict(zip(["desc", "syntax", "version", "args", "return"], clean_data)) # 异步处理单个条目 async def get_info(self, li, session, data): a = li.find("a") name = a.text href = fr"https://examplewebsite.com/{a.get('href')}" info = await self.__get_function_data(href, session) data.append({"Name": name, **info}) # 主异步函数 async def __get_functions(self): data = [] # 创建aiohttp会话(复用连接提升性能) async with aiohttp.ClientSession() as session: # 异步获取首页HTML html = await self.get_html_data(URL, session) soup = bs4.BeautifulSoup(html, self.PARSER_MODE) lists = soup.findAll(**HTML_TAGS["FUNCTION_LIST"]) for ul in lists: li_items = ul.findAll("li") # 传递session和data到每个任务 tasks = [asyncio.create_task(self.get_info(li, session, data)) for li in li_items] done, pending = await asyncio.wait(tasks) self.save_as_json(data)
内容的提问来源于stack exchange,提问作者CodeX
相关产品推荐
相关产品推荐

