tamnd/threads-cli
GitHub: tamnd/threads-cli
一个无需登录或 API key 即可将 Threads 公开资料与帖子解析为结构化数据的命令行工具。
Stars: 0 | Forks: 0
# th
一个令人愉悦、可脚本化的 [Threads](https://www.threads.com) 命令行工具。
只需一个二进制文件,即可将个人资料解析为丰富的记录,流式传输其最近的帖子
和回复,拉取单个帖子的完整讨论串,并将所有内容塑造成
整洁的结构化数据,供你通过管道传输到任何地方,无需登录,无需浏览器。
```
th profile zuck
```
```
ID USERNAME NAME FOLLOWERS FOLLOWING VERIFIED BIO URL
63055343223 zuck Mark Zuckerberg 5530027 0 true Mostly superintelligence and MMA takes https://www.threads.com/@zuck
```
完整文档:[threads-cli.tamnd.com](https://threads-cli.tamnd.com)。
## 为什么需要
从 Threads 中提取数据通常意味着要使用无头浏览器、一大堆脆弱的选择器,
或者使用官方 API 及其繁琐的应用审查和 token。`th` 采取了
一种不同的路线:它读取 Threads 提供给搜索引擎的公开页面,
将服务端渲染的 payload 解析为有类型的记录,并根据你要求的
输出格式进行渲染。只需一个静态二进制文件,无需登录,无需浏览器,无需 API key。
由于它读取的是公开的爬虫接口,因此 `th` 能看到搜索引擎
看到的内容:完整的公开个人资料、帖子和回复讨论串,以及最近的帖子,
而不是全部历史记录。私密内容依然保密,并且 `th` 会
明确提示受限的边界,而不是默默地返回空内容。
## 安装
```
go install github.com/tamnd/threads-cli/cmd/th@latest
```
或者从 [发布页面](https://github.com/tamnd/threads-cli/releases) 获取预编译的二进制文件。
该二进制文件是纯 Go 编写的,没有任何运行时依赖。
从源码构建:
```
git clone https://github.com/tamnd/threads-cli
cd threads-cli
make build # produces ./bin/th
```
## 快速开始
```
th profile zuck # a profile's full record
th profile zuck --posts -n 20 # its twenty most recent posts
th post --replies # a post and its reply thread
th id # classify any Threads handle, id, or URL
```
## 它如何读取 Threads
`th` 以网页爬虫的身份进行匿名读取,无需登录,也无需 cookie。它会向
Threads 请求搜索引擎获取的相同服务端渲染页面,并解析返回的内容。
```
th whoami # reports the access mode and user agent
```
这适用于任何公开的个人资料或帖子。当目标是私密的,或者受到
登录限制时,`th` 会以退出码 `4` 退出并附带一行提示信息,以便脚本能够将其与真正的错误区分开来。
这种权衡在于深度:个人资料会暴露最近的帖子,而不是完整的历史记录,
而帖子则包含可见的回复窗口。
要针对你自己的账户进行更深入的获取,请设置 Graph API token(`THREADS_TOKEN`)或
已登录的 session(`THREADS_SESSION` 和 `THREADS_CSRF`)。这些选项默认是关闭的;
匿名爬虫是构建其他一切的基础。
## 工作原理
`th` 首先将任何 handle、id、shortcode 或 URL 解析为有类型的身份
(`th id` 会准确显示它所看到的内容),然后使用爬虫 user agent 获取匹配的个人资料或帖子
页面。该页面在其嵌入的 JSON 中包含了帖子文本、互动数据、
媒体以及一个回复窗口;`th` 仅依靠标准库将该树形结构遍历成记录。
在渲染窗口之外,只要未登出的持久化查询仍然有效,它们就会通过游标扩展遍历范围。
响应会按 URL 缓存在磁盘上,因此重新运行
命令是即时的,并且对 Threads 来说是礼貌的。
每条记录都是一个带有 JSON 标签的普通 struct,因此 `-o json` 会为你提供完整的
数据结构,而 `--fields` 可以缩小范围。不会凭空捏造任何内容:Threads 不会匿名暴露的字段将保持为空,而不是靠猜测填充。
## 命令
| 命令 | 作用 |
| --- | --- |
| `profile` | 完全解析的个人资料;`--posts` 和 `--replies` 会遍历其信息流 |
| `post` | 完整的单个帖子;`--replies` 流式传输其讨论串,`--raw` 输出原始来源 |
| `replies` | 将对某个帖子的回复作为独立的记录流式传输 |
| `feed` | 遍历某个个人资料最近的帖子(`profile --posts` 的别名) |
| `search` | 跨公开帖子的关键词搜索 |
| `id` | 对任何 Threads handle、id、shortcode 或 URL 进行分类,无需网络 |
| `db` | 从某个个人资料构建本地 SQLite 数据集,然后进行查询 |
| `whoami` | 报告 `th` 是如何访问 Threads 的 |
| `config` | 显示解析后的配置和路径 |
| `cache` | 检查并清除磁盘缓存 |
| `completion` | 生成 shell 自动补全脚本 |
| `version` | 打印版本、commit 和构建日期 |
运行 `th --help` 可查看任何命令的完整 flag 列表。
## 实用方案
将某个个人资料的最后 50 个帖子提取为 JSON Lines:
```
th profile zuck --posts -n 50 -o jsonl
```
获取某个帖子及其整个回复讨论串:
```
th post --replies -o jsonl
```
收集某个个人资料帖子中的所有媒体 URL:
```
th profile zuck --posts -n 200 --fields media_urls -o jsonl
```
将 threads.net 链接重写为其规范 id:
```
th id "https://www.threads.net/@zuck/post/ABC123" -o json
```
构建数据集:将某个个人资料的帖子抓取到 SQLite 中,然后进行查询:
```
th db build zuck --posts -n 200 --db zuck.db
th db query --db zuck.db "select username, sum(like_count) from posts group by 1"
```
## 输出格式
每个命令都通过相同的格式化程序进行渲染。使用 `-o` 选择格式,或者
让 `th` 自动选择:输出到终端时使用表格,通过管道传输时使用 JSON Lines。
```
th profile zuck --posts -o table # aligned columns for reading
th profile zuck --posts -o jsonl # one JSON object per line, for piping
th profile zuck --posts -o json # a single JSON array
th profile zuck --posts -o csv # spreadsheet friendly (tsv too)
th profile zuck --posts -o yaml # YAML documents
th profile zuck --posts -o url # just the permalink
```
使用 `--fields` 缩小列范围,或者为每一行应用模板。两者都可以通过列别名(`likes`)、
其 JSON 键(`like_count`)或其 Go 字段名(`LikeCount`)来命名字段,
因此你可以使用你记得的那个:
```
th profile zuck --posts --fields permalink,likes,replies
th profile zuck --posts --template '{{.permalink}} {{.likes}}'
```
`--raw`(用于 `post`)会原封不动地打印上游的 HTML,方便你在想要
自己解析它时使用。
## 配置
`th` 将其缓存和数据保存在标准的 XDG 路径下(默认为
`~/.cache/th` 和 `~/.local/share/th`;可以通过设置 `XDG_CACHE_HOME` 和 `XDG_DATA_HOME` 来
移动它们)。随时查看解析后的路径和设置:
```
th config show
th config path
```
有用的全局 flag(都有合理的默认值):
| Flag | 含义 |
| --- | --- |
| `-o, --output` | 输出格式(默认自动) |
| `-n, --limit` | 最大记录数(`0` 表示无限制) |
| `--delay` | 请求之间的最小延迟,以保持礼貌(默认 1s) |
| `--retries` | 在遇到 429/5xx 时的重试次数 |
| `--no-cache` | 绕过磁盘缓存 |
| `--token` | 官方 Graph API token(或 `THREADS_TOKEN`) |
| `--session` / `--csrf` | 已登录的 session(或 `THREADS_SESSION` / `THREADS_CSRF`) |
## 退出码
| 代码 | 含义 |
| --- | --- |
| `0` | 成功 |
| `1` | 常规错误 |
| `2` | 使用错误 |
| `3` | 未找到或不可用的内容 |
| `4` | 登录限制:内容不公开 |
| `5` | 被限速 |
| `6` | 网络错误 |
## 开发
```
make test # run the test suite
make vet # go vet
make build # build ./bin/th
make smoke # run every command and assert it works or walls cleanly
```
代码是分层的。`cli/` 是建立在 Cobra 之上的命令树。`threads/` 是
它所依赖的库:HTTP 客户端、缓存、服务端渲染页面
解析器、未登出的 GraphQL 查询以及 SQLite 存储。`pkg/thid/` 是一个
独立的 handle/id/shortcode/URL 分类器,没有其他依赖项,
可以单独导入使用。
## 许可证
Apache-2.0。请参见 [LICENSE](LICENSE)。
标签:BeEF, EVTX分析, Go, Ruby工具, Threads, Web解析, 命令控制, 数据采集, 日志审计, 爬虫