生产环境必须用apscheduler,它支持任务持久化、失败重试和分布式部署,而schedule仅适用于本地开发;实操需用sqlalchemyjobstore持久化、显式指定asia/shanghai时区、避免lambda闭包。

用 schedule 还是 APScheduler?别选错启动方式
直接用 schedule 库写个无限循环(while True: schedule.run_pending(); time.sleep(1))在本地开发没问题,但部署到服务器后一旦进程退出就停摆,且不支持任务持久化、失败重试或分布式。生产环境必须用 APScheduler,它能对接 SQLAlchemy 存储任务状态,还能用 BackgroundScheduler 启动后不阻塞主线程。
实操建议:
- 安装:
pip install apscheduler,避免装错成已停更的apscheduler3 - 初始化时指定
jobstore,例如用 SQLite 持久化:SQLAlchemyJobStore(url='sqlite:///jobs.sqlite'),否则重启服务后定时任务全丢 - 不要在
add_job()里传带闭包的 lambda,容易捕获错误变量;封装成独立函数更可控
抓取竞品价格时怎么绕过反爬又不被封IP?
多数竞品网站用前端渲染(如 Vue/React),直接 requests.get() 拿到的是空容器或 JS 脚本,必须用无头浏览器或解析动态接口。但 Selenium 启动慢、内存高,优先查网站 Network 面板找真实数据接口(常是 /api/price 或带 skuId 的 REST URL),再模拟请求。
实操建议:
- 加
User-Agent和Referer是基础,但不够;关键要复现请求头里的X-Requested-With或加密参数(如sign、ts),用浏览器开发者工具抓包比“通用UA+随机延时”管用十倍 - 别用公共代理池——响应慢、不稳定;用公司固定出口 IP +
time.sleep(random.uniform(2, 5))控制频率更稳妥 - 对返回
403或空数据的请求,先打印response.status_code和response.text[:200],确认是反爬拦截还是接口变更
邮件提醒发不出去?重点检查 SMTP 认证和字符编码
smtplib.SMTP 报 SMTPAuthenticationError 大多不是密码错了,而是邮箱未开启 SMTP 服务,或用了登录密码而非“应用专用密码”。Gmail、Outlook 等已强制要求后者;国内企业邮箱则常需联系 IT 部门开通 SMTP 权限。
实操建议:
- 发件人地址必须和 SMTP 登录账号一致,比如用
xxx@163.com登录,就不能设From: yyy@qq.com - 中文标题和正文必须用
MIMEText(..., _charset='utf-8')显式声明,否则 Outlook 里显示乱码 - 附件(如导出的 CSV)要用
MIMEApplication包裹并设置add_header('Content-Disposition', 'attachment', filename=...),否则收件方看不到下载项
价格变动判断逻辑不能只比数字大小
竞品页面可能临时下架、显示“缺货”或价格为 "¥--",直接 float(new_price) > float(old_price) 会抛 ValueError。更糟的是,有些网站用“¥1,299.00”带千分位,float() 会失败;还有价格含促销标签如“立减¥200”,需正则清洗。
实操建议:
- 统一用正则提取数字:
re.search(r'[\d,]+\.?\d*', text),再.replace(',', '')去掉逗号 - 存历史价格时,字段类型用
REAL(SQLite)或DECIMAL(MySQL),别用TEXT,否则排序和计算都出错 - 判断变动前先检查是否有效值:
if not new_price or new_price.lower() in ['--', '缺货', '暂无报价']:,跳过本次对比
APScheduler 默认用系统时区,但服务器可能在 UTC,而你的“每天 9:00”需求是北京时间。得显式传 timezone='Asia/Shanghai' 给 Scheduler 实例,不然邮件总在凌晨 1 点发。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











