恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Python异步编程与高并发爬虫实战指南

  • 首页
  • 资讯中心
  • /
  • Python异步编程与高并发爬虫实战指南

相关资讯

从Codex到Workbuddy:AI编程工具切换实录与避坑指南 2026/9/16 10:22:35
Tkinter电话本实战:PyCharm下开发可商用的本地GUI联系人系统 2026/9/16 10:22:35
2026年SCI论文AI检测工具与降AI率实战技巧 2026/9/16 10:22:35

最新资讯

Hertz v0.5.2 版本深度解析:多值 Header 访问 API(PeekAll/GetAll)与 amd64/Windows 关键缺陷修复
使用 SkyPilot 部署 LoRAX:单 GPU 托管数千个微调 LLM 的多适配器推理服务器
Loop:免费开源的 macOS 窗口管理器,3 步把分屏变成肌肉记忆
FiftyOne 插件生态系统完全指南:从发现、安装到开发与共享
gogcli 日历变更追踪:使用 `gog calendar changed` 列出最近修改与已删除事件
Velero 插件体系深度解析:四种插件类型、命名规范与实现原理

今日推荐

IoT-For-Beginners 智能语音计时器:Wio Terminal 基于 DMAC 与 Flash 的音频采集实战
基于MATLAB的CRI显色指数计算:从SPD光谱到Ra的完整流程
JSP+Servlet+MySQL博客系统源码部署与优化全攻略

本周热门

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化
Flutter应用改名全指南:从Android到iOS的配置与工具实践

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

Python异步编程与高并发爬虫实战指南

