iPhone新品首发那段时间,我相信很多人都经历过一种焦虑:页面刷了又刷,购物车加了又加,结果一到结算就是“已售完”。更气人的是,过半小时再点进去,某个门店又冒出两台现货,等你切过去早就没了。这种“明明有货,却总是错过”的感觉,才是抢购真正的痛点。
后来我干脆想,与其靠人肉刷新,不如让程序盯着苹果产品的库存接口。但这个想法刚冒出来,又被自己劝退了:写爬虫、解析 JSON、处理异步请求、接通知服务,这套流程一个人从零开始搞,怎么也得一个周末。那几天我正好在试 OpenAI 的 Codex,一个能在终端里自主写代码、跑命令、看报错、自己改代码的 AI 编程 Agent。我突发奇想:这种“目标明确、逻辑相对独立”的小工具,不正是让 AI 来做最好的场景吗?于是就有了这个项目:用 Codex 做一个苹果库存监控工具。
这篇文章我不打算写成教程式的说明书,而是想认真聊聊整个过程中最值得记录的几件事:为什么我会选 Codex 而不是自己手写,监控工具的架构是怎么一步步被 AI 搭起来的,以及在实战里踩过的那些坑。无论你是对 AI 编程感兴趣,还是想用技术解决“抢不到货”这种小烦恼,这篇文章应该都能给你一些启发。
1. 需求拆解:为什么“抢不到”本质上是个信息差问题
1.1 库存不是一次性放出的,而是动态流动的
很多人以为 iPhone 新品开售是“一次性放出全部库存”,实际上并不是这样。苹果线上商店的库存,尤其是热门型号和颜色,经常会以非常不规律的方式分批释放。可能是有人取消订单后回流,可能是某个仓库临时调配,也可能是区域配送计划的间隙。这些库存往往只存在几分钟,甚至几十秒。
这就是信息差:你看到的“无货”,只是某个瞬间的无货,并不代表接下来五分钟不会补货。而人工刷新页面的频率,再快也就是几分钟一次,中间的大量窗口期全部浪费掉了。所以库存监控工具的核心价值,不是“抢”,而是“第一时间感知变化”。它用程序替你把“盯着页面”这个动作做到极致,一旦检测到状态变化就立刻提醒你。
1.2 监控工具的三个基本职责
一个合格的库存监控工具,至少要做三件事:
轮询
:定期去请求苹果产品的库存接口,获取某个产品编码在附近门店的实时库存状态。
判断
:把当前结果与上一次结果做对比,只有在状态发生变化时才触发后续动作,避免重复通知。
通知
:通过手机推送、即时通讯机器人等渠道,把“某门店出现现货”这个消息以最快速度送到你手上。
听起来不复杂,但真正落地时你会发现,这三件事分别对应了网络请求、状态管理和异常处理,每一项都有不少细节。比如轮询频率太高会被风控,判断逻辑不严谨会漏报或误报,通知服务没配好会导致消息延迟。这些细节,正是 AI 辅助编程最容易“翻车”的地方,也是后面 Codex 让我惊喜又头疼的原因。
2. 为什么选 Codex?AI Agent 和传统补全工具完全是两个物种
2.1 Codex 到底是什么
Codex 是 OpenAI 推出的编程 Agent,准确说,它能直接在终端里“干活”。跟你在 IDE 里用 Copilot 补全代码不一样,Codex 不是等你敲几个字符再帮你接一句,而是你给它一个目标,它自己去读项目文件、写代码、执行命令、看运行结果、根据报错自动修复。整个过程是循环的:执行、观察、修正、再执行。
我用的是 Codex CLI,在终端里跑
codex
命令启动交互式会话。它可以在你指定的目录下自由操作文件系统,相当于一个能自己动手写代码的“实习生”。这件事的震撼感在于,你不再需要把每一行代码都想好,只需要把需求描述清楚,它就能把整个功能骨架搭起来。
2.2 Agent 式开发与传统 AI 编程的差别
传统 AI 编程工具,比如 IDE 里的代码补全,本质是“在你已经搭好的框架里填内容”。人还是主导者,你得自己规划模块、自己建文件、自己处理依赖关系。
Codex 这种 Agent 式工具则完全不同。它更像一个拥有“工程能力”的初级开发人员:你告诉它“帮我写一个异步轮询苹果库存接口的脚本”,它会自己决定用哪个库、建几个文件、怎么组织函数、怎么处理异常。你后期做的是“验收”和“纠偏”,而不是“零开始编码”。
这个差别对做小工具来说意义很大。库存监控这种项目,逻辑不算复杂,但要写的样板代码不少:异步客户端、重试机制、参数解析、通知封装……如果人手写,至少磨蹭半天。Codex 在一个小时之内就能把整套东西跑起来。我只需要在关键节点上检查它的思路,防止它跑偏。
2.3 选型思考:Python 还是 Node.js?
我一开始没指定语言,Codex 默认用了 Python,理由是生态成熟:
httpx
做异步请求、
apscheduler
做定时调度、
json
处理解析,都是现成方案。我认可这个选择,因为 Python 的工具链对“写监控脚本”这类任务是最省事的。就算你不熟悉 Python,读它的代码也相对容易理解。
不过这里有个很重要的原则:你可以让 AI 选技术栈,但你自己必须清楚验收标准。Codex 选了 Python,我就按 Python 项目的惯例去检查它;如果它选了 Node.js,我也会用 Node 的方式去验收。AI 可以决定“怎么做”,但“做成什么样才合格”,必须由人来定义。
3. 核心实现拆解:库存监控工具的完整技术链路
3.1 数据源:苹果产品的库存JSON接口
要监控库存,首先得知道数据从哪来。苹果产品的商品详情页并不是纯静态页面,当你进入“选购”流程、选择型号后,页面上会显示附近门店的取货可用性,这部分数据是通过异步请求加载的。浏览器开发者工具里能看到一个返回 JSON 的接口,里面包含每个店铺的库存状态、可用数量、取货时间等信息。
这个接口需要带几类参数:
产品编码,也就是你盯的那款 iPhone 的零件号,页面数据里能找到。
地域信息,通常是经纬度,用来计算附近门店。
请求头,至少要带正常的 User-Agent,否则很容易被识别成异常请求。
我没有在文章里直接贴具体接口地址,因为这类接口的细节会随着产品改版而变化。更重要的是思路:找数据接口、看返回结构、定位字段、封装请求。这个思路通用性极强,换任何网站都成立。
3.2 技术架构:异步并发 + 状态对比 + 多路通知
确认数据源之后,我给 Codex 描述的目标是:写一个 Python 脚本,每隔一段时间查询附近门店的库存,发现状态变化就发送通知。Codex 给出的结构大概是这样的:
config.py
:集中管理产品编码、门店列表、轮询间隔和通知方式。
fetcher.py
:负责请求库存接口,解析每个门店的库存状态。
compare.py
:保存上一次的查询结果,用于差异检测。
notifier.py
:封装通知渠道,包括微信机器人、Telegram、Server酱等。
main.py
:主循环,负责按时间间隔执行抓取、比较和通知。
这个分层很合理。我唯一调整的是把“对比”单独拎出来成一个模块。原因是状态变化检测是这整个工具的大脑:如果每次都无脑通知,手机一会儿就会被轰炸;如果变化检测逻辑写错了,该通知的时候又没反应。所以对比逻辑必须独立、清晰、可测试。
3.3 关键代码:核心轮询逻辑是怎么实现的
下面这段是 Codex 写的核心抓取逻辑简化版,我加了一些注释。要注意,接口地址和字段名我是按当时抓包的示例写的,上线前你需要以实际抓包结果为准。
import asyncio
import httpx
import random
STORE_LIST = [
{"id": "R001", "name": "示例门店A", "lat": 31.2304, "lng": 121.4737},
{"id": "R002", "name": "示例门店B", "lat": 39.9042, "lng": 116.4074},
]
async def fetch_store_availability(client, store, product_code):
"""查询单个门店的库存状态"""
params = {
"product": product_code,
"location": f"{store['lat']},{store['lng']}",
}
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)",
"Accept": "application/json",
}
try:
resp = await client.get(
"[地址已省略]",
params=params,
headers=headers,
timeout=10,
)
resp.raise_for_status()
data = resp.json()
# 实际字段需根据接口结构调整
return data["store"]["availability"]
except Exception as e:
return {"error": str(e)}
async def main():
async with httpx.AsyncClient() as client:
# 使用信号量限制并发,比如同一时间最多发 3 个请求
sem = asyncio.Semaphore(3)
async def guarded(store):
async with sem:
return store["id"], await fetch_store_availability(client, store, PRODUCT_CODE)
results = await asyncio.gather(*(guarded(s) for s in STORE_LIST))
for store_id, availability in results:
print(store_id, availability)
if __name__ == "__main__":
asyncio.run(main())
这段代码的关键点是用了
Semaphore(3)
。这是我特意让 Codex 加的,因为如果不限制并发量,几十家门店同时发请求,很快就会被服务器拒之门外。
3.4 轮询策略与风控意识
监控工具本质上是一个自动化请求程序,所以必须对目标服务器保持基本的尊重。我的策略是:
把轮询间隔设置为 15 到 30 秒随机化,避免像定时炸弹一样在同一秒发出请求。
每次请求之间引入 0.5 到 2 秒的随机延迟,打散请求节奏。
单轮查询完所有门店后必须休息一轮,不做持续高频请求。
失败时采用指数退避重试,比如首次等待 2 秒、第二次 4 秒、第三次 8 秒,最多重试 3 次。
注意:任何网站的接口都不是给你无限刷的。监控工具的价值在于“知道何时有货”,而不是“把服务器干趴下”。保持低频、随机、克制,是对自己账号安全也是对服务商基本的尊重。
这个部分是整个项目里最需要你坚守原则的地方。AI 不会主动告诉你“你这个频率太高了”,但它写出来的代码会默默把你推向风险边缘。作为项目负责人,把握节奏的必须是你。
4. 实操过程:我是怎么用 Codex 一步步把工具搭起来的
4.1 第一次对话的关键提示词
用 Codex 写项目,最重要的不是它的能力,而是你“怎么描述需求”。我第一次给的提示词就踩了坑,只写了一句“帮我写个苹果库存监控”,结果是代码跑倒是能跑,但什么都没监控到——因为我不知道具体产品编码,也没告诉它怎么获取数据源。
后来我重构了提示词,把目标拆成了几层:
我要做一个苹果官网库存监控工具。
目标:
1. 根据我提供的产品编码,查询附近门店的可用库存。
2. 每 20 秒轮询一次,如果某个门店的库存状态发生变化,就发送通知。
3. 通知方式先接企业微信机器人,后续再加 Telegram。
已知信息:
- 我在 config.py 里提供一个 STORE_LIST,包含门店 id、名称、经纬度。
- 库存接口可以抓包获取,先按这种 URL 格式写:`[地址已省略]。
- 返回的 JSON 结构我待会儿会贴给你。
请在项目目录里初始化 Python 项目,并保证代码可直接运行。
这个提示词的关键在于:我给了 Codex 明确的“验收标准”和“已知条件”,而不是让它在真空中猜测。它对业务的理解完全来自我的话,我给得越具体,它做出来的东西就越贴近真实需求。
4.2 Codex 的完整工作流程实录
Codex 的交互方式很像在终端里“远程指挥”一名工程师。我观察下来,它会自己执行这么几步:
扫描当前目录,确认有没有现成的项目结构。
创建虚拟环境和依赖文件,安装
httpx
、
apscheduler
等库。
按我描述的目标分模块写代码,先写核心抓取,再写通知。
运行测试脚本,观察输出。
遇到报错时,自己读 traceback,定位问题,修改代码,重新运行。
让我比较惊艳的一个场景是:第一版代码跑起来后,出现了
json.decoder.JSONDecodeError
,原因是我给的接口地址是示意性的,返回的是 HTML 而不是 JSON。Codex 没有干等,它自己去分析响应内容,尝试从 HTML 里找到库存字段,然后调整了解析逻辑。这种“发现问题—分析原因—自动修复”的闭环,是传统 AI 补全工具完全做不到的。
当然,它也有让我无语的时候。比如它会把我的示意接口地址当成真实地址,努力尝试“修正”它。这时候我就得提醒它:接口地址我是占位的,真实地址需要抓包拿到,你先别在这个上面死磕。这里也体现了人类的必要性:AI 缺乏外部世界的真实信息,需要你给它提供“现实数据”。
4.3 人工验收:AI 写的代码不能直接信任
Codex 写完全部代码后,我做了一次系统的验收,主要查几个点:
请求频率是否合理
:看主循环里有没有写死的短间隔,有没有随机延迟。
异常处理是否健壮
:网络请求失败时会不会导致整个程序崩溃。
通知内容是否清晰
:推送消息有没有包含门店名、产品名、当前状态。
对比逻辑是否准确
:状态变化时,是“有货 => 无货”和“无货 => 有货”都能触发,还是只触发其中一种。
我检查后发现 Codex 的一个典型问题:它把“有货”判定写成了一个固定布尔值,但真实接口返回的状态字段可能是“available today”“unavailable”之类的字符串,甚至包含数量。这种“AI 对字段理解的偏差”如果不在验收阶段发现,上线后就会变成漏报。
我给它补充了字段样例后,它很快调整了判断逻辑。这个过程中我的角色是“测试工程师”,而非“编码工程师”。这也说明了一个趋势:AI 编程时代,人的核心能力正从“怎么写代码”转向“怎么定义好问题,以及怎么验收答案”。
5. 实战避坑:测试和上线过程中踩过的那些坑
5.1 代码没问题,但接口被风控了
第一版工具上线后,我美滋滋地等着通知。结果跑了不到 20 分钟,发现所有请求都返回空数据,像是被“静静屏蔽”了。排查了半天,不是代码逻辑问题,而是请求频率太高,触发了服务端的风控。
解决办法是调整策略:把轮询间隔从 10 秒拉到 30 秒,并且每次请求都带上短暂的随机延迟。另外我给每个请求加上了更完整的请求头,包括
Accept-Language
和
Referer
,让请求看起来更像从浏览器页面发起的。调完之后,跑了整整一天,再没出现过被屏蔽的情况。
这个坑给我最大的教训是:
监控工具真正的敌人不是“接口不存在”,而是“你的请求姿势不正确”。
如果每次访问都像一个无感情的刷量机器人,服务商当然会给你上“冷静期”。
5.2 Codex 终端工具的经典报错:“local proxy failed while handling codex endpoint”
用 Codex CLI 的过程中,最常见的报错之一就是类似
cc switch local proxy failed while handling codex endpoint /responses.
这样的信息。它的大意是:Codex 在调用本地后端服务时,网络代理这一环出了问题,导致请求没能送到 Codex 的接口服务上。
我遇到这个问题的场景很典型:频繁切换网络环境后,Codex 突然开始报错,代码写一半根本没法继续。解决思路如下:
先检查本地代理配置是否和当前网络环境匹配。很多开发者会配置本地 HTTP 代理工具来调试接口,如果代理规则没更新,所有请求都可能被卡住。
清理 Codex 的配置缓存,重新登录确认会话状态。
升级 Codex CLI 到最新版本,新版本对网络异常的容错通常更好。
这个报错本身不是代码问题,而是运行环境问题。我的习惯是遇到这类网络层问题,先不急着改代码,而是理清调试工具、系统代理、应用配置这三层关系,再逐层排查。
5.3 模型不支持的报错:“model is not supported”
有一次我更新 Codex 后,运行时报了类似
the 'gpt-5.6-sol' model is not supported when using codex
的错误。原因是我的配置文件中指定了一个当前版本 CLI 不支持的模型名,或者本地版本太旧,不认识新模型。
解决方式很简单:检查
config.toml
里的
model
配置,改成你当前可用、受支持的模型名;或者升级 CLI 版本,让配置项和实际运行环境匹配。这类问题都需要你先冷静看一下报错信息里的关键词,“not supported”指向的就是配置和版本不匹配。
5.4 配置文件告警:“unrecognized configuration setting”
Codex 对配置文件的解析是很严格的。有一次我在配置文件里加了一行自定义参数,结果启动时给了个警告:
codex is ignoring 1 unrecognized configuration setting. Check for typos or deprecated keys.
翻译过来就是“有个配置项我没认出来,我给忽略了”。
这类问题一定要重视。配置被忽略,意味着某些行为不会按你预期工作。可能你自以为设置了某个开关,实际却用的是默认值。解决办法是逐个检查配置项,删除已经废弃的键,或者查文档确认最新写法。
5.5 通知渠道对比与选型
监控工具最后一步是把结果送到你手上,通知渠道的选择也很重要。我实际用过三类:
| 渠道 | 优点 |
|---|
缺点
|
适合场景
|
| Server酱 | 配置简单,微信公众号推送 |
|---|
需要申请 Key,依赖第三方平台
|
个人自用,快速上手
|
| 企业微信机器人 | 推送速度快,可以发普通文本和 Markdown |
|---|
需要创建企业微信群
|
手头有现成群,通知比较稳定
|
| Telegram Bot | 全球可达,API 开放,机器人配置简单 |
|---|
部分网络环境下访问不稳定
|
已有 Telegram 使用习惯的用户
|
我最后选的是企业微信机器人 + Server酱双路通知。原因是可靠性优先:万一其中一个通道服务波动,另一个还能兜底。通知消息里我会带上门店名称、具体型号、库存状态和查看链接,减少收到通知后还要自己去产品反复确认的时间。
6. 常见问题与排查技巧实录
用 AI 做项目,最磨人的其实不是 AI 本身,而是它出错时你怎么定位。我整理了一份自己真实的排查记录,按“症状—原因—处理”的格式放在下面,方便你对照。
| 症状 | 可能原因 |
|---|
处理方式
|
| 程序运行后没有拿到任何数据 | 接口地址是占位符,或者返回结构解析失败 |
|---|
打开浏览器开发者工具,重新抓包确认真实接口和字段
|
| 请求返回 429 或空数据 | 请求频率太高触发风控 |
|---|
调大轮询间隔,加随机延迟,补全请求头
|
| 有货时不通知,无货时乱通知 | 对比逻辑只判断了单一方向的状态 |
|---|
检查 compare 模块,确保“从无到有”和“从有到无”都触发
|
| 推送偶尔延迟超过 5 分钟 | 通知服务本身不稳定,或者网络链路有问题 |
|---|
配置双路通知,用备用通道兜底
|
| Codex 半天不动,像是在“死循环” | 任务目标不清晰,或它在一个分支里绕不出来 |
|---|
中断会话,重新描述需求,给出现有的代码文件和明确的下一步
|
| 代码能跑,但换一个产品编码就失效 | 硬编码了产品编码或门店信息 |
|---|
把可变参数全部抽到 config.py,代码里禁止出现业务常量
|
| 程序崩溃后没有自动恢复 | 缺少异常捕获和重启机制 |
|---|
给主循环加 try/except,配合 systemd 或 supervisor 常驻运行
|
这里我想特别强调“硬编码”这个问题。Codex 第一版写出来的东西特别倾向于把产品编码、门店列表直接写在函数参数里,看起来方便,但换一个型号就要改代码。我后来专门花了一轮会话让它把配置全部外置,过程和结果都清爽了很多。
还有一个容易被忽视的细节:监控工具跑的时间长了,会产生大量日志。如果不做日志轮换,磁盘很快会被撑满。我给 Codex 加了一个按天滚动写入日志文件的需求,它写得很干净,这样即使工具连续跑几个月,也不会把机器拖垮。
7. 扩展思路:这个项目还能玩出什么花
等库存监控跑稳定之后,你会发现整个架构可以迁移到各种“信息差”场景。核心模式都是一样的:
低频轮询公共接口 + 状态变化检测 + 即时通知
。比如:
监控某个购物网站的商品降价,把“库存状态”替换成“价格字段”,对比逻辑从“是否有货”改成“价格是否低于阈值”。
监控场馆票务平台的余票,逻辑几乎一模一样。
监控某个查询接口返回的特定关键字,比如新版本固件发布公告。
更有意思的是,你可以让多个 AI Agent 参与这个项目,一个负责写代码,一个负责审查代码,一个负责写测试用例。多 AI 协作的意义在于互相当“质检员”,能够显著降低单个模型产生的盲区。我在这个项目的后期测试脚本就是让另一个 AI 会话帮忙写的,它确实找出了一些边界问题。
这个经验也再次说明了一件事:在 AI 编程时代,你的工作重心会从“亲手写每一行代码”迁移到“设计系统、定义验收标准、整合多个 AI 的产出”。这就像一个制片人,不再需要自己扛摄影机,但必须知道每个镜头要拍什么,以及怎么判断拍得好不好。
我个人的体会是,Codex 这类工具最大的价值不是“帮你省时间”,而是“帮你找回做小项目的主动权”。以前很多念头因为“工程量太大”而被搁置,现在只需要把目标描述清楚,AI 就能在半小时内把骨架搭起来。你依然需要理解代码逻辑、理解业务边界、理解风控规则,但这种“理解”的成本,已经比“从零手写”低太多了。
如果你手头也有一个“要是能自动盯着就好”的小需求,我建议你直接打开 Codex,用这篇文章里的提示词结构试一试。第一次跑通之后你会感受到,真正困难的从来不是写代码,而是想清楚你到底想要什么。
