X(Twitter)发推技能。使用 Playwright 连接用户已登录的 Chrome 浏览器,自动填写并发送推文。适用场景:用户说“发推”“发一条推”“发推文”“发推特”“帮我发一条关于XX的推”“发一条推文,内容是…”。核心能力:连接已登录的 Chrome,自动填写并发送推文。
X/Twitter 发推 Skill是一项面向实际任务的技能,主要用于从头讲起:为什么这个方法能成功;背景:X 的反爬虫机制;
行为检测 :异常的浏览器行为模式;关键发现:复用用户真实浏览器;核心思路 :不启动新的自动化浏览器。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。该技能适合用于一次性任务,也可以接入自动化工作流,与其他技能或上层代理配合完成更完整的业务链路;在组合使用时,应明确每一步的输入输出关系,并避免不同步骤之间出现参数冲突。
X (Twitter) 会检测自动化浏览器,主要通过:
核心思路:不启动新的自动化浏览器,而是连接用户已经登录的真实 Chrome 浏览器。
优势:
开放的 CDP 端口允许技能:
post_tweet.js(或让信任的人帮忙)npm install 在隔离环境而非全局安装--remote-debugging-port| 变量 | 说明 | 敏感度 |
|---|---|---|
CDP_URL |
本地调试端口,如 http://127.0.0.1:28800 |
⚠️ 本地端点,勿泄露 |
X_USERNAME |
X 用户名 | 低(公开信息) |
用户启动 Chrome (开启 CDP) → Playwright 连接 → 以用户身份发帖
用户需要打开一个开启了调试端口的 Chrome。这是一次性操作,之后都保持运行。
Mac:
open -a "Google Chrome" --args --remote-debugging-port=28800
Windows/Linux:
chrome.exe --remote-debugging-port=28800
验证方法:
curl http://localhost:28800/json/version
如果返回 JSON,说明 Chrome 已经在监听。
const { chromium } = require('playwright');
(async () => {
// 连接用户已有的 Chrome(CDP 模式)
const browser = await chromium.connectOverCDP('http://127.0.0.1:28800');
// 获取已有页面(继承登录状态!)
const page = browser.contexts()[0].pages()[0];
// 验证
console.log('当前页面:', page.url());
// 发推...
})();
| 方法 | 问题 |
|---|---|
page.fill() |
直接设置 DOM 值,不触发 React onChange 事件 |
page.click('button') |
按钮初始是 disabled,React 状态未更新 |
page.evaluate(() => btn.click()) |
URL 跳转了但推文没发出 |
// 1. 打开发帖页面
await page.goto('https://x.com/compose/post');
await page.waitForTimeout(3000);
// 2. 点击输入框(获得焦点)
await page.click('[data-testid="tweetTextarea_0"]');
await page.waitForTimeout(500);
// 3. 用键盘输入(触发 React 状态更新!)
await page.keyboard.type('这是推文内容 #Web3', { delay: 30 });
// 4. 用 Meta+Enter 发送(不能用 click!)
await page.keyboard.press('Meta+Enter');
// 5. 等待跳转
await page.waitForTimeout(3000);
| 平台 | 快捷键 |
|---|---|
| Mac | Meta+Enter |
| Windows/Linux | Control+Enter |
脚本会自动检测平台并使用正确快捷键。
keyboard.type() 触发完整事件链:
Meta+Enter 触发发送:
Meta+Enter (Mac) / Ctrl+Enter (Windows/Linux)// 不要检查首页!推文排序可能不是按时间
// 直接去用户主页确认
await page.goto('https://x.com/你的用户名');
const tweets = await page.evaluate(() => {
const items = document.querySelectorAll('[data-testid="tweet"]');
return Array.from(items).slice(0, 5).map(t => ({
text: t.innerText.substring(0, 100)
}));
});
console.log('最新推文:', tweets);
用户名通过函数参数传入,默认为 woaijug:
postTweet(content, 'your_username');
或通过环境变量:
export X_USERNAME=your_username node post_tweet.js "我的推文内容"
const { chromium } = require('playwright');
const CONFIG = {
CDP_URL: process.env.CDP_URL || 'http://127.0.0.1:28800',
USERNAME: process.env.X_USERNAME || 'woaijug'
};
async function postTweet(content, username = CONFIG.USERNAME) {
console.log('🚀 开始发推...');
// 检测平台,使用正确的发送快捷键
const isMac = process.platform === 'darwin';
const sendKey = isMac ? 'Meta+Enter' : 'Control+Enter';
console.log(' Platform:', process.platform, '→ Send key:', sendKey);
try {
// 1. 连接 Chrome
const browser = await chromium.connectOverCDP(CONFIG.CDP_URL);
const page = browser.contexts()[0].pages()[0];
console.log('✓ 已连接,当前页面:', page.url());
// 2. 打开发帖页面
await page.goto('https://x.com/compose/post');
await page.waitForTimeout(3000);
console.log('✓ 已打开发帖页面');
// 3. 点击输入框
await page.click('[data-testid="tweetTextarea_0"]');
await page.waitForTimeout(500);
// 4. 用键盘输入内容
await page.keyboard.type(content, { delay: 30 });
console.log('✓ 已填写内容');
// 5. 发送(自动适配 Mac/Windows/Linux)
await page.keyboard.press(sendKey);
console.log('✓ 已发送');
// 6. 等待跳转
await page.waitForTimeout(3000);
// 7. 验证结果
const finalUrl = page.url();
const success = finalUrl.includes('/home') || finalUrl.includes('/' + username);
await browser.close();
return {
success,
message: success ? '推文发送成功!' : '发送状态未知',
url: finalUrl
};
} catch (error) {
return { success: false, message: error.message };
}
}
// 命令行调用
if (require.main === module) {
const username = process.env.X_USERNAME || 'woaijug';
const content = process.argv[2] || '默认推文内容';
postTweet(content, username).then(r => console.log('结果:', r));
}
module.exports = { postTweet };
错误:Error: connect ECONNREFUSED 127.0.0.1:28800
解决:用户需要先启动 Chrome:
# Mac open -a "Google Chrome" --args --remote-debugging-port=28800 # Windows chrome.exe --remote-debugging-port=28800
检查:
page.url() 应该是发帖页keyboard.type() 后加 waitForTimeout尝试:
await page.waitForTimeout(2000); // 等待 React 更新
解决:去用户主页查看,不要只看首页
await page.goto(`https://x.com/${USERNAME}`);
npm install)| 项目 | 说明 |
|---|---|
| 连接方式 | chromium.connectOverCDP() |
| 发送方法 | keyboard.type() + keyboard.press('Meta+Enter') |
| 验证方式 | 去用户主页 x.com/username,不是首页 |
| 端口 | 默认 28800,可在 CONFIG 中修改 |
相关专题
热门下载
相关下载
精品课程
共32课时 | 10.6万人学习
共23课时 | 7.7万人学习
共26课时 | 10.9万人学习