Day 6
海外运营 × Codex 训练营

竞品监控爬虫
每日自动抓 + 推飞书

让 Codex 写一个每天 9 点自动跑的脚本,
抓 3-5 个竞品的价格 / 上新 / 活动 → 只把"变化"推到飞书
从此你比对手早 24 小时知道动向。

讲师 Terrence 时长 90 分钟 产物 1 个 GitHub Action + SQLite 历史库 + 飞书机器人推送
Day 6 · 开场

今天结束,你能做到

关键判断:不是"我会爬虫了"——是"我有了一个 24/7 帮我盯着对手的数字员工"。
Day 6 · 开场

在开始之前——
你做竞品监控的真实状态

传统做法
  • 每天上班打开 5 个竞品网站手动看(15 分钟)
  • 看到价格变化截图存微信群(半小时)
  • 周末总结写"竞品周报"(2 小时)
  • 漏看促销 / 上新 → 老板问起来支吾
  • 结果:看完忘了,对比靠记忆

每天 30 分钟 · 漏报率 60%

Codex 做法
  • 一次性给 Codex 描述竞品 + 字段(20 分钟)
  • Codex 写爬虫 + diff + 推送脚本(自动)
  • 部署 GitHub Action 每天 9 点跑(5 分钟)
  • 飞书机器人 只在有变化时推你(0 噪音)
  • SQLite 留 30 天历史,随时回查

1 次 30 分钟搭建 · 之后 0 维护

💡 核心差异:手动监控的边际成本是"每天都要花时间",Codex 监控的边际成本归零——加一个竞品只需多写一段 prompt。
Day 6 · 选字段

监控什么字段 · 海外运营 5 类高价值变化

1
价格 / 折扣(变价 = 直接影响转化)主页 banner 价 · 主推 SKU 详情页价 · checkout 时的促销 code
2
首页 banner / hero 文案(活动起跑信号)banner 一改 → 大概率是新 campaign · 比官方 newsletter 早 1-3 天
3
SKU 数 / 新品上架(产品节奏)从 collection 页抓产品总数 · 数字+1 就是上新
4
社交内容节奏(投放信号)TikTok / Instagram 24h 新视频数 + TOP 3 标题 · 数量翻倍 = 加投预算
5
评论 / 评分(口碑反转)Trustpilot / Amazon 评分小数点变化 · 差评激增 = 出事了
💡 新手只抓 1-3。先把"价格 + banner + SKU 数"跑通,再加社交和评论。别一上来 5 个全要
Day 6 · 架构

5 块拼图 · 看懂全流程

┌─────────────────────────────────────────────────────────┐ │ GitHub Action (cron: 0 9 * * *) ← 每天 9:00 触发 │ └────────────────────────┬────────────────────────────────────┘ │ ▼ ┌────────────────────────────────┐ │ Playwright 无头浏览器 │ │ 抓 3 个竞品官网 + 1 个 TikTok │ └──────────┬─────────────────────┘ │ 提取字段 ▼ ┌────────────────────────────────┐ │ SQLite (snapshots.db) │ │ 按 (date, competitor, field) │ └──────────┬─────────────────────┘ │ diff vs 昨天 ▼ ┌────────────────────────────────┐ │ changes.json (只含变化项) │ └──────────┬─────────────────────┘ │ POST webhook ▼ ┌────────────────────────────────┐ │ 飞书机器人 → 你的运营群 │ └────────────────────────────────┘
🔑 核心设计:SQLite 是"记忆",diff 是"判断变化",飞书是"通知"——三段缺一不可。少了 SQLite 你每天收到全量快照,必然刷屏。
Day 6 · 工具选型

为什么用 Playwright 不用 requests?

requests + BeautifulSoup

✓ 轻量快
✗ 现代网站 90% JS 渲染
✗ 抓不到价格 / 评分
✗ 反爬一上就废

适用:纯静态 HTML 老网站

Playwright 🏆

✓ 真实浏览器(JS 全渲染)
✓ 反检测能力强
✓ Codex 训练数据充足
✓ 截图 / 视频 / cookie 全支持

适用:所有现代网站 ✓

Selenium

✓ 老牌稳定
△ API 啰嗦
△ 速度慢
✗ 配置链长

适用:遗留项目

讲师选择:Playwright + Python(不用 Node)。原因:Codex 写 Python 比写 Node 准,且数据处理 / SQLite 一站式。

Day 6 · Prompt

核心 Prompt · 直接复制改 3 处

