网站建设网站搭建全网营销的渠道
2026/5/21 18:13:19 网站建设 项目流程
网站建设网站搭建,全网营销的渠道,一般营销方式三大步骤,简述网站推广的方法在网络爬虫开发中#xff0c;高并发是提升爬取效率的核心需求 —— 传统同步爬虫因 “请求发送后等待响应” 的阻塞特性#xff0c;在面对大量页面爬取时效率极低。而 Python 的asyncio#xff08;异步 IO 框架#xff09;结合aiohttp#xff08;异步 HTTP 客户端#xf…在网络爬虫开发中高并发是提升爬取效率的核心需求 —— 传统同步爬虫因 “请求发送后等待响应” 的阻塞特性在面对大量页面爬取时效率极低。而 Python 的asyncio异步 IO 框架结合aiohttp异步 HTTP 客户端能让爬虫在等待网络响应的间隙处理其他请求实现非阻塞的高并发爬取轻松应对海量页面的爬取需求。本文将从核心原理、环境准备、完整实现到优化技巧手把手教你打造高性能异步爬虫。一、核心原理为什么 aiohttpasyncio 能实现高并发要理解异步爬虫的高并发本质需先理清两个核心组件的作用及异步编程的核心逻辑asyncioPython 内置的异步 IO 框架核心是事件循环Event Loop—— 作为异步任务的 “调度中心”它会不断监听任务状态当某个任务因网络请求、IO 操作进入 “等待状态” 时立即切换到其他就绪任务执行避免 CPU 空等最大化利用资源。aiohttp专为asyncio设计的异步 HTTP 客户端库替代了同步的requests库支持异步发送 HTTP 请求与asyncio的事件循环完美兼容不会因单个请求的网络延迟阻塞整个程序。异步核心优势同步爬虫是 “单线程串行执行”一个请求完成再发下一个而异步爬虫是 “单线程多任务并发”同时发起多个请求等待响应时处理其他任务在网络 IO 密集型的爬虫场景中效率能提升数倍甚至数十倍。同步与异步的核心区别同步请求1发送 → 等待响应 → 处理数据 → 请求2发送全程阻塞异步请求1发送 → 立即发送请求2 → … → 某个请求响应完成 → 处理该请求数据无空闲等待二、环境准备仅需安装异步 HTTP 客户端aiohttpasyncio是 Python3.4 内置模块无需额外安装bash运行pip install aiohttp -i https://pypi.tuna.tsinghua.edu.cn/simple推荐 Python 版本3.7对异步语法的支持更完善避免低版本的兼容性问题三、完整实现高并发异步爬虫开发以爬取通用测试站点http://httpbin.org/get为例实现一个可配置、高并发的异步爬虫包含请求发送、响应处理、异常捕获、并发控制等核心功能直接可运行。3.1 完整代码python运行import asyncio import aiohttp from typing import List, Dict import logging # 配置日志方便查看爬取过程和异常信息 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, datefmt%Y-%m-%d %H:%M:%S ) logger logging.getLogger(__name__) # 爬虫核心配置可根据需求修改 CONFIG { TARGET_URLS: [fhttp://httpbin.org/get?page{i} for i in range(1, 101)], # 待爬取100个测试链接 CONCURRENT_LIMIT: 20, # 最大并发数关键避免请求过多被封IP TIMEOUT: 10, # 单个请求超时时间秒 HEADERS: { # 请求头模拟浏览器避免被反爬 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 } } async def fetch(session: aiohttp.ClientSession, url: str) - Dict: 单个URL的异步请求函数发送请求、处理响应、捕获异常 :param session: 共享的aiohttp客户端会话关键减少资源开销 :param url: 待爬取的URL :return: 爬取的结果字典格式包含URL和响应数据 try: # 异步发送GET请求设置超时和请求头 async with session.get( urlurl, headersCONFIG[HEADERS], timeoutaiohttp.ClientTimeout(totalCONFIG[TIMEOUT]) ) as response: # 异步解析JSON响应aiohttp的方法均为async需加await data await response.json() logger.info(f成功爬取{url}状态码{response.status}) return {url: url, status: response.status, data: data} except aiohttp.ClientError as e: # 捕获HTTP请求相关异常连接失败、超时、状态码错误等 logger.error(f请求异常{url}错误信息{str(e)}) except Exception as e: # 捕获其他未知异常 logger.error(f未知异常{url}错误信息{str(e)}) return {url: url, status: -1, data: None, error: str(e)} async def main(): 主异步函数创建会话、创建任务、控制并发、执行任务、收集结果 # 1. 创建aiohttp.ClientSession全局共享整个爬虫仅创建一次 # 作用复用TCP连接减少网络资源开销提升并发效率 async with aiohttp.ClientSession() as session: # 2. 创建信号量Semaphore控制最大并发数 # 原理维护一个计数器获取信号量时-1释放时1计数器为0时阻塞新任务 semaphore asyncio.Semaphore(CONFIG[CONCURRENT_LIMIT]) # 3. 定义带并发控制的任务包装函数 async def bounded_fetch(url: str): # async with semaphore自动获取和释放信号量无需手动操作 async with semaphore: return await fetch(session, url) # 4. 创建所有异步任务列表推导式 # 注意asyncio.create_task()将协程包装为任务立即加入事件循环等待执行 tasks [asyncio.create_task(bounded_fetch(url)) for url in CONFIG[TARGET_URLS]] # 5. 等待所有任务执行完成收集结果gather并发执行多个任务 # return_exceptionsTrue某个任务异常时不终止整个爬虫仅返回异常对象 results await asyncio.gather(*tasks, return_exceptionsTrue) # 6. 处理爬取结果过滤异常、统计成功/失败数 success_count sum(1 for res in results if isinstance(res, dict) and res[status] 200) fail_count len(CONFIG[TARGET_URLS]) - success_count logger.info(f爬取完成总任务数{len(CONFIG[TARGET_URLS])}成功{success_count}失败{fail_count}) # 可选保存结果到本地如JSON文件 # import json # with open(crawl_results.json, w, encodingutf-8) as f: # json.dump(results, f, ensure_asciiFalse, indent2) if __name__ __main__: # 核心启动asyncio事件循环执行主异步函数 # Python3.7简化语法asyncio.run()自动创建和关闭事件循环 asyncio.run(main())3.2 核心组件详解1aiohttp.ClientSession共享会话的重要性ClientSession是 aiohttp 的核心对象整个爬虫仅需创建一次所有请求共享该会话底层复用 TCP 连接避免为每个请求创建新连接的资源开销统一管理 Cookie、请求头、超时配置简化代码支持连接池提升高并发下的请求效率。注意必须使用async with管理会话确保任务完成后自动释放资源。2asyncio.Semaphore并发数的关键控制异步爬虫的最大坑是无限制发起并发请求会导致目标服务器拒绝连接429/503、本地端口耗尽甚至 IP 被封。asyncio.Semaphore(N)的作用是限制同时执行的任务数为N通过async with semaphore实现自动加锁 / 释放无需手动调用acquire()和release()简洁且安全。并发数建议根据目标网站的反爬策略调整一般建议 10-50反爬严格的网站可设置为 5-10。3asyncio.gather批量任务的并发执行asyncio.gather(*tasks, return_exceptionsTrue)是批量执行异步任务的核心方法*tasks解包任务列表将多个任务传入return_exceptionsTrue核心参数某个任务抛出异常时不会终止整个爬虫而是将异常对象作为结果返回保证其他任务正常执行返回值与任务列表顺序一致的结果列表方便后续统一处理。四、关键注意事项避免异步爬虫踩坑4.1 禁用同步 IO 操作异步编程的核心原则事件循环中不能有同步阻塞的 IO 操作如requests.get()、time.sleep()、open()的同步读取、数据库的同步连接。这些操作会阻塞整个事件循环导致异步爬虫退化为 “同步爬虫”完全丧失高并发优势。替代方案网络请求用aiohttp替代requests延时操作用asyncio.sleep()替代time.sleep()文件操作用aiofiles替代原生open()数据库操作用asyncpgPostgreSQL、aiomysqlMySQL替代同步数据库驱动。4.2 全局共享 ClientSession禁止重复创建错误做法在fetch函数内部每次创建ClientSessionpython运行# 错误每次请求创建新会话资源开销大无连接复用 async def fetch(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: pass正确做法在主函数main中创建一次ClientSession通过参数传递给fetch函数所有请求共享该会话如示例代码所示。4.3 所有异步操作必须加 awaitaiohttp 的所有 IO 相关方法session.get()、response.json()、response.text()、asyncio 的方法asyncio.sleep()、asyncio.gather()都是协程对象必须在前面加await才能执行否则仅会创建协程对象不会实际运行。典型错误python运行data response.json() # 错误未加await仅返回协程对象无实际数据 data await response.json() # 正确异步解析响应五、进阶优化让爬虫更稳定、更高效5.1 增加请求重试机制网络波动、临时的服务器错误500/502会导致请求失败增加重试机制可提升爬取成功率python运行from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type # 为fetch函数增加重试最多3次指数退避等待1s→2s→4s仅对ClientError重试 retry( stopstop_after_attempt(3), waitwait_exponential(multiplier1, min1, max4), retryretry_if_exception_type(aiohttp.ClientError), before_sleeplambda retry_state: logger.info(f重试{retry_state.fn.__name__}第{retry_state.attempt_number}次) ) async def fetch(session: aiohttp.ClientSession, url: str) - Dict: # 原有fetch逻辑不变 pass需安装依赖pip install tenacity5.2 随机延时与请求头轮换针对有反爬的网站在请求之间增加随机异步延时并轮换User-Agent、Referer等请求头模拟真实浏览器行为python运行# 1. 定义请求头池 USER_AGENTS [ Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) Firefox/121.0 Safari/537.36, Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) Safari/605.1.15 ] # 2. 带随机延时的bounded_fetch async def bounded_fetch(url: str): async with semaphore: # 随机延时0.5-2秒异步延时不阻塞事件循环 await asyncio.sleep(random.uniform(0.5, 2)) # 随机选择User-Agent headers CONFIG[HEADERS].copy() headers[User-Agent] random.choice(USER_AGENTS) return await fetch(session, url, headers) # 传递新的请求头5.3 分布式异步爬虫当爬取量达到百万级甚至千万级时单台机器的性能有限可结合Redis实现分布式异步爬虫用 Redis 的列表List作为任务队列存储所有待爬取的 URL多台机器或多个进程运行相同的异步爬虫代码从 Redis 队列中取 URL 爬取用 Redis 的集合Set做去重避免重复爬取每台机器内部仍通过Semaphore控制单进程并发数。核心依赖aioredis异步 Redis 客户端替代同步的redis-py。5.4 数据持久化的异步优化避免用原生open()同步写入数据阻塞事件循环使用aiofiles实现异步文件操作或用异步数据库驱动将数据写入数据库python运行import aiofiles # 异步保存结果到JSON文件 async def save_results(results: List[Dict]): async with aiofiles.open(crawl_results.json, w, encodingutf-8) as f: import json await f.write(json.dumps(results, ensure_asciiFalse, indent2)) # 在main函数中调用 await save_results(results)六、同步爬虫 vs 异步爬虫效率对比以爬取 100 个网络链接为例对比 ** 同步爬虫requests和异步爬虫aiohttpasyncio** 的耗时测试环境网络延迟约 100ms单进程爬虫类型并发数总耗时核心问题同步爬虫requests1串行约 10 秒全程阻塞CPU 空等异步爬虫aiohttp20约 0.8 秒无阻塞资源利用率最大化结论在 IO 密集型的爬虫场景中异步爬虫的效率远高于同步爬虫且并发数越高效率提升越明显。七、总结本文详细讲解了基于aiohttpasyncio的高并发异步爬虫的实现原理和完整流程核心要点可总结为 3 个核心、4 个注意、5 个优化核心要点异步核心asyncio的事件循环实现任务调度aiohttp实现异步 HTTP 请求两者结合突破同步阻塞的效率瓶颈资源复用全局共享aiohttp.ClientSession复用 TCP 连接减少资源开销并发控制通过asyncio.Semaphore严格限制最大并发数避免被反爬或资源耗尽。核心注意禁用所有同步 IO 操作替换为对应的异步库仅创建一次ClientSession全局共享所有异步协程方法必须加await才能执行用asyncio.gather(return_exceptionsTrue)保证爬虫的健壮性。进阶优化增加重试机制提升爬取成功率随机延时 请求头轮换规避反爬用aiofiles/ 异步数据库实现异步数据持久化结合 Redis 实现分布式异步爬虫处理海量任务增加日志和监控方便问题排查。aiohttpasyncio是 Python 实现高并发网络爬虫的最优组合之一掌握其核心思想和使用技巧不仅能打造高性能爬虫还能将异步编程思维应用到其他 IO 密集型场景如异步接口、消息队列消费等大幅提升程序的运行效率。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询