📦 xclaw — 推特采集归档

v1.0.0

在浏览器中访问 X(Twitter) 时间线或用户主页,自动提取推文、互动指标、媒体链接并下载本地副本,一键生成结构化 markdown 归档。

1· 195·0 当前·0 累计
zyliu0 头像by @zyliu0 (zyliu)·MIT-0
下载技能包
License
MIT-0
最后更新
2026/4/18
0
安全扫描
VirusTotal
可疑
查看报告
OpenClaw
安全
high confidence
该技能的指令、文件写入与抓取行为与其声明用途(抓取 X/Twitter 时间线并保存媒体)一致,未请求无关凭据或安装。
评估建议
此技能看起来确实在做它声称的事:它将导航 X 页面、抓取 DOM 内容,并把情报 markdown 文件及媒体保存到 ../../intel/x/media/{timestamp}。安装或运行前请考虑:1) 若你的代理浏览器已登录 X 账号,技能可能抓取私人/首页时间线内容——如不希望如此,请退出登录或使用未认证会话。2) 技能会在执行目录上两级写文件——确认该路径可接受且不会覆盖重要文件。3) 抓取可能违反 X/Twitter 服务条款或版权,请审视法律/伦理影响。4) 若需访问受保护数据(如私信或认证 feed),需单独提供认证;技能未声明凭据。若以上可接受,则技能内部逻辑一致。...
详细分析 ▾
用途与能力
名称/描述与运行时指令一致:SKILL.md 描述对 X 页面进行 DOM 抓取,收集互动指标与媒体,并将结果保存到指定文件夹结构。未请求无关二进制文件、环境变量或安装。
指令范围
指令让代理导航浏览器、运行页面评估 JS 提取推文、创建文件夹 (../../intel/x/media/...) 并下载媒体。这对抓取器是预期的,但技能会隐式读取浏览器会话可访问的任何内容(包括已登录首页时间线及会话 Cookie),并在上两级相对路径写文件——因此若代理登录个人账号或目标页含私人数据,则存在隐私风险。
安装机制
无安装规范且无代码文件——仅指令。这降低了供应链风险,因为安装时不会下载或写入任何内容。
凭证需求
技能无需环境变量或凭据,逻辑自洽。但它假定可访问可能已认证的浏览器上下文;该对会话 Cookie 的隐式访问未声明,运行时可能暴露私人时间线数据。
持久化与权限
always 为 false,安装时无持久化。技能确实指示在代理工作区(或父目录)创建文件,但未请求提升或持久的平台权限。
安全有层次,运行前请审查代码。

License

MIT-0

可自由使用、修改和再分发,无需署名。

运行时依赖

无特殊依赖

版本

latestv1.0.02026/3/16

**重大技能重构:XClaw 现成为本地 X (Twitter) 帖子提取器,专注于抓取与归档。** - 移除所有先前的基于 API 的情报、分析与端点文档。 - 清除与原情报功能及命令集相关的所有代码与引用。 - 技能现仅提供一项主要功能:提取并归档 X 时间线/用户帖子,含互动数据与本地媒体下载。 - 提供严格的抓取情报文件输出格式,包括帖子元数据、指标及文件/文件夹命名规范。 - 更新使用说明与工作流,仅用于本地抓取与文件管理。

可疑

安装命令

点击复制
官方npx clawhub@latest install x-openclaw
镜像加速npx clawhub@latest install x-openclaw --registry https://cn.longxiaskill.com

技能文档