我想监控以下 3 个海外竞品(每天 9 点抓一次): 1) 竞品 A · https://glossier.com 抓:主页 hero banner 文案 + 主推产品("Boy Brow")价格 2) 竞品 B · https://thekrazycouponlady.com 抓:当前促销 code(首页顶部 announcement bar) + 主推 collection 的 SKU 数 3) 竞品 C · TikTok @glossier 抓:最近 24 小时新发视频数 + TOP 3 视频标题 输出: 1) Python 脚本(用 Playwright,headless 模式,含 User-Agent + 随机延迟) 2) 结果保存到 SQLite (snapshots.db):(date, competitor, field, value) 3) 每天和昨天 diff,找出变化项(只对比 value 字段) 4) 把变化推送到飞书机器人(webhook: https://open.feishu.cn/open-apis/bot/v2/hook/XXXX-XXXX-XXXX) 消息格式:Markdown,标题 "📊 竞品日报 {today}", 每个变化一行:"{竞品} · {字段}: {昨天} → {今天}" 5) 部署:GitHub Action 每天 UTC 01:00(=北京 09:00)自动跑 workflow 文件路径 .github/workflows/monitor.yml 合规: - 遵守 robots.txt - 不爬登录后内容 - 请求间隔 ≥ 3 秒 - 单次最多 20 个页面 文件结构: - monitor.py - requirements.txt - .github/workflows/monitor.yml - README.md(含部署步骤)
⚠️ 3 个地方必改:(1) 竞品 URL 和字段描述 (2) 飞书 webhook (3) cron 时区(北京 9 点 = UTC 1 点)。
Day 6 · 演示

Step 1 · Codex 生成的 monitor.py 长什么样

