| name | twitter-harvest |
| description | 用 Chrome 浏览器持续刷 Twitter,AI 评估筛选有价值内容和精彩评论,写入每日笔记 |
| argument-hint | [可选:rounds=N | topic=AI,crypto] |
| allowed-tools | Bash, Read, Write, Edit, Glob, Grep, ToolSearch, mcp__chrome-devtools__evaluate_script, mcp__chrome-devtools__navigate_page, mcp__chrome-devtools__take_screenshot, mcp__chrome-devtools__take_snapshot, mcp__chrome-devtools__click, mcp__chrome-devtools__press_key, mcp__chrome-devtools__list_pages, mcp__chrome-devtools__select_page |
| user-invocable | true |
Twitter 持续采集 Skill
概述
模拟用户真实刷 Twitter 体验:多数据源轮换采集 → 滚动阅读 → AI 两级筛选(高门槛,每轮最多 5 条)→ 看热门评论 → 写入笔记 → 继续刷下一波。全部轮次结束后生成「今日 Top 10 精选」。核心目标:捕捉极强信息差(新工具、新趋势、独家观点),而非堆量。
前置条件
- Chrome 已通过 CDP 模式启动(端口 9222),已登录 Twitter/X
- 启动脚本:skill 目录下
scripts/launch-chrome-cdp.sh
工作流
1. 参数解析
rounds=N → 刷 N 轮(默认 8 轮,即约 240 条推文)
topic=关键词1,关键词2 → 只关注这些话题
2. 浏览器准备
重要:使用 mcp__chrome-devtools__* 工具前,必须先用 ToolSearch 加载。
- 用
ToolSearch 加载所需的 chrome-devtools 工具(evaluate_script, navigate_page, take_screenshot, click, list_pages, select_page, new_page)
- 调用
list_pages 确认 Chrome 已连接
- 使用专属 tab(避免与其他 harvest skill 冲突):
- 在
list_pages 结果中查找 URL 包含 x.com 或 twitter.com 的已有 tab
- 如果找到 →
select_page 选中该 tab
- 如果没找到 →
new_page 创建新 tab,URL 为 https://x.com/home
- 全程只在此 tab 内操作,导航到推文详情页后用浏览器后退或重新导航回数据源,不切换到其他 tab
- 用
evaluate_script 确认 timeline 已加载,如果是登录页则告知用户并终止
3. 多源轮换策略
核心思想:不同数据源提供完全不同的内容,轮换使用避免重复。
每轮按以下策略选择数据源:
| 轮次 | 数据源 | 导航目标 | 说明 |
|---|
| 1-2 | For You 算法推荐 | x.com/home (默认 tab) | 算法推荐,覆盖面广 |
| 3-4 | Following 时间线 | x.com/home → 点击 "Following" tab | 纯关注者内容,按时间排序 |
| 5 | 💰 赚钱信息差搜索 | x.com/search?q=关键词&f=top | indie hacker / SaaS / ARR / launched / vibe coding |
| 6 | 💰 Crypto & 市场信号 | x.com/search?q=关键词&f=top | BTC / alpha / DeFi / airdrop / 宏观经济信号 |
| 7 | 关键词搜索(技术) | x.com/search?q=关键词&f=live | Claude / MCP / Agent / 开源工具 |
| 8 | 大牛主页深挖 | 直接访问大牛 profile 的 Replies tab | 发现他们参与的讨论串 |
3.0 切换数据源
For You → Following 切换:
(() => {
const tabs = document.querySelectorAll('[role="tab"]');
for (const tab of tabs) {
if (tab.textContent.includes('Following')) {
tab.click();
return 'switched to Following';
}
}
return 'Following tab not found';
})()
关键词搜索:
- 导航到
https://x.com/search?q=关键词&f=live
- 时间限制:搜索词中必须加
since:YYYY-MM-DD(当天日期),避免拉到旧内容和前几天重复的推文
- 例:
Claude Code since:2026-03-04
- 如果
f=live + since:今天 结果太少(< 5 条),可放宽到 since:昨天
- 绝对不用
f=top 不带时间限制——这会拉到一周甚至更久前的推文,导致大量重复
- 搜索关键词从默认列表中轮换选取 2-3 个组合
- 搜索关键词组合示例:
- 第 5 轮(赚钱信息差):
("indie hacker" OR "solo founder" OR "$1M" OR ARR OR MRR OR "vibe coding" OR "launched" OR "built with") since:YYYY-MM-DD min_faves:50
- 第 6 轮(Crypto/市场):
(BTC OR crypto OR Solana OR airdrop OR DeFi OR alpha) (buy OR sell OR signal OR opportunity) since:YYYY-MM-DD min_faves:100
- 第 7 轮(技术):
(Claude Code OR MCP OR Agent OR "open source") since:YYYY-MM-DD
- 可根据
topic= 参数自定义
- 使用
min_faves:N 过滤低质量内容
Explore 热门:
- 导航到
https://x.com/explore/tabs/technology(如果不存在则用 x.com/explore)
- 浏览热门话题和推文
大牛主页深挖:
- 从本次已采集的高质量推文中挑 3-5 个活跃作者
- 访问
x.com/{handle} 浏览其最新推文和 Replies tab
- 这能发现 timeline 推不到的高质量讨论
4. 持续刷推循环
对每一轮(round)重复:
4.1 滚动采集本轮推文(约 30 条)
重复滚动提取:
- 用
evaluate_script 执行 JS 提取当前可见推文:
(() => {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
const tweets = [];
for (const article of articles) {
try {
const userLinks = article.querySelectorAll('a[role="link"]');
let author = '', handle = '';
for (const link of userLinks) {
const href = link.getAttribute('href') || '';
if (href.match(/^\/[^/]+$/) && !href.startsWith('/i/') && !href.startsWith('/search')) {
handle = href.replace('/', '');
const nameSpan = link.querySelector('span');
if (nameSpan) author = nameSpan.textContent || '';
break;
}
}
const textEl = article.querySelector('[data-testid="tweetText"]');
const text = textEl ? textEl.textContent : '';
if (!text) continue;
const timeEl = article.querySelector('time');
const timeParent = timeEl ? timeEl.closest('a') : null;
const tweetUrl = timeParent ? 'https://x.com' + timeParent.getAttribute('href') : '';
const timestamp = timeEl ? timeEl.getAttribute('datetime') : '';
const getMetric = (testId) => {
const el = article.querySelector(`[data-testid="${testId}"]`);
if (!el) return 0;
const txt = el.textContent.replace(/,/g, '').trim();
if (!txt) return 0;
if (txt.endsWith('K')) return Math.round(parseFloat(txt) * 1000);
if (txt.endsWith('M')) return Math.round(parseFloat(txt) * 1000000);
return parseInt(txt) || 0;
};
const hasMedia = article.querySelector('[data-testid="tweetPhoto"], video') !== null;
tweets.push({ author, handle, text: text.substring(0, 300), url: tweetUrl, timestamp, likes: getMetric('like'), retweets: getMetric('retweet'), replies: getMetric('reply'), has_media: hasMedia });
} catch (e) {}
}
return JSON.stringify(tweets);
})()
- 用
evaluate_script 滚动:() => { window.scrollBy(0, 5000); return 'scrolled'; }
- 再次提取
- 按 url 去重(跨轮次全局去重,同一条推文不会重复处理)
- 本轮采集约 30 条新推文后停止滚动(或连续 3 次无新推文)
4.2 对本轮高互动推文抓取精彩评论
挑选本轮 likes 最高的 2-3 条推文(likes >= 100),逐一点进去:
navigate_page 到推文 URL
- 滚动一下让评论加载,用
evaluate_script 提取评论(跳过第一个 article 即原推):
(() => {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
const replies = [];
let isFirst = true;
for (const article of articles) {
if (isFirst) { isFirst = false; continue; }
try {
const userLinks = article.querySelectorAll('a[role="link"]');
let author = '', handle = '';
for (const link of userLinks) {
const href = link.getAttribute('href') || '';
if (href.match(/^\/[^/]+$/) && !href.startsWith('/i/') && !href.startsWith('/search')) {
handle = href.replace('/', '');
const nameSpan = link.querySelector('span');
if (nameSpan) author = nameSpan.textContent || '';
break;
}
}
const textEl = article.querySelector('[data-testid="tweetText"]');
const text = textEl ? textEl.textContent : '';
if (!text) continue;
const getMetric = (testId) => {
const el = article.querySelector(`[data-testid="${testId}"]`);
if (!el) return 0;
const txt = el.textContent.replace(/,/g, '').trim();
if (!txt) return 0;
if (txt.endsWith('K')) return Math.round(parseFloat(txt) * 1000);
if (txt.endsWith('M')) return Math.round(parseFloat(txt) * 1000000);
return parseInt(txt) || 0;
};
replies.push({ author, handle, text: text.substring(0, 200), likes: getMetric('like') });
} catch (e) {}
}
return JSON.stringify(replies);
})()
- 保留 likes >= 10 的评论,每条最多 3 条
- 回到当前数据源继续
4.3 AI 评估本轮推文(两级筛选)
对本轮采集的推文做 AI 评估,采用两级筛选控制信息量:
第零级 — 排除条件(命中任一直接丢弃):
- 🚫 虚假/误导信息:
- 无可靠来源的「BREAKING」:只有全大写标题、没有链接到权威媒体(WSJ/NYT/Reuters/Bloomberg/AP)原文的突发新闻
- 未经证实的战争/灾难细节:声称具体伤亡数字、军事行动细节但无官方或权威媒体引用
- 明显的情绪操纵:全大写 + 大量 emoji + 「you have NO IDEA」式夸张措辞,实际无增量信息
- Crypto 喊单/Pump:「100x」「SEND IT」「早期机会」等推广特定代币,尤其附带合约地址(CA:)的
- 阴谋论:UFO、深层政府、「被操纵」等无证据的叙事
- Engagement bait:「Follow me + RT + Comment "XXX"」式套路推文,内容空洞仅为涨粉
- AI 生成的低质新闻聚合:多个账号发布措辞几乎相同的「BREAKING」推文,明显是机器人网络
- 🚫 来源可信度检查:
- 优先信任:权威媒体、知名创始人/投资人、有 verified badge 的行业专家、已被关注的大牛
- 保持怀疑:匿名账号的独家爆料、粉丝量极低但声称有内幕的新账号、纯转述无原始来源的信息
- 交叉验证:重大新闻(战争、市场崩盘、公司收购)如果只有一个来源,在锐评中标注「⚠️ 待验证」而非直接当事实引用
第一级 — 必要条件(至少满足一个):
- 🔥 赚钱信息差(最高优先级):能直接帮用户赚钱或省钱的信息,包括但不限于:
- 新工具/产品发布(可以用来构建产品或提效的)
- 独立开发者的收入数据、增长策略、商业模式拆解
- 市场信号:宏观经济、关税、利率、监管变化对投资的影响
- Crypto/DeFi alpha:链上数据、做市商策略、套利机会、空投信息
- 创业机会:未被满足的需求、新赛道信号、YC/融资趋势
- AI 变现实例:谁用 AI 做了什么产品、赚了多少钱、怎么做的
- 免费资源/API/program:能降低创业成本的免费工具和加速器
- 即使 likes 较低(>= 50)也优先入选
- 极强信息差:新趋势信号、独家观点、圈内人爆料(即使 likes 较低也入选)
- 高互动:likes >= 200 或 retweets >= 50
- 话题高度相关 + likes >= 50(仅关键词匹配不够,还需一定互动)
- 有精彩评论:likes >= 10 的回复 2 条以上
第二级 — 每轮硬上限:
- 从通过第一级的推文中选 top 5(赚钱信息差优先,再按 likes 降序)
- 8 轮总量控制在 30-40 条
- 用
!! 标记 outstanding 推文(likes >= 1K 或 retweets >= 200)
- 含赚钱信息差的轮次标题加 💰 标记:
### Twitter #N (HH:MM) 💰 赚钱信息差
默认关注话题关键词:
AI, LLM, GPT, Claude, Agent, MCP, RAG, Cursor, 大模型,
Rust, Go, TypeScript, Python, Vim, Neovim,
Web3, crypto, BTC, ETH, Solana, DeFi, airdrop,
startup, 创业, 独立开发, indie hacker, SaaS, ARR, MRR,
vibe coding, side hustle, passive income, monetize,
productivity, 效率, workflow, Obsidian
用户 topic= 指定时替换默认列表。
总结原则:
- 每条推文压缩为 1-2 句核心观点,突出信息差而非描述事实
- 中文推文中文总结,英文推文用中文总结
- 保留原始链接
[->](url)
- 互动数据格式统一为
(1.2K likes, 311 rt),省略 retweet 低于 10 的 rt 部分
- 含图片标
[img],含视频标 [video]
!! 标记 outstanding 推文(likes >= 1K 或 retweets >= 200)
- 有精彩评论的在推文下方缩进展示
锐评(💬):
- 每条入选推文附一句锐评,缩进写在推文下方
- 锐评要有观点、有态度、有洞察,不要复述推文内容
- 好的锐评:指出隐含趋势、点破本质、做横向对比、给出可操作建议
- 赚钱信息差推文的锐评特别要求:必须包含可执行的 insight,比如「合法版本 = XX SaaS」「如果你在做 XX,这个 program 要第一时间申请」「对冲策略:XX」
- 坏的锐评:重复推文说了什么、泛泛而谈"值得关注"
4.4 Follow 大牛
如果发现质量极高的个人账号(非公司/媒体),检查是否已 follow:
(() => {
const btn = document.querySelector('[data-testid$="-follow"]');
if (btn) return 'not_following';
const ubtn = document.querySelector('[data-testid$="-unfollow"]');
if (ubtn) return 'already_following';
return 'unknown';
})()
如果未 follow 且符合大牛标准(持续高质量原创内容、有影响力),则点击 follow。
4.5 去重并写入 Daily Note
Read 今日 daily note,检查已有推文 URL 避免重复
- 如果有新的有价值内容,
Edit 追加到 ## 记录 section(## 复盘 之前)
Daily note 路径:归档/daily note/年/月/YYYY-MM-DD.md
不存在则创建:
---
date: YYYY-MM-DD
tags: [daily]
---
# YYYY-MM-DD
## 今日待办
- [ ]
## 记录
## 复盘
每轮写入格式(平铺列表,每轮 3-5 条,不需要分类标题):
### Twitter #N (HH:MM)
- **@author**: 核心观点一句话 [->](url) (1.2K likes, 311 rt) !! [img]
- 💬 锐评:有态度的一句话点评
- **@commenter**: 精彩评论 (56 likes)
- **@author**: 核心观点 [->](url) (350 likes)
- 💬 锐评
- **@author**: 核心观点 [->](url) (200 likes)
- 💬 锐评
> 本轮采集 N 条,筛选 M 条 | 数据源:For You / Following / 搜索"关键词" / Explore / @handle 主页
格式细节:
- 标题与列表之间空一行,列表项之间不空行
- 锐评紧跟推文,精彩评论紧跟锐评
- 每轮末尾用
> blockquote 写统计,与列表之间空一行
- 当某轮有 5 条以上通过第一级筛选且话题跨度大时,可用
**分类名** 加粗行分组(不用 ####)
4.6 进入下一轮
- 打印 "第 X 轮完成,继续刷..."
- 按多源轮换策略切换到下一个数据源
- 重复 4.1 → 4.5
5. 生成「今日 Twitter 精选」
全部轮次完成后,回顾所有已写入的推文,生成精选摘要插入到所有 ### Twitter #N 之前:
### 🐦 今日 Twitter 精选 (Top 10)
> 从 N 轮采集中精选最值得关注的 10 条
1. **@author**: 一句话核心观点 [->](url) ⭐
2. **@author**: 一句话核心观点 [->](url) ⭐
3. **@author**: 一句话核心观点 [->](url) ⭐
4. **@author**: 一句话核心观点 [->](url)
...
10. **@author**: 一句话核心观点 [->](url)
选取标准(按优先级):
- 极强信息差:新工具发布、新趋势信号、独家观点、圈内人爆料
- likes/retweets 最高的头部推文
- 话题多样性(不全是同一类)
格式:每条仅一句话 + 链接,不附评论、不标数据,极简扫描。⭐ 标记信息差最强的前 3 条。
Top 10 与后续各轮之间用 --- 分隔线隔开。
6. 终止条件
- 已完成指定轮数(默认 8 轮)
- 连续 2 轮筛选出 0 条有价值内容(timeline 质量下降)
- 浏览器连接丢失
完成后输出总结:共刷 X 轮,采集 Y 条推文,筛选 Z 条写入 daily note,follow N 位大牛。
注意事项
- 分类是动态的,根据实际内容决定,空分类跳过
- 每轮的 #N 递增(读取 daily note 中已有的最大 N 值 + 1)
- 跨轮次全局去重(用 URL set 追踪已处理推文)
- 跨数据源也要去重(搜索结果可能和 timeline 重复)
- 跨日去重:开始采集前,读取前一天的 daily note 提取所有推文 URL 加入去重集合,避免和昨天重复
- 推文含图片/视频标注 [img] / [video]
- 采集完不关闭标签页
- 自动模式(
claude -p):全程无需用户交互
排版规范(写入 Daily Note 时严格遵守)
一致性:
- 链接格式统一用
[->](url),不用 [→] 或其他变体
- 互动数据统一用
(1.2K likes, 311 rt) 格式,K/M 缩写,低于 1000 写原数
- 媒体标记统一用
[img] [video],不用 emoji 📷
- Outstanding 标记统一用
!!,不用 🔥
层次感:
### Twitter #N (HH:MM) 作为每轮标题
- 推文条目用
- 无序列表
- 锐评用
- 💬 缩进在推文下方
- 精彩评论用
- **@handle**: 内容 缩进
- 统计信息用
> blockquote
- Top 10 精选与各轮之间用
--- 分隔
简洁性:
- 每条推文总结不超过 2 句话
- 锐评限 1 句话,要有信息增量
- 不重复推文已说的内容
- retweet 低于 10 时省略 rt 部分