当前位置: 首页 > article >正文

Python异步爬虫实战:aiohttp并发采集与验证码异步处理完整教程

前言爬虫效率是每个数据工程师都关心的问题。当你需要采集上万个页面时同步请求一个一个排队等待的方式实在太慢了。Python的asyncio aiohttp组合可以让你的爬虫速度提升10-50倍而且代码改动并不大。本文将从零开始讲解异步爬虫的原理和实战包括并发控制、错误处理、以及如何在异步流程中处理验证码。同步 vs 异步为什么差这么多同步爬虫的瓶颈importrequestsimporttime urls[fhttps://httpbin.org/delay/1for_inrange(10)]starttime.time()forurlinurls:resprequests.get(url)print(f{resp.status_code},end )print(f\n同步耗时:{time.time()-start:.1f}秒)# 输出: 同步耗时: 10.3秒 (每个请求等1秒串行排队)问题很明显每个请求都在等网络IO返回CPU其实在空闲。异步爬虫的优势importaiohttpimportasyncioimporttimeasyncdeffetch(session,url):asyncwithsession.get(url)asresp:returnresp.statusasyncdefmain():urls[fhttps://httpbin.org/delay/1for_inrange(10)]asyncwithaiohttp.ClientSession()assession:tasks[fetch(session,url)forurlinurls]resultsawaitasyncio.gather(*tasks)print(f状态码:{results})starttime.time()asyncio.run(main())print(f异步耗时:{time.time()-start:.1f}秒)# 输出: 异步耗时: 1.2秒 (10个请求并发几乎同时完成)10个请求从10秒变成1秒这就是异步的威力。aiohttp基础安装pipinstallaiohttpSession管理importaiohttpimportasyncioasyncdefmain():# 创建session复用TCP连接性能更好asyncwithaiohttp.ClientSession()assession:# GET请求asyncwithsession.get(https://httpbin.org/get)asresp:dataawaitresp.json()print(data)# POST请求asyncwithsession.post(https://httpbin.org/post,json{key:value})asresp:dataawaitresp.json()print(data)# 自定义请求头headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0.0.0,Accept-Language:zh-CN,zh;q0.9,en;q0.8,}asyncwithsession.get(https://httpbin.org/headers,headersheaders)asresp:print(awaitresp.json())asyncio.run(main())超时和代理importaiohttpimportasyncioasyncdefmain():# 设置超时timeoutaiohttp.ClientTimeout(total30,connect10)# 设置代理proxyhttp://user:passproxy:8080asyncwithaiohttp.ClientSession(timeouttimeout)assession:asyncwithsession.get(https://httpbin.org/ip,proxyproxy)asresp:print(awaitresp.json())asyncio.run(main())并发控制Semaphore不加限制地并发会导致目标服务器拒绝连接甚至把自己的IP封了。用Semaphore控制并发数importaiohttpimportasyncioasyncdeffetch_with_limit(sem,session,url):asyncwithsem:# 信号量控制并发try:asyncwithsession.get(url)asresp:textawaitresp.text()return{url:url,status:resp.status,length:len(text)}exceptExceptionase:return{url:url,error:str(e)}asyncdefmain():urls[fhttps://httpbin.org/get?page{i}foriinrange(100)]semasyncio.Semaphore(10)# 最多同时10个请求connectoraiohttp.TCPConnector(limit20)# TCP连接池上限asyncwithaiohttp.ClientSession(connectorconnector)assession:tasks[fetch_with_limit(sem,session,url)forurlinurls]resultsawaitasyncio.gather(*tasks)success[rforrinresultsiferrornotinr]failed[rforrinresultsiferrorinr]print(f成功:{len(success)}, 失败:{len(failed)})asyncio.run(main())实战异步爬虫完整模板importaiohttpimportasynciofromdataclassesimportdataclassfromtypingimportOptionalimportloggingimportrandom logging.basicConfig(levellogging.INFO)loggerlogging.getLogger(__name__)dataclassclassScrapedItem:url:strtitle:strcontent:strstatus:intclassAsyncScraper:def__init__(self,concurrency10,delay_range(0.5,2.0),proxyNone):self.concurrencyconcurrency self.delay_rangedelay_range self.proxyproxy self.semasyncio.Semaphore(concurrency)self.results[]self.errors[]asyncdeffetch_page(self,session,url):asyncwithself.sem:# 随机延迟避免请求过于规律awaitasyncio.sleep(random.uniform(*self.delay_range))try:asyncwithsession.get(url,proxyself.proxy)asresp:ifresp.status200:htmlawaitresp.text()itemself.parse(url,html,resp.status)self.results.append(item)logger.info(f[OK]{url})returnitemelifresp.status403:logger.warning(f[403]{url}- 可能需要处理验证码)self.errors.append({url:url,status:403})else:logger.warning(f[{resp.status}]{url})self.errors.append({url:url,status:resp.status})exceptasyncio.TimeoutError:logger.error(f[TIMEOUT]{url})self.errors.append({url:url,error:timeout})exceptExceptionase:logger.error(f[ERROR]{url}:{e})self.errors.append({url:url,error:str(e)})defparse(self,url,html,status):# 替换为你的解析逻辑fromhtml.parserimportHTMLParser titleclassTitleParser(HTMLParser):defhandle_starttag(self,tag,attrs):nonlocaltitle self._in_titletagtitledefhandle_data(self,data):nonlocaltitleifgetattr(self,_in_title,False):titledata self._in_titleFalseparserTitleParser()parser.feed(html[:5000])returnScrapedItem(urlurl,titletitle,contenthtml[:500],statusstatus)asyncdefrun(self,urls):timeoutaiohttp.ClientTimeout(total30)connectoraiohttp.TCPConnector(limitself.concurrency*2)headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0.0.0,Accept:text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8,Accept-Language:zh-CN,zh;q0.9,en;q0.8,}asyncwithaiohttp.ClientSession(timeouttimeout,connectorconnector,headersheaders)assession:tasks[self.fetch_page(session,url)forurlinurls]awaitasyncio.gather(*tasks,return_exceptionsTrue)logger.info(f完成:{len(self.results)}成功,{len(self.errors)}失败)returnself.results# 使用asyncdefmain():scraperAsyncScraper(concurrency5,delay_range(1.0,3.0))urls[fhttps://httpbin.org/get?id{i}foriinrange(50)]resultsawaitscraper.run(urls)foriteminresults[:3]:print(f{item.title}-{item.url})asyncio.run(main())异步流程中处理验证码异步爬虫遇到验证码时不能阻塞整个事件循环。正确做法是将验证码解决也异步化importaiohttpimportasynciofrompassxapiimportAsyncPassXAPIclassAsyncScraperWithCaptcha:def__init__(self,captcha_api_key,concurrency10):self.semasyncio.Semaphore(concurrency)self.solverAsyncPassXAPI(api_keycaptcha_api_key)asyncdeffetch_with_captcha(self,session,url):asyncwithself.sem:asyncwithsession.get(url)asresp:htmlawaitresp.text()# 检测验证码ifdata-sitekeyinhtml:tokenawaitself._solve_captcha(html,url)iftoken:asyncwithsession.post(url,data{cf-turnstile-response:token,g-recaptcha-response:token,})asretry_resp:returnawaitretry_resp.text()returnhtmlasyncdef_solve_captcha(self,html,url):importrematchre.search(rdata-sitekey([^]),html)ifnotmatch:returnNonesitekeymatch.group(1)ifcf-turnstileinhtml:resultawaitself.solver.solve_turnstile(sitekeysitekey,urlurl)elifh-captchainhtml:resultawaitself.solver.solve_hcaptcha(sitekeysitekey,urlurl)else:resultawaitself.solver.solve_recaptcha(sitekeysitekey,urlurl)returnresult.get(token)asyncdefrun(self,urls):asyncwithaiohttp.ClientSession()assession:tasks[self.fetch_with_captcha(session,url)forurlinurls]returnawaitasyncio.gather(*tasks,return_exceptionsTrue)# 使用asyncdefmain():scraperAsyncScraperWithCaptcha(captcha_api_keyyour_passxapi_key,concurrency10)urls[https://protected-site.com/page/1,https://protected-site.com/page/2]resultsawaitscraper.run(urls)asyncio.run(main())生产者-消费者模式对于大规模爬取推荐使用asyncio.Queue实现生产者-消费者模式importasyncioimportaiohttpasyncdefproducer(queue,urls):forurlinurls:awaitqueue.put(url)# 发送结束信号for_inrange(5):# worker数量awaitqueue.put(None)asyncdefconsumer(queue,session,results,worker_id):whileTrue:urlawaitqueue.get()ifurlisNone:breaktry:asyncwithsession.get(url)asresp:dataawaitresp.text()results.append({url:url,length:len(data)})print(f[Worker-{worker_id}]{url}-{len(data)}bytes)exceptExceptionase:print(f[Worker-{worker_id}] Error:{url}-{e})queue.task_done()asyncdefmain():urls[fhttps://httpbin.org/get?id{i}foriinrange(30)]queueasyncio.Queue(maxsize20)results[]asyncwithaiohttp.ClientSession()assession:# 启动1个生产者 5个消费者producer_taskasyncio.create_task(producer(queue,urls))workers[asyncio.create_task(consumer(queue,session,results,i))foriinrange(5)]awaitproducer_taskawaitasyncio.gather(*workers)print(f总计采集:{len(results)}个页面)asyncio.run(main())性能优化技巧1. 连接池复用# 配置TCP连接池connectoraiohttp.TCPConnector(limit100,# 总连接数上限limit_per_host10,# 单个域名连接数ttl_dns_cache300,# DNS缓存5分钟enable_cleanup_closedTrue,)### 2. 流式读取大文件pythonasyncdefdownload_file(session,url,filepath):asyncwithsession.get(url)asresp:withopen(filepath,wb)asf:asyncforchunkinresp.content.iter_chunked(8192):f.write(chunk)### 3. 优雅关闭pythonimportsignalasyncdefgraceful_shutdown(scraper):print(收到退出信号正在优雅关闭...)scraper.runningFalse# 等待当前任务完成awaitasyncio.sleep(2)loopasyncio.get_event_loop()loop.add_signal_handler(signal.SIGINT,lambda:asyncio.create_task(graceful_shutdown(scraper)))常见坑不要在async函数中使用time.sleep会阻塞整个事件循环用await asyncio.sleep()Session要复用每个请求创建新Session浪费TCP连接并发不是越多越好过高并发会触发反爬建议5-20异常要捕获一个任务的异常不应该影响其他任务总结异步爬虫是提升采集效率的最有效手段aiohttp asyncio可以轻松实现10倍以上的速度提升用Semaphore控制并发数避免被封IP验证码解决也要异步化不能阻塞事件循环生产者-消费者模式适合大规模采集场景验证码异步解决方案可以参考passxapi-python提供AsyncPassXAPI异步客户端完美融入asyncio工作流。觉得有帮助请点赞收藏有问题欢迎评论区讨论。

相关文章:

Python异步爬虫实战:aiohttp并发采集与验证码异步处理完整教程

前言 爬虫效率是每个数据工程师都关心的问题。当你需要采集上万个页面时,同步请求一个一个排队等待的方式实在太慢了。 Python的asyncio aiohttp组合可以让你的爬虫速度提升10-50倍,而且代码改动并不大。 本文将从零开始讲解异步爬虫的原理和实战&am…...

pose-search:Web端人体姿态识别与动作检索的革新实践

pose-search:Web端人体姿态识别与动作检索的革新实践 【免费下载链接】pose-search x6ud.github.io/pose-search 项目地址: https://gitcode.com/gh_mirrors/po/pose-search 在计算机视觉与Web技术深度融合的今天,pose-search作为一款开源项目&am…...

【深度学习】RoBERTa:BERT的优化升级与实战应用

1. RoBERTa:BERT的全面进化 第一次接触RoBERTa时,我正为一个电商评论情感分析项目发愁。当时用BERT模型效果总是不稳定,直到尝试了RoBERTa,准确率直接提升了5个百分点。这个经历让我意识到,看似细微的技术改进在实际应…...

小白程序员快看!轻松入门大模型驱动的AI Agent,收藏这份超全学习指南!

本文以通俗易懂的语言介绍了AI Agent的概念、构成、分类及工作流程,并与传统软件进行了对比,阐述了AI Agent的核心优势。同时,文章还列举了AI Agent的常见应用场景,并推荐了5个适合新手使用的开发工具,最后通过一个实际…...

如何快速使用LivePortrait实现AI肖像动画:终极指南

如何快速使用LivePortrait实现AI肖像动画:终极指南 【免费下载链接】LivePortrait Bring portraits to life! 项目地址: https://gitcode.com/GitHub_Trending/li/LivePortrait LivePortrait 是一款革命性的AI肖像动画工具,能够将静态照片转化为栩…...

Stable-Diffusion-v1-5-archive生产环境部署:异常自动拉起+日志监控+多用户隔离方案

Stable-Diffusion-v1-5-archive生产环境部署:异常自动拉起日志监控多用户隔离方案 1. 引言 如果你正在寻找一个稳定、可靠、易于管理的Stable Diffusion v1.5生产环境部署方案,那么你来对地方了。SD1.5作为文生图领域的经典模型,虽然新模型…...

MySQL 8.0 等保合规实战:手把手配置开源审计插件 server_audit.so

MySQL 8.0 等保合规审计插件实战指南 在数字化转型浪潮中,数据库安全审计已成为企业合规运营的刚需。对于使用MySQL 8.0的企业而言,如何在不影响性能的前提下满足等保2.0三级及以上对数据库审计的要求,是每位DBA和安全工程师必须掌握的技能。…...

QLVideo终极指南:三步让Mac视频预览功能全面升级

QLVideo终极指南:三步让Mac视频预览功能全面升级 【免费下载链接】QuickLookVideo This package allows macOS Finder to display thumbnails, static QuickLook previews, cover art and metadata for most types of video files. 项目地址: https://gitcode.com…...

中兴B863AV3.2-M/B863AV3.1-M2_S905L3A_通刷_优化开机速度_指示灯绿色

中兴B863AV3.2-M/B863AV3.1-M2_S905L3A_通刷_优化开机速度_指示灯绿色线刷方法:1、准备好一根双公头USB线刷刷机线,长度30-50CM长度最佳,同时准备一台电脑;2、电脑上安装好刷机工具Amlogic USB Burning Tool 软件 →打…...

requests - 简单好用的HTTP请求库

一、什么是requests? requests 是一个用于发送HTTP请求的 Python 库。 它可以帮助你: 轻松发送GET、POST、PUT、DELETE等请求处理Cookie、会话等复杂性自动解压缩内容处理国际化域名和URL 二、应用场景 requests 广泛应用于以下实际场景:…...

Tomcat安全防护指南:如何防御CVE-2017-12615和CNVD-2020-10487漏洞攻击

Tomcat安全防护实战:从漏洞原理到企业级防御体系构建 最近在帮某金融客户做安全审计时,发现他们的Tomcat服务器竟然还开着AJP端口,而且管理后台用的还是默认密码。这让我想起去年处理过的一次安全事件——攻击者仅用3小时就通过CVE-2017-1261…...

从零手写感知机到MindSpore实战:一份完整的鸢尾花分类作业避坑指南

从零手写感知机到MindSpore实战:一份完整的鸢尾花分类作业避坑指南 鸢尾花分类是机器学习入门的经典案例,但对于初学者来说,从理论推导到框架实战往往充满挑战。本文将带你完整走通这条学习路径:先手写感知机理解算法本质&#xf…...

【AI 智能体时代的软件工程】12 信任工程:建立 AI 时代的“三维材料清单 (BOM)”

大家好,我是Tony Bai。欢迎来到微专栏 《AI 智能体时代的软件工程》的第十二讲。在前面的课程中,我们从单体智能体的“任务简报(Mission Brief)”,一路讲到了多智能体协同的“自动化流水线”,并在上一讲为你…...

从学习到实战:用快马ai生成企业级java博客项目,打通知识应用最后一公里

今天想和大家分享一个特别实用的Java学习实战经验——如何用InsCode(快马)平台快速搭建一个企业级Java博客系统。这个项目完美覆盖了Java学习路线中的核心知识点,从基础框架到生产级功能一应俱全,特别适合想要通过实战巩固技能的朋友。 项目整体设计思路…...

5个高效步骤掌握MOOTDX数据接口:构建专业金融分析系统指南

5个高效步骤掌握MOOTDX数据接口:构建专业金融分析系统指南 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx MOOTDX作为一款专为Python开发者设计的通达信数据接口封装库,通过…...

CHORD-X与Matlab仿真联动:战术场景生成与效果评估

CHORD-X与Matlab仿真联动:战术场景生成与效果评估 最近在做一个挺有意思的项目,需要验证一个智能感知系统在复杂动态场景下的表现。这个系统叫CHORD-X,它专门处理视频流,能识别和追踪画面里的多个目标。但问题来了,我…...

TurboDiffusion应用案例:让静态照片变动态视频的魔法

TurboDiffusion应用案例:让静态照片变动态视频的魔法 1. 从静态到动态的视觉革命 想象一下,你手机相册里那些珍贵的照片突然"活"了过来——海浪开始翻涌,树叶随风摇曳,人物的微笑变得更加生动。这就是TurboDiffusion带…...

实测Guohua Diffusion国风生成效果:荷塘锦鲤、竹林薄雾,画面太美了

实测Guohua Diffusion国风生成效果:荷塘锦鲤、竹林薄雾,画面太美了 1. 国风绘画工具初体验 当我第一次打开Guohua Diffusion时,就被它简洁的界面设计所吸引。整个工具没有任何冗余参数,只有几个核心选项:画幅选择、提…...

一文读懂能源效率优化AI智能体提升能源使用效率,AI应用架构师知识盛宴

一文读懂能源效率优化AI智能体:架构师的技术拆解与实战指南 一、引言:从“能源浪费”到“AI救赎”的必然选择 1. 钩子:一个触目惊心的数字 你知道吗?全球工业领域约有30%的能源消耗是“无意义的浪费”——锅炉燃烧不充分导致的排烟…...

AI智能体开发全解析:从需求到部署,打造下一代智能应用!

AI智能体(AI Agent)的开发流程已从传统的软件开发生命周期(SDLC)演进为智能体开发生命周期(ADLC, Agentic Development Lifecycle)。其核心逻辑不再是编写确定的逻辑代码,而是构建具备感知、规划…...

COMSOL:模拟多尺度扩散模型下的流体运动与浆液扩散

COMSOL COMSOL模拟不同扩散模型下煤粒吸附/解吸扩 散 comsol仿真模拟电双层纳米电极,扩散双电层耦 合了Nernst-Planck方程和泊松方程。 comsol二 氧化碳混相驱替,多孔介质驱替,油气,扩散, 考虑浓度变化,速度…...

AI金融分析与智能交易系统:TradingAgents-CN全攻略

AI金融分析与智能交易系统:TradingAgents-CN全攻略 【免费下载链接】TradingAgents-CN 基于多智能体LLM的中文金融交易框架 - TradingAgents中文增强版 项目地址: https://gitcode.com/GitHub_Trending/tr/TradingAgents-CN 在数字化投资时代,如何…...

告别样本不平衡噩梦:Focal Loss 让你的模型学会“划重点”

我说的不是 Python 那个 HTTPX 客户端,而是 ProjectDiscovery 出的 httpx。官方对它的定义很直接: 一个高性能、面向多探针的 HTTP 工具包支持高并发下对 URL、主机、CIDR 等 目标做 HTTP 层探测,并尽量保证结果稳定性。 它本质上不是漏洞扫描…...

通达信数据获取革新:用MOOTDX构建极简股票分析系统全攻略

通达信数据获取革新:用MOOTDX构建极简股票分析系统全攻略 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 在量化投资与金融数据分析领域,开发者常面临数据获取的三重困境&a…...

tinyECC:Arduino嵌入式平台的轻量级ECC密码库

1. tinyECC 库概述:面向 Arduino 微控制器的轻量级椭圆曲线密码学实现tinyECC 是一个专为资源受限的 Arduino 微控制器平台设计的嵌入式椭圆曲线密码学(Elliptic Curve Cryptography, ECC)库。其核心目标是在仅有几 KB RAM 和数十 KB Flash 的…...

Stable Yogi 模型 Java 开发实战:SpringBoot 微服务集成指南

Stable Yogi 模型 Java 开发实战:SpringBoot 微服务集成指南 最近在做一个智能客服项目,后端用的是 SpringBoot 微服务架构,需要集成一个图像理解模型来处理用户上传的截图。选型的时候,Stable Yogi 模型进入了我们的视野。它不仅…...

吃透Linux/C++系统编程:文件与I/O操作从入门到避坑

合集 - LLM应用实战(17) 1. LLM应用实战:当KBQA集成LLM(二) 2024-04-25 2. LLM应用实战:当KBQA集成LLM 2024-04-11 3. LLM实战:LLM微调加速神器-Unsloth LLama3 2024-05-14 4. LLM实战:LLM微调加速神器-Unsloth Qwen1.5 2024-05…...

农业图像标注效率暴跌63%?这5个Auto-Labeling技巧已获农业农村部AI应用白皮书推荐

第一章:农业图像标注效率暴跌的根源与Auto-Labeling破局逻辑农业图像标注正面临严峻效率瓶颈:单张田间作物病害图平均需人工耗时4.7分钟完成细粒度标注(含病斑轮廓、类别、严重等级三重标签),而标注错误率高达18.3%——…...

量子力学的抽象地位与c语言等价

多种量子/粒子的各种表象,就像 cpu 的微架构指令集,量子力学的状态矢量表示和密度矩阵表示就像c语言。 中间从状态矢量到具体粒子的具体表象的转换,就像是一个编译器的工作。量子力学表象与编译器架构的深刻类比这个类比非常精妙且深刻&#…...

3分钟让静态图像“活“起来:AI肖像动画技术全解析

3分钟让静态图像"活"起来:AI肖像动画技术全解析 【免费下载链接】LivePortrait Bring portraits to life! 项目地址: https://gitcode.com/GitHub_Trending/li/LivePortrait 静态图像如何突破二维平面的限制,展现动态生命力&#xff1f…...