# XCLAW 从 X(Twitter)页面提取帖子,包含完整元数据:文本、作者、时间戳、互动指标、媒体 URL,并下载本地副本。 ## 使用场景 - 列出某用户主页的最新帖子 - 提取主页时间线帖子 - 不进入单条帖子即可抓取帖子链接 - 收集互动指标(点赞、转推、回复、浏览量) - 下载图片与视频缩略图 - 分析多条帖子的内容模式 --- ## 文件结构 `` intel/x/ ├── {date}-{time}-X.md # 情报文件 └── media/ └── {YYYYMMDD}-{HHMMSS}/ # 媒体文件夹(与情报文件同名时间戳) ├── image_{postId}_{index}.jpg └── video_{postId}_poster.jpg ` --- ## 文件命名 | 项目 | 格式 | 示例 | |------|--------|---------| | 情报文件 | {date}-{time}-X.md | 2026-03-16-143052-X.md | | 媒体文件夹 | {YYYYMMDD}-{HHMMSS} | 20260316-143052 | | 图片 | image_{postId}_{index}.jpg | image_2032741269689213289_0.jpg | | 视频缩略图 | video_{postId}_poster.jpg | video_2032741269689213289_poster.jpg | --- ## 输出格式 —— 必须严格遵循的格式 以如下精确格式写入情报文件。每个组件都必须严格遵守。 ` # X Intelligence Report Scraped: {date} {time} (Asia/Shanghai) Source: X Home Timeline Posts Collected: {count} --- ## Post {n}: {Topic Title} Author: {Name} (@{handle}) Posted: {relative time} URL: {post_url} Content: {post_text_content} Metrics: ❤️ {likes} 🔁 {reposts} 💬 {replies} 👁 {views} Media: 🖼️ media/{folder}/image_{postId}_{index}.jpg Signal: {🔴 HIGH / 🟡 MEDIUM / 🟡 LOW / ⚪ SKIP} — {Brief signal assessment} --- ## Post {n+1}: ... (更多帖子...) --- ## Summary High Signal (Tier 1): 1. {Topic} — {一句话摘要} 2. {Topic} — {一句话摘要} Medium Signal (Tier 2): - {Topic} — {一句话摘要} - {Topic} — {一句话摘要} Skip: - {Topic} — {原因} ` ### 输出格式中的媒体部分(条件) 如果帖子包含媒体,在 Metrics 后插入 Media 行: ` Media: 🖼️ media/{folder}/image_{postId}_{index}.jpg ` 视频缩略图则写: ` Media: 🎬 media/{folder}/video_{postId}_poster.jpg ` 若帖子无媒体,则完全省略 Media 部分。 --- ## 工作流 ### 步骤 1:创建媒体文件夹 在提取任何帖子前,先创建媒体文件夹: `bash # 按当前时间戳创建文件夹 # 格式:YYYYMMDD-HHMMSS mkdir -p ../../intel/x/media/{YYYYMMDD}-{HHMMSS} # 示例 mkdir -p ../../intel/x/media/20260316-143052 ` ### 步骤 2:导航至目标页面 `javascript // 主页时间线 browser.navigate({ url: "https://x.com/home" }) // 指定用户主页 browser.navigate({ url: "https://x.com/username" }) ` ### 步骤 3:滚动加载更多帖子 `javascript browser.act({ fn: "() => { for(let i=0; i<3; i++) { window.scrollBy(0, window.innerHeight); } return 'scrolled'; }", kind: "evaluate" }) ` ### 步骤 4:提取帖子及媒体链接 `javascript browser.act({ fn: "() => { const articles = document.querySelectorAll('article[data-testid=\"tweet\"]'); const posts = []; articles.forEach(article => { const url = article.querySelector('a[href=\"/status/\"]')?.href; if (!url || url.includes('/analytics') || url.includes('/photo')) return; const text = article.querySelector('[data-testid=\"tweetText\"]')?.innerText || ''; const timeEl = article.querySelector('time'); const timestamp = timeEl?.innerText || ''; const datetime = timeEl?.dateTime || ''; // Get author info const nameEl = article.querySelector('[data-testid=\"User-Name\"]'); const name = nameEl?.querySelector('span')?.innerText || ''; const handle = nameEl?.querySelector('a[href=\"/\"]')?.innerText || ''; // Get engagement metrics const metricButtons = article.querySelectorAll('button[role=\"button\"]'); let replies = '0', reposts = '0', likes = '0', views = '0'; metricButtons.forEach(btn => { const txt = btn.innerText || ''; const label = btn.getAttribute('aria-label') || ''; if (label && label.includes('Reply')) { const match = txt.match(/(\d+)/); if (match) replies = match[1]; } if (label && label.includes('Repost')) { const match = txt.match(/(\d+)/); if (match) reposts = match[1]; } if (label && label.includes('Like')) { const match = txt.match(/(\d+)/); if (match) likes = match[1]; } }); // Views are in an link (not button), e.g. 71K const viewLink = article.querySelector('a[href=\"/analytics\"]'); if (viewLink) { const v = viewLink.innerText.trim(); views = v.replace(/[^0-9KMB.]/g, '') || '0'; } // Get media URLs - images and video thumbnails const mediaUrls = []; // Image posts: pbs.twimg.com/media/ const images = article.querySelectorAll('img[src=\"pbs.twimg.com/media/\"]'); images.forEach(img => { if (img.src && !mediaUrls.includes(img.src)) { mediaUrls.push(img.src); } }); // Also check for image links in tags const imageLinks = article.querySelectorAll('a[href=\"pbs.twimg.com/media/\"]'); imageLinks.forEach(link => { if (link.href && !mediaUrls.includes(link.href)) { mediaUrls.push(link.href); } }); // Video thumbnails: pbs.twimg.com/amplify_video_thumb/ const videoThumbs = article.querySelectorAll('img[src=\"pbs.twimg.com/amplify_video_thumb/\"]'); videoThumbs.forEach(img => { if (img.src && !mediaUrls.includes(img.src)) { mediaUrls.push(img.src); } }); const postId = url.match(/\/status\/(\d+)/)?.[1] || ''; posts.push({ name, handle, text: text.substring(0, 500), timestamp, datetime, url, postId, mediaUrls, metrics: { replies, reposts, likes, views } }); }); return posts.slice(0, 10); }", kind: "evaluate" }) ` ### 步骤 5:下载媒体文件 针对每条含媒体的帖子,下载文件: `bash # 下载图片 - 将 URL 替换为实际提取到的媒体地址 curl -L -o "../../intel/x/media/{folder}/image_{postId}_{index}.jpg" "https://pbs.twimg.com/media/xxx?format=jpg&name=large" # 下载视频缩略图 curl -L -o "../../intel/x/media/{folder}/video_{postId}_poster.jpg" "https://pbs.twimg.com/amplify_video_thumb/xxx" ` 重要: - 使用 -L 参数跟随重定向 - 图片 URL 追加 &name=large 获取高分辨率 - 使用步骤 4 提取的真实地址 ### 步骤 6:写入情报文件 将 Markdown 文件写入 ../../intel/x/{date}-{time}-X.md 严格遵循上方所示输出格式。包含: - 头部:Scraped、Source、Posts Collected - 每条帖子:Author、Posted、URL、Content、Signal - 如有媒体则引用 - 末尾 Summary 部分 ### 步骤 7:关闭 Chrome 标签 `javascript browser.close() ` --- ## 关键选择器 | 元素 | 选择器 | |---------|----------| | 文章容器 | article[data-testid="tweet"] | | 帖子正文 | [data-testid=\"tweetText\"] | | 时间戳 | time | | 用户名 | [data-testid=\"User-Name\"] | | 帖子链接 | a[href=\"/status/\"] | | 浏览量链接 | a[href=\"/analytics\"] | | 互动按钮 | button[role=\"button\"] | | 图片 | img[src=\"pbs.twimg.com/media/\"] | | 视频缩略图 | img[src=\"pbs.twimg.com/amplify_video_thumb/\"] | --- ## 技巧 1. 不要点击进入单条帖子 —— 在时间线直接提取链接 2. 过滤链接 —— 排除 /analytics/photo` 地址 3. 先滚动再提取 —— X 动态加载帖子 4. 先建文件夹 —— 下载前媒体文件夹必须存在 5. curl 用 -L 参数 —— 跟随 pbs.twimg.com 的重定向 6. 追加 &name=large —— 获取原图而非缩略图 7. 务必关闭标签页 —— 任务结束时关闭标签

数据来源ClawHub ↗ · 中文优化:龙虾技能库