简介:这是一套面向茅台爱好者与技术用户的i茅台自动预约解决方案,通过程序化方式每日自动完成App预约流程,省去手动操作,并支持Docker一键部署,降低环境搭建门槛。资源包共542个文件,约2.99MB,以Java源码(209个)为核心后端逻辑,配合Vue组件(87个)与JavaScript脚本(84个)构建前端界面,另有SVG图标、XML配置、SCSS样式及yml、bat等部署与启动脚本,整体结构接近一个完整的前后端分离项目。目前已有1483人学习下载,说明该方案在自动预约场景中具备一定参考价值。读者可从中获取可运行的预约程序源码、Docker容器化部署配置、前后端模块划分方式以及环境变量与构建脚本示例,适合具备Java、Docker基础并希望研究自动化预约实现思路的开发者参考,但需自行确认使用行为是否符合平台规则。
1. i茅台每日自动预约:从手动抢不到到 Docker 一键跑起来
每天九点整,i茅台 App 的申购页面会准时刷新,然后就是熟悉的「当前申购人数过多,请稍后再试」。手动点了一个月,一瓶没中,这不是运气问题,是手动操作在时间精度和并发上根本打不过脚本。所谓 i茅台自动预约,本质是用程序在每天固定时间窗口内,自动完成登录态复用、门店与商品选择、申购请求提交这一整套动作,把「人守着点」换成「容器守着跑」。它适合两类人:一类是有基本 Linux 或 Docker 基础、想自己掌控运行环境的开发者;另一类是手里有 NAS、软路由或一台常开小主机的折腾党。Docker 一键部署的价值在于,把 Python 运行环境、依赖库、定时任务、配置文件全部封进镜像,换台机器照样跑,不用再经历一遍装依赖装到怀疑人生的过程。这一章先把这件事的边界讲清楚,后面再拆怎么落地。
2. 自动预约到底在自动什么:请求链路与登录态拆解
2.1 一次申购请求里藏着哪些环节
把 i茅台的一次申购拆开看,它并不是「点一下按钮」这么简单。完整链路大致是:App 启动后校验本地登录凭证,拉取当日可申购的商品列表和门店列表,用户选定商品与门店后提交申购请求,服务端返回申购结果。自动预约脚本要复现的,就是这条链路里除了「人选门店」之外的所有环节。其中最关键的是登录态,也就是请求头里携带的凭证信息。手动操作时这个凭证由 App 自己维护,脚本要做的就是把这个凭证提取出来,在有效期内反复使用。
这里有个容易被忽略的点:凭证是有有效期的,短则几小时,长则几天,过期后所有请求都会返回未登录。所以一个能长期跑的自动预约方案,必须处理凭证失效后的重新获取,或者至少能在失效时给出明确告警,而不是默默失败。很多新手第一次跑脚本,第二天发现没申购成功,排查半天才发现是凭证过期了,这就是典型的「黑匣子」问题。
2.2 为什么用 Docker 而不是直接跑 Python 脚本
直接在一台机器上跑 Python 脚本当然可以,但你会遇到几个现实问题。第一是环境依赖,脚本可能依赖特定版本的 requests、schedule 等库,和你机器上已有的 Python 环境冲突。第二是定时任务,用系统 cron 也能做,但 cron 的环境变量和你的登录 shell 不一致,经常出现「手动跑没问题,cron 跑就报错」的玄学。第三是迁移,换台机器要重新配一遍环境。
Docker 把这些问题一次性解决:镜像里锁死了 Python 版本和依赖版本,容器内的定时逻辑不依赖宿主机 cron,换机器只需要把镜像和配置文件搬过去。这也是为什么热词里 docker 一键部署、docker compose 出现频率这么高——大家要的就是「一次配好,到处能跑」。
2.3 最小可跑的 Docker 部署流程
下面给出一套通用的部署流程。由于具体镜像名称和仓库地址需要以你实际拿到的为准,这里用占位符表示,重点是流程和参数含义。
# 1. 拉取镜像(镜像名以实际为准) docker pull <your-image>:latest # 2. 准备配置目录,存放凭证和商品门店配置 mkdir -p /opt/imt/config cd /opt/imt # 3. 首次运行,挂载配置目录,设置时区为东八区 docker run -d \ --name imt-auto \ --restart unless-stopped \ -e TZ=Asia/Shanghai \ -v /opt/imt/config:/app/config \ <your-image>:latest这段命令里,--restart unless-stopped保证容器异常退出后自动拉起,这是长期运行的关键;-e TZ=Asia/Shanghai让容器内时间与北京时间一致,否则定时任务会在错误的时间触发;-v把配置目录挂载出来,这样修改配置不用进容器。首次运行后,通常需要进入容器或查看日志,按提示完成一次凭证录入。
# 查看运行日志,确认是否正常启动 docker logs -f imt-auto # 如果需要进入容器手动录入凭证 docker exec -it imt-auto /bin/sh日志是排查问题的第一入口。正常启动会打印下次预约时间;如果一直报未登录,说明凭证没配好。参数方面,TZ必须设对,--restart策略建议用unless-stopped而不是always,方便你手动停掉调试。
2.4 docker compose 方式与一键脚本的取舍
如果你更习惯 compose,可以把上面的命令翻译成docker-compose.yml:
version: "3" services: imt-auto: image: <your-image>:latest container_name: imt-auto restart: unless-stopped environment: - TZ=Asia/Shanghai volumes: - ./config:/app/configcompose 的好处是配置即文件,版本管理方便,改完docker compose up -d即可。一键脚本的好处是门槛更低,适合完全不想碰 YAML 的人。我的建议是:如果你只有这一台机器跑这一个服务,一键脚本够用;如果你机器上还跑着别的容器,用 compose 统一管理更清爽。两者不冲突,选一个顺手的就行。
3. 凭证、定时与门店配置:三个必须调对的参数
3.1 凭证获取与刷新:最容易翻车的一步
凭证是整个方案的地基。常见做法是手动抓取一次请求头里的关键字段,填入配置文件。这个过程需要你用到抓包工具,具体工具不展开,核心是找到申购请求的 Request Headers,把其中标识用户身份的字段复制出来。注意,凭证里往往包含时间戳和签名,直接复制可能只有很短的有效期。
更稳妥的做法是让脚本支持凭证自动刷新,但这依赖对登录流程的完整复现,难度更高。对于大多数只想稳定跑起来的用户,我一般建议先用手动凭证跑通,确认整个链路没问题,再考虑要不要上自动刷新。手动凭证的刷新频率取决于实际有效期,建议每天检查一次日志,发现失效及时更新。
注意:凭证属于个人敏感信息,配置文件不要提交到公开仓库,也不要在群里截图分享。
3.2 定时时间怎么设才不白跑
i茅台的申购有固定时间窗口,脚本的定时任务必须落在这个窗口内。设早了,商品还没上架;设晚了,名额可能已经满了。常见做法是把触发时间设在窗口开启后的几秒内,留出网络请求的缓冲。
# 定时逻辑示意,实际以镜像内实现为准 import schedule import time def job(): # 这里调用申购流程 do_reserve() # 每天 9:00:02 触发,避开整点瞬间的拥堵 schedule.every().day.at("09:00:02").do(job) while True: schedule.run_pending() time.sleep(1)参数上,09:00:02这个秒数不是随便写的。整点瞬间是请求高峰,稍微错开一两秒反而更容易成功。但也不能太晚,具体窗口长度以实际为准。如果你的容器时间不对,这个定时就是白设,所以前面强调的TZ一定要配对。
3.3 门店与商品配置:选错等于没跑
自动预约需要指定申购哪个商品、哪个门店。配置通常是一个列表,脚本会按顺序尝试。这里有个策略问题:热门门店中签率低但价值高,冷门门店中签率高但可能不是你想要的产品。常见做法是配置多个备选,脚本依次提交。
| 配置项 | 含义 | 建议 |
|---|---|---|
| item_id | 商品标识 | 以实际抓取为准,不要手写猜测 |
| shop_id | 门店标识 | 可配多个,按优先级排列 |
| retry | 失败重试次数 | 2 到 3 次,太多会触发风控 |
| interval | 重试间隔秒数 | 1 到 2 秒,太短容易被限流 |
配置完成后,先手动触发一次,看日志里返回的结果,确认商品和门店都正确,再交给定时任务。很多人跳过这一步,结果跑了一周才发现门店 ID 填错了,血泪经验。
4. 避坑与排查:跑不起来时先看这几条
4.1 容器启动就退出
现象:docker ps看不到容器,docker ps -a显示已退出。原因通常是配置文件缺失或格式错误,脚本启动时读取失败直接退出。解决:先docker logs看报错,多半是配置文件路径不对或 JSON 格式有误。检查挂载目录里文件是否真的存在,JSON 是否有多余逗号。
4.2 日志显示未登录但凭证刚更新过
现象:明明刚填了新凭证,日志还是报未登录。原因可能是凭证字段复制不全,或者容器时间与服务器时间偏差过大导致签名校验失败。解决:重新抓取完整请求头,确认TZ设置正确,用date命令在容器内核对时间。
4.3 定时到了但没有任何请求发出
现象:日志显示等待中,到了设定时间却没有申购记录。原因通常是容器内时区不对,或者定时表达式写错。解决:进容器执行date确认时间,检查定时配置的时区基准。这是最隐蔽的坑,因为脚本本身没报错。
4.4 请求频繁被限流
现象:日志里出现大量失败,提示请求过于频繁。原因:重试间隔太短或重试次数太多。解决:把interval调到 2 秒以上,retry降到 2 次。自动预约不是并发越高越好,稳定比激进更重要。
4.5 换机器后跑不起来
现象:原来机器上正常,迁移到新机器就失败。原因:新机器没装 Docker,或者 Docker 服务没启动,或者镜像没拉全。解决:先确认docker info能正常输出,再确认镜像存在。Windows 用户注意,Docker Desktop 需要 WSL2 支持,如果提示 virtualization support not detected,要去 BIOS 开启虚拟化。
5. 让自动预约更稳的两个进阶技巧
第一个技巧是加一层结果通知。脚本跑没跑成功,你不看日志就不知道,但每天手动看日志不现实。常见做法是接入一个通知渠道,申购成功或凭证失效时推送一条消息。实现上就是在申购流程结束后判断返回码,命中特定状态就发通知。这样你只需要在收到「凭证失效」时去更新一次,其余时间不用管。
def notify(msg): # 伪代码,替换成你实际使用的通知方式 requests.post(WEBHOOK_URL, json={"text": msg}) result = do_reserve() if result["code"] == "SUCCESS": notify("申购提交成功") elif result["code"] == "AUTH_FAIL": notify("凭证失效,请更新")第二个技巧是给容器加健康检查。Docker 支持HEALTHCHECK指令,定期执行一个命令判断服务是否正常。如果脚本卡死,健康检查失败后配合--restart策略可以自动重启。这比你自己盯着强。
HEALTHCHECK --interval=1h --timeout=10s \ CMD python /app/healthcheck.py || exit 1参数上,interval不用太短,一小时一次足够,因为预约本身一天就一次。timeout给 10 秒,避免误判。
最后说个我自己的习惯:每次更新凭证后,我会手动触发一次申购流程,看日志确认返回正常,再让它自己跑。这个动作花不了一分钟,但能避免「以为在跑其实早就挂了」的情况。自动预约这件事,稳定运行比功能花哨重要得多,把凭证、时间、门店这三个参数管好,基本就不会出大问题。希望帮到你。
本文还有配套的精品资源,点击获取