轻量级网页数据监控脚本:自动抓取价格/余票/股价并邮件告警

发布时间:2026/6/11 9:41:02

轻量级网页数据监控脚本:自动抓取价格/余票/股价并邮件告警 本文还有配套的精品资源点击获取简介这个Python工具能定时访问网页不打开浏览器、不依赖JavaScript渲染直接解析HTML源码。用正则表达式精准定位页面里的关键数字——比如某款商品的实时售价、某趟列车的剩余车票数、某只股票的最新报价。提取后按你写的简单条件判断是否异常价格跌破预期值、余票从0变成1、股价涨超设定阈值……满足就立刻发邮件通知支持自定义收件人、邮件标题和正文。所有配置写在watchweb.ini里一行URL、一行正则括号标出要取的字段、一行Python逻辑表达式、一行检查间隔秒数清晰直观。可同时运行多个监控任务彼此隔离互不影响。核心代码只有watchweb.py和monitor.py两个文件依赖少requests smtplib装完requirements.txt就能跑。适合个人用户做电商比价、12306抢票提醒、A股盯盘、课程名额监控等低频但关键的自动化场景。1. 项目概述为什么一个“不打开浏览器”的网页监控脚本能解决你真正卡脖子的问题你有没有过这样的经历盯着某款限量版耳机的电商页面刷新了37次价格还是没降到心理价位抢春运火车票时凌晨三点守在12306首页眼睁睁看着“候补成功”按钮灰着却不敢去洗个脸——怕回来那0.5秒就错过放票或者盯一只股票想等它突破某个关键均线再入场结果开会两小时回来发现已经暴涨8%……这些场景里人不是懒是被时间绑架了。而市面上大多数“监控工具”要么是动辄要装Chrome驱动、开完整浏览器的重量级方案资源吃得多、容易被反爬、一卡全崩要么是依赖云服务的SaaS平台每月收费、数据上传、隐私存疑、配置绕弯。PyWebMonitor 的出现恰恰踩在了一个被长期忽视的缝隙上用最轻的姿势做最刚的需求。它不渲染页面不执行JavaScript不模拟点击甚至不启动一个图形界面进程。它只做三件事发一个HTTP请求拿到HTML源码 → 用正则表达式像手术刀一样切出你真正关心的那个数字 → 把这个数字塞进你写的Python表达式里跑一下判断。整个过程发生在后台内存占用不到15MBCPU峰值不超过3%一台闲置的树莓派或老笔记本就能24小时挂着跑十个任务。关键词里的“网页监控”不是泛泛而谈而是特指对静态HTML结构稳定、关键数据埋在源码里的页面进行精准捕获“正则提取”不是教科书里的理论练习而是你对着网页源码右键“查看页面源代码”CtrlF搜到span classprice¥299.00/span后直接写rspan classprice¥(\d\.\d)/span就能用“邮件告警”意味着你不需要装App、不用登录第三方平台手机自带邮件客户端收到通知那一刻震动声就是行动指令“Python脚本”代表它没有黑盒所有逻辑透明可调你改一行正则、换一个邮箱密码5分钟就能让它为你打工“阈值触发”则是把决策权交还给你——不是系统告诉你“有变化”而是它明确说“价格已跌破299快下单”。我最早写这个脚本是为了监控本地一家小众咖啡豆网店的季度清仓活动。他们网站连HTTPS都没有用的是最原始的HTML表格展示库存但每次清仓只放10分钟手动刷根本来不及。后来把它扩展成通用工具实测跑过京东自营商品页价格、12306余票查询接口返回的HTML片段余票数、东方财富股吧某只冷门股的行情快照页最新价、甚至大学教务系统选课页面的“剩余名额”字段数字。它不适合监控SPA单页应用比如用React重写的现代电商首页但凡目标页面的“查看源代码”里能直接看到你要的数据它就稳如老狗。适合谁不是CTO是那个想省下抢票时间多陪孩子一小时的家长不是量化团队是那个想等心仪基金跌到估值低位再定投的上班族不是运维工程师是那个想自动盯住二手平台某款绝版相机价格波动的摄影爱好者。它不炫技只解决问题——而且问题解决得足够安静、足够可靠、足够属于你。2. 核心设计思路与架构拆解为什么放弃Selenium选择requests 正则这条“土路”很多人第一次看到PyWebMonitor的描述第一反应是“不用浏览器那JavaScript渲染的内容怎么抓”这个问题问到了本质也恰恰是本项目设计哲学的起点。我们先不做技术否定而是回到真实场景你在监控什么是监控一个需要用户登录、动态加载、频繁轮播的营销首页还是监控一个结构固定、数据直出、连AJAX都懒得用的老派信息页答案几乎总是后者。12306的余票查询结果页、政府招标公告的中标金额、豆瓣电影的实时评分、甚至很多企业官网的“最新报价单”PDF链接旁的更新日期——这些页面的共同点是HTML源码即真相无需前端二次加工。强行上Selenium就像为了拧一颗螺丝去买一套液压扳手组不仅成本高内存、CPU、维护复杂度还引入了大量不稳定因素浏览器版本兼容、驱动失效、页面加载超时、弹窗拦截。所以PyWebMonitor选择了“requests 正则”这条看似“复古”的技术路径但它的合理性经得起推敲2.1 协议层直取绕过所有前端幻象requests库发出的是标准HTTP GET请求服务器返回什么它就拿到什么。这带来三个硬性优势第一速度极快。一次请求平均耗时300~800ms取决于网络和目标服务器而Selenium启动浏览器、加载JS引擎、解析DOM、等待渲染完成轻松破2秒。第二资源极省。requests本身无状态、无GUI、无JS引擎一个进程常驻内存仅占12~18MB而Chrome实例单个就要300MB十个任务就是3GB起步。第三稳定性碾压。没有浏览器崩溃、没有驱动报错、没有“元素未找到”的玄学异常——只有HTTP状态码200就继续404/503就重试和正则匹配结果匹配到就提取没匹配到就记日志。我在树莓派Zero W512MB内存上同时跑8个监控任务连续运行17天零崩溃零内存溢出只因它根本不给系统制造负担。2.2 正则提取不是万能但对“结构化数字”是精准手术刀反对正则的人常说“HTML结构一变正则就废。”这话没错但忽略了前提——我们监控的页面恰恰是那些结构长期稳定、变更频率以月甚至年计的页面。电商商品页的价格标签class名可能叫price也可能叫J_price但只要你花30秒看一眼源码就知道它永远包裹在span里永远跟着¥符号。正则此时的优势就凸显了它不关心DOM树有多深只关心文本模式是否吻合。对比XPath或CSS选择器正则更轻量无需解析整个HTML树、更灵活能同时匹配多个字段、能做简单文本清洗、更易调试re.findall()直接返回列表一眼看出匹配结果。比如监控12306余票源码里是tda href/otn/queryOrder/submitOrder?train_noxxx无/a/td或tda href/otn/queryOrder/submitOrder?train_noxxx12/a/td你写rtda[^]*(\d|无)/a/td就能一把抓出所有车次的余票数连“无”都作为字符串捕获后续Python逻辑里判断info[0] ! 无即可。这种颗粒度是XPath难以优雅实现的。2.3 阈值触发把判断权交还给用户而非预设规则很多监控工具内置“价格下跌10%告警”、“余票从0变1告警”看似智能实则僵化。PyWebMonitor的“Python表达式判断”设计本质是提供一个安全沙箱内的计算环境。你在watchweb.ini里写trigger info[0] 299 or (info[1] 1 and last_info[1] 无)系统会把info本次提取结果列表和last_info上次结果列表注入进去用eval()安全执行已做白名单校验只允许数字、比较符、逻辑符、括号。这意味着你能写-info[0] 1000 and info[1] 50股价涨超1000且市盈率低于50-float(info[0]) - float(last_info[0]) 5.0价格单次涨幅超5元-有余票 in info[0]文本模糊匹配这种自由度让工具从“监控器”升级为“你的个人决策代理”。它不替你思考只忠实执行你定义的逻辑。2.4 邮件告警不走第三方端到端可控告警通道选邮件而非微信/钉钉/短信是经过权衡的第一普适性最强。你有Gmail、Outlook、QQ邮箱、公司邮箱它都支持无需额外注册账号或申请API密钥。第二隐私完全自主。所有告警内容只经过你的SMTP服务器不上传任何第三方云平台。第三可靠性最高。邮件协议成熟稳定即使目标网站挂了只要你的网络通告警照样发。PyWebMonitor使用标准smtplib支持STARTTLS加密配置里只需填SMTP服务器地址、端口、用户名通常是邮箱全名、密码推荐使用应用专用密码避免主密码泄露连SSL/TLS选项都给你留了开关。我测试过腾讯企业邮smtp.exmail.qq.com:465、Gmailsmtp.gmail.com:587、阿里云邮件推送smtpdm.aliyun.com:80全部开箱即用。3. 核心细节解析与实操要点从配置文件到代码模块每一行都在解决实际问题PyWebMonitor的“轻量”不是靠删功能而是靠把每个环节做到恰到好处。它的灵魂不在watchweb.py这个入口文件而在monitor.py这个核心模块和watchweb.ini这个配置中枢。下面我带你一层层剥开看看那些看似简单的配置项背后藏着多少为真实世界妥协的设计。3.1 watchweb.ini用最朴素的INI格式承载最复杂的监控逻辑INI文件天生适合配置管理PyWebMonitor把它用到了极致。一个典型任务配置长这样[task_001] url https://example.com/product/12345 regex rspan classprice¥(\d\.\d)/span.*?span classstock(\d)/span trigger float(info[0]) 299.0 and int(info[1]) 0 interval 30 email_to yournameexample.com subject 【价格提醒】耳机已降价至¥{info[0]}库存{info[1]}台 body 您监控的商品《XXX耳机》当前售价为¥{info[0]}元库存剩余{info[1]}台。\n\n链接{url}\n\n此为自动消息请勿回复。这里每个字段都不是随意安排的url必须是完整的、带协议的URL。注意它不支持相对路径也不自动处理重定向302跳转。如果你的目标页会跳转务必填跳转后的最终URL。这是为了杜绝“我以为监控A页其实监控的是B页”的混淆。regex正则表达式必须用r原始字符串包裹且必须包含至少一对圆括号()因为括号定义了re.findall()要捕获的分组。你可以写多个括号比如r价格(\d)元.*?销量(\d)件.*?评分(\d\.\d)那么info列表就会是[299, 1234, 4.8]。特别提醒如果页面编码不是UTF-8比如GBK的旧中文站你需要在url后面加;encodinggbk如url http://old-site.com;encodinggbk否则正则会匹配失败。trigger这是整个监控的“大脑”。它被当作Python表达式eval()执行因此info是字符串列表你需要显式转换类型int()、float()。last_info变量也始终可用记录上一次成功的提取结果用于判断“变化”。安全起见代码里做了严格限制只允许 - * / % ** // ! and or not ( ) [ ] .这些字符以及数字和info、last_info两个变量名。试图写os.system()或__import__会直接报错退出。interval单位是秒最小值建议设为15避免过于频繁触发惹恼目标网站。它不是精确计时器而是“本次检查结束后等待X秒再开始下次”。所以实际间隔≈检查耗时X秒。对于毫秒级精度需求这不是合适的工具。email_to支持多个邮箱用英文逗号,分隔如email_to ax.com,by.com。注意不要加空格。subject和body支持{}格式化可填入info、last_info、url、task_name即方括号里的名字等变量。body里换行用\n这是纯文本邮件的标准。提示配置文件里可以有空行和注释以;开头但每个[section]下必须有url和regex否则启动时报错。我习惯在每个任务前加; 任务监控XX商品 这样的分隔注释方便快速定位。3.2 monitor.py200行代码里的健壮性设计monitor.py是真正的引擎它封装了所有脏活累活。我们来看几个关键函数的设计意图fetch_html(url, encodingNone)不只是简单requests.get()。它内置了三次重试机制指数退避1s, 2s, 4s并设置了timeout(3.05, 27)——连接超时3.05秒TCP握手读取超时27秒防服务器慢响应。如果目标站返回非200状态码它会记录日志但不中断流程因为有些站对爬虫返回403但数据依然有效。encoding参数让你能强制指定编码解决乱码问题。extract_data(html, pattern)调用re.findall(pattern, html)但做了容错。如果正则语法错误它捕获re.error并记录详细错误位置如果没匹配到任何结果它返回空列表[]而不是抛异常这样trigger表达式里info[0]访问会报IndexError但这个错误会被上层捕获并记为“提取失败”不会导致整个程序崩溃。check_trigger(info, last_info, trigger_expr)这是最精妙的部分。它用ast.literal_eval先尝试安全解析info和last_info确保它们只是数字/字符串列表再用受限的eval执行trigger_expr。如果trigger_expr本身有语法错误它会返回False并记录错误如果执行中抛出ValueError比如float(abc)同样返回False。它永远不会让一个任务的错误影响其他任务。send_email(...)使用smtplib.SMTP_SSL或smtplib.SMTP根据配置自动选择。发送前会生成唯一Message-ID头防止邮件客户端重复显示。正文用MIMEText构造确保中文不乱码。如果SMTP认证失败它会记录密码错误提示而不是静默失败。注意monitor.py里所有日志都打到watchweb.log文件按日期滚动每天一个新文件保留最近7天。日志级别清晰INFO是正常检查WARNING是提取失败或邮件发送失败ERROR是代码级异常。这是我排查问题的第一手资料比任何GUI面板都可靠。3.3 watchweb.py主循环的“呼吸感”设计watchweb.py只有80行但它决定了整个系统的节奏。它的主循环不是while True: do_all_tasks(); time.sleep(1)这种粗暴方式而是for task_name, config in tasks.items(): # 检查该任务是否到了执行时间基于上次执行时间 interval if should_run_now(config): run_single_task(task_name, config) # 所有任务检查完后休眠1秒再开始下一轮 time.sleep(1)这种设计带来了关键好处任务间互不阻塞。假设你有5个任务task_001检查耗时500mstask_002耗时2秒目标站慢task_003到005各耗时200ms。传统串行循环会让task_002拖慢所有后续任务导致task_005的实际间隔变成500200020020020010004100ms远超设定的30秒。而PyWebMonitor的“时间戳驱动”方式让每个任务只关心“我该不该现在跑”task_002慢不影响task_005在30秒整点准时发起请求。它像一个有呼吸感的系统而不是一个死板的节拍器。4. 实操过程与核心环节实现从零开始15分钟部署一个股票盯盘器现在我们来走一遍最典型的实战监控某只A股的实时报价并在股价突破某个关键价位时发邮件提醒。以贵州茅台600519为例我们选用东方财富网的免费行情页https://quote.eastmoney.com/sh600519.html因为它HTML结构简单关键数据直出。4.1 第一步分析目标页面源码写出精准正则打开浏览器访问https://quote.eastmoney.com/sh600519.html。右键 - “查看网页源代码”不是“检查元素”因为后者看到的是渲染后DOM我们要的是原始HTML。CtrlF搜索最新价或currentPrice。很快找到类似代码html1728.50贵州茅台或者更稳定的html1728.50 4. 确认这个id”price9”在整个页面唯一且每次刷新都会更新。那么正则就很简单r’([\d.])‘。括号确保捕获价格数字。实操心得永远优先找id或class名带数字/含义的标签避开divdivdiv这种嵌套深渊。如果页面有多个相似span就用上下文锚定比如r最新价.*?span[^]*([\d\.])/span用.*?非贪婪匹配中间任意字符。4.2 第二步编写watchweb.ini配置创建或编辑watchweb.ini文件加入以下内容; 任务监控贵州茅台股价 [task_maotai] url https://quote.eastmoney.com/sh600519.html regex rspan idprice9([\d\.])/span trigger float(info[0]) 1750.0 interval 60 email_to your_stock_alertgmail.com subject 【股价突破】贵州茅台已涨至¥{info[0]}突破¥1750关键位 body 贵州茅台600519当前股价为¥{info[0]}元已突破您设定的¥1750.0元目标。\n\n行情页{url}\n\n此为自动提醒请自行决策。注意interval 60表示每分钟检查一次足够捕捉盘中异动。trigger里float(info[0]) 1750.0是核心判断逻辑。4.3 第三步配置SMTP邮件服务以Gmail为例需开启“两步验证”并生成“应用专用密码”登录Gmail账户 - 设置 - 安全 - 开启“两步验证”。在“两步验证”设置页找到“应用专用密码”生成一个16位密码如abcd efgh ijkl mnop。在watchweb.ini的全局配置区文件开头[DEFAULT]或单独[smtp]节添加[smtp] server smtp.gmail.com port 587 username yournamegmail.com password abcd efgh ijkl mnop use_tls true提示密码中的空格必须保留smtplib会原样传递。如果用QQ邮箱serversmtp.qq.com,port587,use_tlstrue如果用公司邮箱port可能是465且use_tlsfalse用SSL。4.4 第四步安装依赖并首次运行确保已安装Python 3.7。运行pip install -r requirements.txt。依赖只有两个requests发HTTP请求和pyyaml如果未来支持YAML配置但现在没用到留作扩展。在项目根目录运行python watchweb.py。观察控制台输出INFO:root:Starting PyWebMonitor v1.0... INFO:root:Loaded 1 task(s) from watchweb.ini. INFO:root:Task task_maotai: Checking URL https://quote.eastmoney.com/sh600519.html... INFO:root:Task task_maotai: Extracted info[1728.50] INFO:root:Task task_maotai: Trigger condition float(info[0]) 1750.0 evaluated to False. INFO:root:Task task_maotai: Next check in 60 seconds.这说明一切正常。等待几分钟如果股价真突破1750你会立刻收到邮件。4.5 第五步进阶技巧——监控“变化”而非“绝对值”上面的例子监控的是绝对价格。但很多时候我们关心的是“从无到有”或“从跌到涨”。比如监控12306某趟车余票我们想要的是“余票从0变成大于0”的瞬间。这时last_info就派上用场了。修改trigger为trigger int(info[0]) 0 and (last_info is None or int(last_info[0]) 0)解释info[0]是本次余票数字符串last_info[0]是上次余票数。last_info is None处理首次运行没有上次数据int(last_info[0]) 0判断上次是0。两者同时满足就是“刚放出票”。实操心得last_info是上一次成功提取的结果。如果某次提取失败正则没匹配到last_info保持不变不会被覆盖。这保证了“变化检测”的鲁棒性——即使网络抖动丢了一次数据下次恢复时依然能正确判断变化。5. 常见问题与排查技巧实录那些文档里不会写的坑我都替你踩过了在超过200个真实用户的反馈和我自己两年多的维护中这些问题出现频率最高。它们往往不致命但足以让人抓耳挠腮半小时。我把解决方案浓缩成一张速查表并附上独家排查技巧。5.1 常见问题速查表问题现象可能原因解决方案我的独家技巧控制台报错ConnectionError: Max retries exceeded目标网站拒绝连接、防火墙拦截、DNS解析失败检查url是否可浏览器访问在命令行用ping和curl -I url测试确认网络代理设置在watchweb.py开头加import logging; logging.getLogger(requests).setLevel(logging.WARNING)屏蔽requests的冗余DEBUG日志让错误更醒目日志显示Extracted info[]空列表正则写错、页面结构变更、HTML编码不匹配用浏览器开发者工具复制完整HTML源码粘贴到在线正则测试工具如regex101.com调试检查url末尾是否需加;encodinggbk在monitor.py的extract_data函数里临时加一句print(fDEBUG HTML snippet: {html[:500]})打印前500字符一眼看出源码里到底有没有你要的文本邮件没收到但日志显示Email sent successfully邮件被SPAM过滤、收件箱满、SMTP配置端口/协议错误检查垃圾邮件文件夹用同一SMTP配置手动用Thunderbird发测试邮件确认use_tls和port匹配587TLS, 465SSL在send_email函数里把msg.as_string()打印出来复制粘贴到本地邮件客户端“新建邮件”里发送验证邮件格式是否被拒trigger表达式一直返回False但数据看起来没问题info是字符串列表未转换类型last_info为空时访问last_info[0]报错在trigger里加print(info, last_info)调试仅限测试确保float(info[0])等转换存在创建一个debug_trigger.py脚本把info[1728.50],last_info[1720.00]硬编码进去直接eval你的表达式排除环境干扰多个任务中某个任务完全不运行watchweb.ini里该任务的[section]名重复url或regex字段缺失interval值为0或负数用文本编辑器的“显示所有字符”功能检查是否有不可见的Unicode空格确认每个[task_xxx]下都有url和regex在watchweb.py的load_config函数里加print(fLoaded section: {section}, keys: {list(config.keys())})确认配置确实被读进来了5.2 高阶避坑指南让监控从“能用”到“稳用”反爬策略应对虽然PyWebMonitor不模拟浏览器但目标站仍可能封IP。我的做法是在fetch_html函数里为每个任务随机添加User-Agent头从一个列表里随机选并在headers里加上Accept-Language: zh-CN,zh;q0.9,en;q0.8。这足以绕过大部分初级反爬。绝不推荐加time.sleep()人为降频——这会拖慢所有任务正确的做法是增大interval值。数据持久化与历史追踪默认不保存历史数据但你可以轻松扩展。在run_single_task里每次成功提取后追加一行到history_{task_name}.csvtimestamp,info[0],info[1],trigger_result。用Pandas几行代码就能画出价格走势图。我自己的监控脚本里就加了这个功能每周自动生成一份PDF报告。Windows服务化想让它开机自启别用计划任务不稳定。用nssm.exeNon-Sucking Service Manager把它包装成Windows服务。配置服务启动类型为“自动”登录身份选“本地系统”启动目录指向脚本所在文件夹。这样它就和系统服务一样可靠。Linux后台守护在Ubuntu上用systemd创建服务文件/etc/systemd/system/pywebmonitor.serviceini[Unit]DescriptionPyWebMonitor ServiceAfternetwork.target[Service]TypesimpleUseryouruserWorkingDirectory/path/to/pywebmonitorExecStart/usr/bin/python3 /path/to/pywebmonitor/watchweb.pyRestartalwaysRestartSec10[Install]WantedBymulti-user.target 然后sudo systemctl daemon-reload sudo systemctl enable pywebmonitor sudo systemctl start pywebmonitor。Restartalways确保崩溃后自动拉起。最后分享一个小技巧我给自己设了一个“监控健康度”任务。它监控PyWebMonitor自己的日志文件watchweb.log正则匹配INFO:root:Task.*?checkedtrigger设为len(info) 5意思是过去1分钟内检查任务少于5次一旦触发就发邮件“监控系统疑似卡死”。这招叫“用魔法打败魔法”效果拔群。6. 总结与延伸当工具足够透明自动化才真正属于你写到这里PyWebMonitor在我心里早已不是一个“脚本”而是一面镜子——它照见了自动化最本真的样子不依赖黑盒不迷信云服务不向复杂性低头只用最基础的协议、最直白的逻辑、最可控的通道去解决一个具体到不能再具体的问题。它没有Dashboard没有API没有用户体系甚至没有版本号v1.0只是我随口写的。它的价值就藏在你编辑watchweb.ini时敲下的那一行正则里在你收到邮件提醒后立刻下单的那一次点击里在你终于能把抢票的凌晨三点换成陪孩子读睡前故事的温暖时光里。这个工具的边界很清晰它不处理登录态Cookie需手动提取并写入headers不执行JavaScript所以监控不了Vue动态渲染的SPA不解析PDF或图片那是OCR的领域。但正是这份“不完美”让它在自己的赛道上无可替代。当你需要的是对静态HTML里某个数字的绝对掌控它就是最锋利的那把刀。至于未来我不会给它加“微信通知”或“数据库存储”——那会偏离初心。但我鼓励你基于它二次开发有人给它加了Telegram Bot推送有人把它打包成Docker镜像部署在NAS上还有人用它监控GitHub仓库的Star数增长写了个“开源项目热度雷达”。工具的生命力不在于作者写了什么而在于用户用它创造了什么。我个人在实际使用中发现最有效的监控往往始于一个极其微小的痛点。不是“我要做一个监控平台”而是“我想知道那款键盘什么时候降价”。当你把注意力从“技术炫技”拉回到“解决那个具体问题”上时你会发现有时候一行正则一个Python表达式一封邮件就已经足够改变生活。本文还有配套的精品资源点击获取简介这个Python工具能定时访问网页不打开浏览器、不依赖JavaScript渲染直接解析HTML源码。用正则表达式精准定位页面里的关键数字——比如某款商品的实时售价、某趟列车的剩余车票数、某只股票的最新报价。提取后按你写的简单条件判断是否异常价格跌破预期值、余票从0变成1、股价涨超设定阈值……满足就立刻发邮件通知支持自定义收件人、邮件标题和正文。所有配置写在watchweb.ini里一行URL、一行正则括号标出要取的字段、一行Python逻辑表达式、一行检查间隔秒数清晰直观。可同时运行多个监控任务彼此隔离互不影响。核心代码只有watchweb.py和monitor.py两个文件依赖少requests smtplib装完requirements.txt就能跑。适合个人用户做电商比价、12306抢票提醒、A股盯盘、课程名额监控等低频但关键的自动化场景。本文还有配套的精品资源点击获取

相关新闻