发布时间:2026/9/16 10:22:35
Python异步编程与高并发爬虫实战指南 1. 为什么需要异步编程当你在Python中编写一个简单的爬虫程序时可能会遇到这样的问题程序大部分时间都在等待网络响应而不是真正处理数据。这就是典型的I/O密集型场景而异步编程正是为此而生的解决方案。传统的同步编程模型下当你的爬虫发送一个HTTP请求后整个程序就会阻塞在那里直到收到响应才能继续执行。想象一下如果你要爬取100个网页每个请求耗时1秒那么总耗时就是100秒——即使大部分时间都在等待网络响应。# 传统同步爬虫示例 import requests def fetch(url): response requests.get(url) return response.text urls [http://example.com/page1, http://example.com/page2, ...] for url in urls: content fetch(url) # 这里会阻塞 process(content)2. asyncio核心概念解析2.1 事件循环(Event Loop)事件循环是asyncio的核心它负责调度和执行协程。你可以把它想象成一个高效的交通警察指挥着所有协程的交通。import asyncio async def main(): print(Hello) await asyncio.sleep(1) print(World) # 获取事件循环并运行协程 loop asyncio.get_event_loop() loop.run_until_complete(main())2.2 协程(Coroutine)协程是异步编程的基本单位使用async def定义。与普通函数不同协程可以被暂停和恢复。重要提示仅仅调用协程函数不会执行它必须通过await或事件循环来运行。2.3 Future和TaskFuture代表一个异步操作的最终结果而Task是Future的子类用于包装协程。当你在asyncio中创建任务时实际上是在调度协程的执行。async def my_coroutine(): return 42 # 创建任务 task asyncio.create_task(my_coroutine())3. 构建异步HTTP客户端3.1 aiohttp基础使用aiohttp是Python中流行的异步HTTP客户端/服务器框架。与requests不同它完全基于asyncio构建。import aiohttp import asyncio async def fetch(session, url): async with session.get(url) as response: return await response.text() async def main(): async with aiohttp.ClientSession() as session: html await fetch(session, http://python.org) print(html[:200]) # 打印前200个字符 asyncio.run(main())3.2 连接池与超时设置在实际爬虫项目中合理配置连接池和超时参数至关重要# 自定义连接池和超时 connector aiohttp.TCPConnector( limit30, # 最大连接数 limit_per_host5, # 每个主机最大连接数 force_closeTrue, enable_cleanup_closedTrue ) timeout aiohttp.ClientTimeout(total10) # 总超时10秒 async with aiohttp.ClientSession( connectorconnector, timeouttimeout ) as session: # 使用session进行请求4. 高并发爬虫实战4.1 基本并发爬虫实现让我们实现一个能并发爬取多个URL的爬虫async def fetch_url(session, url): try: async with session.get(url) as response: if response.status 200: return await response.text() return None except Exception as e: print(fError fetching {url}: {e}) return None async def crawl(urls): async with aiohttp.ClientSession() as session: tasks [fetch_url(session, url) for url in urls] return await asyncio.gather(*tasks) # 使用示例 urls [http://example.com/page1, http://example.com/page2, ...] results asyncio.run(crawl(urls))4.2 并发控制与限速不加限制的高并发可能会对目标服务器造成压力甚至导致你的IP被封。我们可以使用信号量(Semaphore)来控制并发度async def fetch_with_semaphore(sem, session, url): async with sem: return await fetch_url(session, url) async def controlled_crawl(urls, concurrency10): sem asyncio.Semaphore(concurrency) async with aiohttp.ClientSession() as session: tasks [fetch_with_semaphore(sem, session, url) for url in urls] return await asyncio.gather(*tasks)4.3 生产者-消费者模式对于大规模爬虫生产者-消费者模式更为高效async def producer(queue, urls): for url in urls: await queue.put(url) await queue.put(None) # 结束信号 async def consumer(queue, session, results): while True: url await queue.get() if url is None: break content await fetch_url(session, url) if content: results.append(content) queue.task_done() async def producer_consumer_crawl(urls, concurrency10): queue asyncio.Queue(maxsizeconcurrency*2) results [] async with aiohttp.ClientSession() as session: producers [asyncio.create_task(producer(queue, urls))] consumers [asyncio.create_task(consumer(queue, session, results)) for _ in range(concurrency)] await asyncio.gather(*producers) await queue.join() for c in consumers: c.cancel() return results5. 高级技巧与优化5.1 错误处理与重试机制网络请求难免会遇到各种错误合理的重试机制能提高爬虫的健壮性async def fetch_with_retry(session, url, max_retries3, delay1): for attempt in range(max_retries): try: async with session.get(url) as response: if response.status 200: return await response.text() elif response.status 429: # Too Many Requests await asyncio.sleep(delay * (attempt 1)) continue return None except (aiohttp.ClientError, asyncio.TimeoutError) as e: if attempt max_retries - 1: raise await asyncio.sleep(delay * (attempt 1)) return None5.2 代理与User-Agent轮换为了避免被目标网站封禁我们可以使用代理和随机User-Agentfrom fake_useragent import UserAgent ua UserAgent() async def fetch_with_proxy(session, url, proxyNone): headers {User-Agent: ua.random} try: async with session.get(url, proxyproxy, headersheaders) as response: return await response.text() except Exception as e: print(fError with proxy {proxy}: {e}) return None5.3 性能监控与调试使用asyncio的内置工具监控协程执行async def monitored_crawl(urls): start asyncio.get_event_loop().time() async with aiohttp.ClientSession() as session: tasks [fetch_url(session, url) for url in urls] done, pending await asyncio.wait(tasks, timeout30) print(fCompleted {len(done)} tasks in {asyncio.get_event_loop().time() - start:.2f}s) return [task.result() for task in done]6. 遵守robots.txt与道德爬虫虽然技术让我们能够高效爬取数据但我们必须遵守robots.txt协议和合理的爬取频率import urllib.robotparser async def check_robots_txt(session, base_url): rp urllib.robotparser.RobotFileParser() robots_url f{base_url.rstrip(/)}/robots.txt try: async with session.get(robots_url) as response: if response.status 200: rp.parse((await response.text()).splitlines()) return rp except Exception: pass return None async def ethical_fetch(session, url): base_url /.join(url.split(/)[:3]) rp await check_robots_txt(session, base_url) if rp and not rp.can_fetch(*, url): print(fSkipping {url} due to robots.txt restrictions) return None return await fetch_with_retry(session, url)在实际项目中我通常会设置至少1秒的延迟between requests to the same domain并严格遵守robots.txt中的Crawl-delay指令。这不仅是对目标网站的尊重也能避免因请求过于频繁而导致IP被封。异步编程确实能大幅提升爬虫效率但记住能力越大责任越大。合理控制并发数设置适当的延迟避免对目标网站造成过大压力。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号