用Python写网页监控脚本,自动盯住COMING SOON页面变化

用Python写网页监控脚本,自动盯住COMING SOON页面变化 看到 FansToys FT-63 TURBO COMING SOON! 这个标题我的第一反应不是这个新品值不值得买而是一个很适合写代码解决的场景页面只停留在预告状态之后什么时候放出参数、什么时候开放下单官方不会主动通知你。与其每天手动刷新不如写一个 Python 页面监控脚本让它在后台盯着这个“即将到来”的页面发生变化时通过 Webhook 推送一条提醒。这篇就来拆解这个方案并给出一套可以直接改 URL 就复用的监控脚本。这个方案并不依赖具体项目本身但用 FansToys FT-63 TURBO 作为演示对象很合适。标题里明确写着 COMING SOON意味着这个页面大概率还会被更新。脚本要做的事情很简单周期抓取目标页面响应计算一个页面指纹与上一次记录对比指纹变了说明页面内容发生变化然后再检查页面里是否出现预设关键词比如 FT-63、TURBO、预订、价格两条规则命中任意一条就通知。本文会用一套完整的本地项目流程来讲环境准备、脚本设计、批量配置、通知接入、运行验证、问题排查。这个监控脚本不需要 GPU不需要显存普通 CPU 就能 24 小时运行。如果你想盯住官网页面放到一台低配云主机上即可如果只想在本地临时用命令行启动也够。下面直接进入部署。1. 核心能力速览能力项说明监控对象FansToys FT-63 TURBO 官方发布页URL 需要替换为实际页面当前状态COMING SOON页面内容后续可能更新运行环境Python 3.8Windows / macOS / Linux硬件要求无 GPU普通 CPU 即可内存占用很低启动方式命令行启动或用 systemd / cron / 计划任务核心功能页面变化检测、关键词命中提醒、Webhook 通知、多 URL 批量监控是否支持 API脚本以 Webhook 方式输出通知可接入钉钉、企业微信、Server酱等是否支持批量任务支持通过 JSON 配置多个 URL 与关键词适合场景新品发布监控、页面更新提醒、版本发布跟踪、文档更新检测表格里这些信息都是从标题和现有公开状态推出来的。FansToys FT-63 TURBO 的完整规格、价格、发售时间官方没有在预告里放出所以这篇不会去编参数。我们要做的事情是监控页面而不是评测产品本身。后面所有测试都围绕“页面变化检测”这个技术目标展开。整个脚本不涉及显存不涉及 GPU也不涉及复杂的模型依赖。你只需要保证网络能访问目标页面并且运行环境能安装 Python 第三方包。这样一来它比很多 AI 本地部署项目更轻量适合作为新手第一个自动化监控项目来练手。2. 适用场景与使用边界这个监控脚本适合四类场景。第一类是新品发布跟踪。以 FansToys FT-63 TURBO 为例新品在正式发售前通常会有多个更新阶段先是 COMING SOON接着放开箱图、公布参数、给出价格、开启预订。每个阶段都可能触发页面变化脚本能第一时间提醒你去看变化后的内容。第二类是限量和库存监控比如某些商品突然补货、重新上架这类信息往往只存在很短时间。第三类是文档和软件版本监控比如一篇技术文档从 draft 变成 release或者下载页面出现新的版本号。第四类是活动页监控比如报名入口从“关闭”变成“开放”票务状态从“无票”变成“可选”。不适用场景也要说清楚。需要登录后才能访问的会员专属页面脚本直接抓取会失败需要额外处理 cookie 和登录态。纯 JavaScript 渲染的单页应用requests 拿到的 HTML 可能只是一个空壳页面正文由 JS 动态生成这种情况下需要用 Playwright 或直接抓取页面背后的 JSON API。还有明确禁止自动化访问、反爬严格、存在法律风险的站点不建议用这类脚本去硬碰即使只是很低频的请求也要先看 robots.txt 和服务条款。使用边界上还有一层要注意的是消息准确度。FansToys FT-63 TURBO 这个标题目前只能说明“即将到来”并不代表官方已经确认了任何规格细节。作为个人提醒工具重点是帮你及时注意到官方更新不要把页面里出现的第三方评论或营销文案当成官方消息。我们只把脚本用于个人提醒不承诺自动下单不绕过任何风控不批量爬取敏感数据也不把抓取结果用于商业转载。另外关于第三方品牌和版权边界需要特别提醒FansToys 属于第三方产品品牌你在监控其页面时建议只关注官方发布渠道。不要在未经授权的情况下复制、分发官方图片和文案。无论产品本身是否涉及版权争议这次要解决的始终是技术监控问题而不是内容搬运问题。3. 环境准备与前置条件运行这个监控脚本不需要很复杂的依赖一个 Python 3.8 环境就足够。推荐在虚拟环境里安装避免污染系统 Python。下面以 Ubuntu / macOS 为例Windows 用户可以换成py -3命令路径和激活方式稍作调整即可。mkdir -p ft63-monitor cd ft63-monitor python3 -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install requests安装完成后检查 requests 是否可用python -c import requests; print(requests.__version__)如果出现ModuleNotFoundError说明虚拟环境没有启用或者 pip 安装到了另一个 Python 环境。这种情况在初学者中最常见它导致的故障和项目本身无关但会影响后续所有步骤。之后确认网络能访问目标页面先用浏览器手动打开一次确认页面可以正常渲染再写脚本。如果你的运行环境无法访问目标站点需要先解决网络连通性问题否则脚本会一直请求超时。磁盘空间方面代码文件加虚拟环境通常占用几十 MB 到一两百 MB可以忽略不计。运行期间会写一个小的状态文件state.json用来保存每个监控页面当前指纹这个文件会随着监控 URL 数量增加而增大但通常也就是几十行 JSON不会成为性能瓶颈。4. 安装部署与启动方式把核心脚本命名为monitor.py第一次运行它会请求目标页面记录当前指纹然后进入循环。脚本核心逻辑可以拆成三块抓取页面、计算指纹、发送通知。为兼容更多页面这里不解析 DOM而是用整页文本做 SHA256 哈希逻辑简单且通用。如果你觉得全页指纹误报率高可以后续改成只对标题或某个 DOM 节点取哈希。import requests import hashlib import time import os import json import logging logging.basicConfig(levellogging.INFO, format%(asctime)s [%(levelname)s] %(message)s) DEFAULT_CONFIG { urls: [ { name: FansToys FT-63 TURBO official page, url: https://example.com/fanstoystoys/ft63-turbo, keywords: [FT-63, TURBO, COMING SOON] } ], interval: 300, webhook: } def load_config(): if os.path.exists(config.json): with open(config.json, r, encodingutf-8) as f: return json.load(f) return DEFAULT_CONFIG def fetch_text(url): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36, Accept-Language: zh-CN,zh;q0.9 } resp requests.get(url, headersheaders, timeout15) resp.raise_for_status() return resp.text def fingerprint(html): return hashlib.sha256(html.encode(utf-8, errorsignore)).hexdigest() def has_keyword(html, keywords): lower_html html.lower() return [kw for kw in keywords if kw.lower() in lower_html] def send_notification(webhook_url, text): if not webhook_url: logging.info(未配置 webhook将通知打印到日志%s, text) return try: requests.post(webhook_url, json{text: text}, timeout10) except Exception as e: logging.error(发送通知失败: %s, e) def check_urls(cfg): state {} if os.path.exists(state.json): with open(state.json, r, encodingutf-8) as f: state json.load(f) for item in cfg[urls]: name item[name] url item[url] keywords item.get(keywords, []) logging.info(检查: %s, name) try: html fetch_text(url) current_fp fingerprint(html) previous_fp state.get(name) if previous_fp is None: logging.info(首次检查 %s记录当前指纹, name) elif previous_fp ! current_fp: logging.info(检测到 %s 页面发生变化, name) send_notification(cfg.get(webhook, ), f{name} 页面发生变化) hit has_keyword(html, keywords) if hit: send_notification( cfg.get(webhook, ), f{name} 命中关键词: {hit} ) state[name] current_fp except Exception as e: logging.error(检查 %s 失败: %s, name, e) continue with open(state.json, w, encodingutf-8) as f: json.dump(state, f, ensure_asciiFalse, indent2) def main(): cfg load_config() logging.info(启动监控共 %d 个 URL间隔 %d 秒, len(cfg[urls]), cfg[interval]) while True: check_urls(cfg) time.sleep(cfg[interval]) if __name__ __main__: main()config.json用来管理监控目标和通知地址。默认脚本会读取这份配置文件如果不存在就使用内置配置。下面是一个批量示例包含两个 URL其中第一个就是 FansToys FT-63 TURBO 页面需替换为真实 URL{ interval: 600, webhook: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?keyREPLACE_ME, urls: [ { name: FansToys FT-63 TURBO, url: https://example.com/ft63, keywords: [FT-63, TURBO] }, { name: 备用资讯页, url: https://example.com/news, keywords: [FansToys] } ] }启动方式很简单python monitor.py第一次启动后日志会显示类似下面的内容。这里最核心的是脚本会把当前页面指纹保存到state.json作为后续对比的基准2025-12-20 10:00:01 [INFO] 启动监控共 1 个 URL间隔 300 秒 2025-12-20 10:00:02 [INFO] 检查: FansToys FT-63 TURBO official page 2025-12-20 10:00:03 [INFO] 首次检查 FansToys FT-63 TURBO official page记录当前指纹如果希望脚本在断开 SSH 后继续运行可以加nohup放到后台如果希望重启后也能自动拉起建议用 systemd 或 Windows 计划任务。这里给一个简单的后台启动方式nohup python monitor.py monitor.log 21 对于 Windows 用户可以把python monitor.py添加到“任务计划程序”触发器设置成“计算机启动后”或“每天固定时间”运行。因为脚本本身是常驻循环添加计划任务时不要同时启动多个进程否则会重复抓取页面。5. 功能测试与效果验证先做基础验证确认脚本能正常获取页面并记录指纹。第一次运行后观察state.json是否生成如果生成且内部包含当前页面指纹说明抓取与状态保存正常。此时即使没有配置 Webhook也不影响基础功能。第二步做页面变化测试。手动修改state.json中对应 URL 的指纹改成任意一段乱码再运行脚本。正常情况下日志会输出“检测到页面发生变化”。这个测试的目的是验证指纹对比逻辑不依赖目标页面真实变化。第三步做关键词命中测试。把某个 URL 的关键词改成页面中一定存在的词比如COMING SOON再把另一个关键词改成不可能存在的词比如zqxjk。运行后只有命中词的日志会输出关键词提醒。这样能验证关键词过滤是否生效。第四步做 Webhook 测试。用 webhook.site 或类似在线工具生成一个临时 Webhook 地址填入config.json的webhook字段再次触发页面变化观察在线工具是否收到 POST 请求。如果收到说明通知链路可用。第五步做异常处理测试。故意把 URL 改成不可访问的域名运行脚本应该看到“检查失败”的错误日志但进程不会退出。这说明单个 URL 的故障不会影响整个监控循环。六项测试的预期结果可以汇总如下测试项操作预期结果首次启动直接运行 monitor.py生成 state.json记录页面指纹页面变化修改 state.json 中的指纹日志出现“页面发生变化”关键词命中配置存在与不存在的关键词只提醒命中关键词Webhook配置临时 Webhook 地址在线工具收到 POST 请求异常处理配置不可达 URL日志报错进程继续运行批量验证在 urls 中添加多个 URL每个 URL 独立检查并保存状态完成上述测试后脚本就可以进入正式监控状态。建议先用 10 分钟间隔跑半天观察日志和状态文件是否稳定再把间隔调整到最终值。6. 接口 API 与批量任务这个脚本本身不暴露 HTTP API但 Webhook 就是消费端接口。你可以把它接入钉钉群机器人、企业微信应用消息、Server酱只要服务商提供 POST 地址即可。以钉钉机器人为例通知格式通常是{ msgtype: text, text: { content: FansToys FT-63 TURBO 页面发生变化 } }不同服务商字段不同需要按各自文档调整。接入以后脚本检测到页面变化就能直接在群里收到提醒。对不想写邮件服务的场景这是最轻量的通知方案。批量任务方面config.json的urls数组天然支持多个页面。每次check_urls循环都会按顺序检查所有 URL每个页面独立保存指纹互不影响。如果希望提高检查速度可以用线程池并发但要控制并发数量。这里建议并发数不超过 2否则容易触发网站限流。失败重试逻辑方面当前脚本采用“跳过并等待下一轮”的策略请求异常时只记录日志不阻塞其他 URL也不会无限重试。对监控这种场景这已经足够。如果你希望脚本暴露一个简单的查询接口可以在现有项目里加一个 Flask 服务提供两个路由/health返回运行状态/check手动触发一次全量检查。这样外部监控系统可以主动探测脚本是否存活。不过考虑到config.json已经能实现批量监控直接加 Flask 服务会让项目多一个端口增加维护成本。按需扩展即可。7. 资源占用与性能观察脚本保存的是页面文本的 SHA256 指纹不是整页内容所以状态文件开销很小。运行时每个 URL 只占用一个 requests 连接等待响应期间几乎不消耗 CPU。实际观察可以用top或任务管理器正式使用前先跑 30 分钟观察内存是否稳定、CPU 是否接近 0。如果发现 CPU 持续偏高多数原因是网络超时重试或者页面体积过大导致字符串处理和哈希计算变慢。性能影响最大的参数是interval。间隔越短发现变化越快但请求频率越高。对 FansToys FT-63 TURBO 这种新品预告页面官方不太可能每分钟都更新5 到 10 分钟一次已经足够。如果到了限时抢购阶段需要更快反应可以临时把间隔调到 10 秒但不要长时间高频运行。除了间隔页面体积、关键词数量、日志输出量也会影响资源占用。几 KB 的普通页面和几 MB 的富媒体页面抓取和哈希耗时差异明显。如果计划长期运行建议把requests.get替换为requests.Session让连接复用减少 TCP 握手开销。把 Session 对象放在模块级然后在fetch_text里使用同一个 Session可以明显改善网络请求稳定性。当然对于单机监控几个页面这种优化不是必需的但对提升工程规范性有帮助。另一个容易忽略的问题是脚本残留。多次用nohup启动脚本会同时存在多个监控进程导致重复请求和重复通知。启动前先检查是否有旧进程或在脚本开头加一个 PID 文件锁避免一台机器上跑出多个实例。8. 常见问题与排查方法问题现象可能原因排查方式解决方案脚本报 SSL 证书错误本地网络代理或系统证书异常查看完整异常日志更新证书或在测试环境下关闭校验请求超时网络不通或页面响应慢用 curl 手动访问目标页面增加 timeout降低检查频率页面一直提示变化页面含动态时间戳、广告位、推荐位打印页面指纹对比变化内容只提取标题或指定 DOM 节点再计算指纹通知发送失败Webhook 地址错误或服务商限制手动 POST 测试 Webhook检查地址、字段格式、IP 白名单页面返回 403网站开启了基础反爬检查请求头是否完整补充 User-Agent、Accept 头保持低频访问关键词没触发关键词与实际页面文本不一致打印页面响应查看具体文本调整关键词或用正则匹配Python 命令找不到虚拟环境未激活检查终端提示符是否有 venv 前缀重新执行source venv/bin/activate状态文件不更新脚本权限不足或磁盘只读检查运行用户对目录的写权限修改目录权限或换个工作目录最常见的误报来源是动态页面。很多页面每次访问都会带不同的时间戳、随机 token、广告位数据导致整页指纹频繁变化。这时候不能修改页面内容而应该先打印出前后两次页面差异找到变化的区域然后只对该区域取指纹。比如用 BeautifulSoup 提取h1或classproduct-info节点再对这段文本做哈希。这样既能减少误报也能让通知更精确。另一个需要关注的是编码问题。某些页面返回 GBK 或 GB2312 编码直接使用html.encode(utf-8)可能丢弃字符导致中文内容变化检测失效。更稳妥的做法是依赖requests的resp.encoding字段或使用resp.text前先手工设置编码把页面文本规范成 UTF-8 后再计算哈希。9. 最佳实践与使用建议把监控脚本当成一个小工具来维护不要写完就丢。第一次使用先小参数测试比如把间隔设为 600 秒只监控一个 URL跑半天确认稳定后再增加 URL。每个监控任务要有一个清晰的name并且保留state.json的历史记录方便出问题时回溯。建议定期查看日志确认脚本没有因为网络异常长时间停摆。不要把脚本部署在需要频繁睡眠的电脑上低配云主机更适合。云主机的公网 IP 和稳定网络能减少很多请求超时而且不会因为合上笔记本就中断。如果监控的页面分布在不同域名可以考虑按域名拆分多个配置文件避免某个网站改版导致所有任务都失败。日志文件要按日期切割避免单个 log 文件无限膨胀。合规提醒需要放到实际操作之前不要抓取需要授权的内容不要对同一站点做高频请求不要使用本脚本绕过登录或验证码也不要把抓取结果用于商业爬虫。部署到正式环境前应该用robots.txt查看目标路径是否允许访问。对 FansToys FT-63 TURBO 这类新品页面低频率的个人提醒在合理范围内但仍要尊重网站服务条款。为了减少漏报可以同时关注官方社交账号脚本只是补充手段。不同渠道交叉验证能降低单一页面结构变化带来的风险。检测到变化后通知信息最好包含检测时间、URL、命中的关键词方便判断是否值得打开页面。当前代码里的send_notification已经能输出基础文本你可以按需求改成 Markdown 消息。如果担心页面变化检测不够精细还可以扩展版本对比功能每次变化后保存一份页面快照并写入一个history目录。后续用 diff 工具查看两个版本之间的具体差异这样即使已经过去几天也能知道官网页面上到底改了什么。10. 总结与下一步这个工程最核心的价值是把“COMING SOON”变成一个有状态、可监控、可通知的技术任务。FansToys FT-63 TURBO 最终什么时候更新不是脚本能决定的但脚本会在页面更新后第一时间提醒你。第一个要验证的功能是状态文件生成第一个容易踩的坑是动态页面产生假变化第一个要优化的方向是区域提取与稳定指纹。你还能继续扩展很多内容把state.json换成 SQLite保存每次变化的历史记录用 Flask 包一个/check接口让其他服务主动轮询接入钉钉、企业微信机器人后让提醒直接进入群聊如果目标页面是 JS 渲染用 Playwright 替代 requests。这个监控方案的边界很清晰扩展自由度很高建议收藏备用。等 FT-63 TURBO 正式公布参数时你就能第一时间拿到消息不用再反复刷新页面了。