import sqlite3, json, time, random from datetime import date from playwright.sync_api import sync_playwright DB = "snapshots.db" COMPETITORS = [ {"name": "glossier", "url": "https://glossier.com", "selectors": {"hero": ".hero-text", "boybrow_price": ".product-price"}}, # ... 其余 2 个 ] def init_db(): conn = sqlite3.connect(DB) conn.execute("""CREATE TABLE IF NOT EXISTS snapshots ( date TEXT, competitor TEXT, field TEXT, value TEXT, PRIMARY KEY (date, competitor, field))""") return conn def scrape(page, comp): page.goto(comp["url"], wait_until="networkidle") return {k: page.locator(s).first.inner_text() for k, s in comp["selectors"].items()} # ... 主循环:抓 → 存 → diff → push 飞书

你不需要懂代码——但要看懂 3 个块:(1) COMPETITORS 配置 (2) scrape() 抓取 (3) 主循环。改竞品 = 改第一个 list。

Day 6 · 演示

Step 2 · selector 不用你写 · 让 Codex 自己找

你只需要把竞品页面截图给 Codex,告诉它"框出来这块的价格"。

[拖一张 glossier.com 首页截图给 Codex] 我标黄的部分(页面顶部"Boy Brow $18")就是要抓的字段。 请帮我找到它的 CSS selector,并加到 monitor.py 的 glossier.selectors.boybrow_price 里。 如果 selector 不稳(类名是动态生成的 hash), 改用 XPath 或者文本匹配。
💡 新手最大障碍解决:以前抓数据卡在"找不到 selector",现在截图给 AI就行。Codex 会用 Playwright Inspector / DevTools 思路自己分析。

如果 selector 不稳定(Shopify / Next.js 动态 class):

Day 6 · 演示

Step 3 · diff 逻辑 · 别让自己被淹

只推变化,不推快照——这是和"全量日报"的核心区别。

def diff_with_yesterday(conn, today): yesterday = (date.today() - timedelta(days=1)).isoformat() changes = [] for row in conn.execute( "SELECT competitor, field, value FROM snapshots WHERE date=?", (today,) ): prev = conn.execute( "SELECT value FROM snapshots WHERE date=? AND competitor=? AND field=?", (yesterday, row[0], row[1]) ).fetchone() if prev and prev[0] != row[2]: changes.append({ "competitor": row[0], "field": row[1], "from": prev[0], "to": row[2] }) return changes
✓ 推送

glossier · Boy Brow 价格
$18 → $16

krazycouponlady · 促销 code
"SUMMER10" → "MEMORIAL20"

✗ 不推

所有字段每天
原样展示一遍

→ 看 3 天你就把通知关了

Day 6 · 演示

Step 4 · 飞书机器人推送长这样

推送代码:

import requests WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/XXXX" def push(changes): if not changes: return lines = ["📊 **竞品日报** " + date.today().isoformat(), ""] for c in changes: lines.append( f"• **{c['competitor']}** · {c['field']}: " f"`{c['from']}` → `{c['to']}`" ) requests.post(WEBHOOK, json={ "msg_type": "interactive", "card": {"elements": [{ "tag": "markdown", "content": "\n".join(lines) }]} })

飞书消息预览:

📊 竞品日报 2026-05-27
  • glossier · Boy Brow 价格: $18$16
  • krazycouponlady · 促销 code: SUMMER10MEMORIAL20
  • glossier-TikTok · 24h 新视频: 27
🤖 监控机器人 · 09:00
💡 换钉钉 / Slack / Telegram:prompt 改一行——"把飞书 webhook 替换成钉钉 / Slack incoming webhook"。其余逻辑完全一样。
Day 6 · 部署

Step 5 · GitHub Action · 关电脑也跑

为什么要 GitHub Action?因为你不可能 24/7 开电脑。Action 是 GitHub 给你的免费服务器(公开仓库每月 2000 分钟)。

# .github/workflows/monitor.yml name: Daily Competitor Monitor on: schedule: - cron: '0 1 * * *' # UTC 01:00 = 北京 09:00 workflow_dispatch: # 手动触发按钮(调试用) jobs: monitor: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: { python-version: '3.11' } - run: pip install -r requirements.txt - run: playwright install chromium - run: python monitor.py env: FEISHU_WEBHOOK: ${{ secrets.FEISHU_WEBHOOK }} - uses: actions/upload-artifact@v4 # 保留 SQLite 历史 with: name: snapshots-db path: snapshots.db
🔐 FEISHU_WEBHOOK 存在 GitHub Secrets:仓库 Settings → Secrets and variables → Actions → New repository secret。千万别直接写在代码里
Day 6 · 反爬

竞品网站不让爬怎么办

轻度反爬 · 90% 站点
  • 加真实 User-Agent(Codex 自动加)
  • 请求间隔 ≥ 3 秒(不刷接口)
  • Playwright headless=False(解析极少数检测)
  • 用住宅 IP(GitHub Action 自带数据中心 IP,被识别就上代理)
中度反爬 · Cloudflare
  • playwright-stealth 插件
  • 跳过 challenge:先访问首页留 cookie,再访问产品页
  • 实在不行 用 Scrapling(开源,反反爬开箱即用)
  • Codex 一句话"用 Scrapling 而不是 Playwright"
🚫 这些坚决不爬:(1) 需要登录的页面 (2) robots.txt 禁止的路径 (3) 个人账号 / 用户信息 (4) 有图形验证码的(爬过去了也违法)。海外尤其严,GDPR / CCPA 罚款起步 $千万
Day 6 · 合规

合规红线 · 海外爬虫 5 条不能碰

  1. 不爬登录后内容——hiQ Labs v. LinkedIn 案后美国判例倾向"公开 = 可爬,需登录 = 禁止"
  2. 遵守 robots.txt——不是法律强制但是行业共识,违反在欧盟可能被列为不正当竞争
  3. 不爬个人信息——用户评论里的姓名 / 邮箱属于 GDPR 个人数据,不存不传
  4. 请求节流——QPS > 1 可能被认定 DoS(拒绝服务攻击),延迟 ≥ 3 秒为底线
  5. 不冒充人类——User-Agent 写明 bot 身份("MyMonitorBot/1.0 contact@xx.com")反而更合规
⚠️ 真实案例:2024 一个国内电商运营爬美国 Sephora 抓 SKU 价格被起诉,因为他爬了商品评论(含用户名)违反 CCPA。只抓"商品本身的公开属性"是安全区
Day 6 · 避坑

常见错误 #1 · selector 第二天就失效

症状:今天跑 OK,明天报错 "selector not found",再查发现网站改版了。

脆弱写法
page.locator(".css-1a2b3c4 > div:nth-child(2) > span").inner_text()

依赖动态 class hash → 改版必废

稳健写法
page.get_by_text("Boy Brow", exact=False) .locator("xpath=..//span[contains(@class,'price')]") .first.inner_text()

文本锚定 + 语义类名 → 改版也能扛

💡 防御策略:让 Codex 在 prompt 里加"selector 失败时发飞书警报,不要静默吞错误"。错误推送 > 沉默
Day 6 · 避坑

常见错误 #2 · 推送变成"通知地狱"

症状:刚上线那 3 天人人盯飞书,第 4 天起没人看了。

3 个止血策略:

改一下 monitor.py: - 只在 changes 非空时推送 - 价格字段变化 < 5% 视为噪音,不推 - 价格 -15% 以上 → 飞书 @所有人 + 加 🚨 - 普通变化 → 普通推送
⚠️ 核心原则:通知是注意力税。每条推送都要值得读。宁可少推不能滥推。
Day 6 · 避坑

常见错误 #3 · 在 GitHub Action 上跑半小时 timeout

症状:本地 10 秒跑完,部署 GitHub Action 跑 25 分钟卡住超时。

原因
  • wait_until="networkidle" 等所有请求结束,分析工具脚本永远 idle 不了
  • 没设超时 → 单页卡住整个 job 不退
  • 抓 TikTok 视频列表用了无限滚动,循环不退出
修法
  • wait_until="domcontentloaded" + 显式 locator.wait_for(timeout=5000)
  • page 级 page.set_default_timeout(15000) 兜底
  • scroll 用固定次数不用 while True(例:scroll 5 次截一次屏)
💡 调试技巧:GitHub Action 一直挂 → 在 workflow 加 workflow_dispatch,本地手动触发,看日志。别在 production cron 上 debug
Day 6 · 实操
现在轮到你

30 分钟实操
盯住你最想盯的 2 个海外竞品

用你真正关心的 2 个竞品(不是讲师示例)
跑完整套流程,最后产出:
1 个 GitHub 仓库 + 1 个能跑的 Action + 1 个飞书机器人推送

⏱ 30 分钟 · 讲师全程巡场

Day 6 · 实操

实操 6 步

1
选 2 个竞品 + 想抓的字段(5 分钟)建议:1 个品牌官网 + 1 个 TikTok/IG · 字段 ≤ 3 个
2
建一个空的 GitHub 仓库(2 分钟)新建 private repo · 名字 competitor-monitor
3
把核心 prompt 贴进 Codex(5 分钟)替换:竞品 URL / 字段 / 飞书 webhook
4
本地跑一次 monitor.py 看输出(5 分钟)python monitor.py · selector 报错就把页面截图丢给 Codex 修
5
推到 GitHub + 配 Secrets(5 分钟)git push · Settings → Secrets 加 FEISHU_WEBHOOK
6
手动触发 Action 一次(3 分钟)Actions 页 → Run workflow · 看飞书有没有收到
Day 6 · 实操

验收清单 · 你应该有的产物

  1. GitHub 有一个 competitor-monitor 仓库,含 monitor.py + requirements.txt + .github/workflows/monitor.yml
  2. 本地跑 python monitor.py 能输出 changes(首次跑 changes 为空很正常,没昨天对比项)
  3. Actions 标签页里"Daily Competitor Monitor"工作流可手动触发,跑完绿色 ✓
  4. 飞书运营群收到一条机器人消息(首次跑可能是"无变化"——OK,第二天起才有 diff)
  5. 明天 9 点(cron 触发后)你飞书会收到自动推送(如果有变化)
5 个都打勾 → 今天目标达成。明天 9 点见证奇迹。
Day 6 · 进阶

下周你能再做的 4 件事

1
加 LLM 总结changes 太多 → 让 Codex 调 GPT 把 10 条变化总结成"今日 3 个 takeaway"再推飞书
2
加截图证据每次抓时存网页截图到 GitHub Artifact · 周末用 Codex 拼 1 张"竞品价格变化时间线"
3
扩展到 10+ 竞品把 COMPETITORS list 加长 · 注意 cron 时间错开避免被 IP 封
4
反向做:被监控提醒让 Codex 监控你自己网站——价格被恶意爬 / banner 被改 → 立刻报警
💡 原则:今天搭好的是基础设施——加任何功能就是改 prompt + 改一段代码。再不用从零开始。
Day 6 · 方法论

运营做爬虫 × Codex · 3 条原则

  1. 定义"变化"比"抓取"重要 10 倍——抓数据是体力活(Codex 全包),决定"什么算有意义的变化"是脑力活(只能你来)
  2. 合规是地基不是补丁——把"遵守 robots.txt + 不爬登录"写进 prompt 里,Codex 自动遵守。事后补很麻烦
  3. 系统的价值 = 运行时长 × 信噪比——跑 1 年 + 推 100 条都是关键变化 > 跑 1 周 + 推 1000 条噪音
核心 mindset:Codex 不是替你做监控——是把"监控"变成数字员工岗位,让你把自己的注意力留给"看到变化后怎么反应"。
Day 6 · 小结

今天 3 个 takeaway

  1. 爬虫 = 抓 + 存 + diff + 推——少一环就废。Codex 一次 prompt 全包,你只描述竞品 + 字段 + 阈值
  2. GitHub Action 是免费的 24/7 服务器——cron 表达式 + Secrets + Artifact 三件套,覆盖 99% 监控场景
  3. 不要推送一切,只推变化里有意义的——通知设计比抓取技术更影响真实效果
课后作业(明天前完成):让监控跑 24 小时,明天 9 点截图飞书推送发到课程群。没收到的把日志贴出来一起排查
Day 6 · 结束
明天 · Day 7

广告素材批量生成
1 个 brief → 30 张创意

让 Codex 调 nano-banana / Midjourney API,
一份 brief → 30 张投放素材(横版/竖版/方版 × 5 种 hook)
Meta / TikTok / Google 投放包一站搞定

🙋 现在 · Q&A 时间
课后微信群答疑 · 联系讲师 Terrence
📝 讲师备注 · 按 N 切换显示 / 隐藏
翻页 · Space 下一页 · F 全屏 · N 备注 · Home 首页