npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ants-move

v0.0.7

Published

An open-source CLI for collecting and moving data between systems.

Readme

ants-move

Language / 语言: English · 简体中文

ants-move 是一个开源 TypeScript CLI,用于在系统之间搬运数据。命令被设计成小型 worker:采集器把数据拿进来,自动化命令可以把数据写入创作者后台等系统。当前采集器支持 36 氪、今日头条、闲鱼(goofish)、Hacker News、GitHub,以及主流科技 / AI 媒体(WIRED、MIT Technology Review、TechCrunch、The Verge、Ars Technica、Engadget、IEEE Spectrum、BBC Technology、Google AI / DeepMind / NVIDIA / OpenAI 博客、Bloomberg 标题流)。头条还支持创作者后台登录,以及文章 / 微头条的草稿与发布。闲鱼搜索需要已登录的浏览器会话。

安装与环境

依赖:

  • Node.js 22 或更高
  • npm
  • PATH 中可用的 curl(36 氪与科技 / AI 媒体采集)
  • 通过 Playwright 安装的 Chromium(头条采集)

全局安装包,并安装头条采集用的浏览器:

npm install -g ants-move
npx [email protected] install chromium

包会安装两个等价可执行文件:ants 与短别名 amv

输出约定

成功结果写 stdout,结构化错误写 stderr。默认输出 JSON。列表 / 搜索命令支持 --format table-t 表格输出。文章详情命令仅支持 JSON。

成功 JSON 信封:{ "ok": true, "data": ... }。错误信封:{ "ok": false, "error": ... },并以非零退出码返回。

36 氪命令

按数字 ID 拉取文章:

ants 36kr article <article-id> [--format json]

AItechnology 频道拉取 1~20 页资讯:

ants 36kr list <AI|technology> [--pages 1..20] [--format json|table] [-t]

采集方式:

  • 文章:从 www.36kr.com 拉 HTML(不用裸域 36kr.com)并解析 window.initialState。裸域常被火山引擎安全检测页拦截且没有正文数据;遇到时返回 KR36_PARSE_ERROR 并提示安全检测。
  • 列表:只走官方 gateway 流式接口(gateway.36kr.com,首页 pageEvent: 0,后续页带 pageCallback),不再依赖频道页 HTML。

分页串行,单次调用最多 20 页。每个 curl 响应与映射结果限制 20 MB,每页最多 30 条,映射列表限制 5 MB,因此一次列表最多保留 600 条,且不会跨页累积过大字段。

闲鱼(goofish)命令

这些命令使用从 www.goofish.com 逆向的非官方 MTOP 搜索接口不是闲鱼开放平台官方 API。账号限流、登录验证与风控仍然有效。请用个人/测试账号,保持低频,不要接到高 QPS 路径。CLI 不会绕过验证码或风控。

登录

登录仍用有界面浏览器扫码(一次性)。会话以 Playwright storageState 保存(权限 0600),默认路径 ~/.config/ants-move/xianyu/default.json,可用 --state 覆盖。纯 API 搜索复用该文件中的 Cookie(尤其 _m_h5_tk)。

ants xianyu auth login [--browser chrome|msedge|chromium] [--state <path>] [--timeout-ms <ms>]
ants xianyu auth status [--browser chrome|msedge|chromium] [--state <path>] [--headed]
ants xianyu auth logout [--state <path>]

搜索

搜索需要已保存的登录态。默认传输为纯 API--transport api):用 _m_h5_tk 计算 H5 MTOP sign,HTTP POST mtop.taobao.idlemtopsearch.pc.search。可用 --transport browser 回退到 Playwright 页面拦截。默认 JSON;--format table-t 输出表格。

ants xianyu search <keyword> \
  [--pages 1..5] \
  [--transport api|browser] \
  [--sort default|price_asc|price_desc|newest|oldest|distance|credit] \
  [--brand <名称>] [--brand-vid <vid>] \
  [--min-price <n>] [--max-price <n>] \
  [--publish-days 1|3|7|14] \
  [--quick-filter personal,free_postage,new,appraise,...] \
  [--personal] [--free-postage] [--new] [--appraise] \
  [--province <省>] [--city <市>] [--area <区>] \
  [--exclude-multi-places] \
  [--lat <n> --lng <n> --distance <米>] \
  [--format json|table] [-t] \
  [--browser chrome|msedge|chromium] \
  [--state <path>] \
  [--headed]

示例:

ants xianyu auth login
ants xianyu search 单反 --pages 1
ants xianyu search 单反 --brand 佳能
ants xianyu search 单反 --brand Canon --min-price 500 --max-price 2000 --sort price_asc --personal
ants xianyu search 单反 --province 广东 --city 深圳 --publish-days 7 -t
ants xianyu search 单反 --transport browser --headed

实现要点:

  • api(默认):从 storageState 读 Cookie,按 md5(token&t&appKey&data) 签名后 POST h5api.m.goofish.com,映射 resultList。搜索本身不启动浏览器。
  • browser:在已登录会话中打开搜索页,用 Playwright 捕获同一 MTOP 响应。高级筛选始终走 MTOP body(API 字段),即使指定了 --transport browser
  • PC 高级筛选(逆向 MTOP 字段):
    • 排序 → sortField / sortValue
    • 价格 / 发布时间 / 快捷筛选 → propValueStr.searchFilter,例如 priceRange:500,2000;publishDays:7;quickFilter:filterPersonal;
    • 地区 → extraFilterValuedivisionList(可选排除多地卖家)
    • 距离 → gps / customGps / customDistance(米)
    • 任意筛选时 fromFilter: true
    • 快捷筛选对应 UI:个人闲置、包邮、全新、验货宝、超赞鱼小铺、严选、转卖、验号担保
  • 映射字段:itemIdtitleprice / priceNumber,可选 area / picUrl / userNick,以及商品链接。meta.transport 标明路径。
  • 分页最多 5 页;结果 ≤ 5 MB;同 state 单飞锁;token 轮换最多再试 1 次。
  • 品牌(--brand / --brand-vid:一条命令内部两次 MTOP——(1) 从 cpvNavigatorDo 解析品牌 facet 并解析名称→pid/vid,(2) 搜索时写入 searchFilterpid:vid;。结果 meta.brand 回传解析结果;名称不存在返回 XIANYU_BRAND_NOT_FOUND 并列出可选品牌。
  • 仍未单独做 CLI 的:成色/功能状态等其它 CPV tab(机制相同,可后续复用)。

头条命令与验证限制

按数字 ID 或文章 / group / 旧版 URL 拉取文章:

ants toutiao article <article-id-or-url> [--format json]

从科技频道或支持的搜索关键词拉取 1~5 页:

ants toutiao list <tech|AI|光刻机|芯片|半导体> [--pages 1..5] [--format json|table] [-t]

按 token 或 /c/user/token/<token>/ 主页 URL 拉取作者动态:

ants toutiao author <token-or-url> [--pages 1..5] [--with-content] [--format json|table] [-t]

Feed 采集最多保持请求页数的解析结果活跃,最多启动两倍数量的有界解析尝试以替换畸形响应,并最多接受 5 个成功响应。每个 feed body 在 JSON 解析前限制 5 MB,解析后最多 100 条原始条目。

文章抽取对标题、正文、段落分别限制 1 MB。搜索回退最多串行检查 300 个有界链接,并拒绝大于 1 MB 的 body。--with-content 在同一浏览器会话中串行拉详情,最多 100 篇唯一文章,单次调用最多保留 10 MB 结果。头条可能要求交互式验证;验证导致搜索不可用时返回 TOUTIAO_VERIFICATION_REQUIRED。CLI 不会尝试绕过站点验证。

头条创作者登录与发布

这些命令用 Playwright 驱动非官方创作者后台 mp.toutiao.com不是官方头条开放 API。账号限流、验证码、风控策略仍然有效。请先用测试账号。CLI 永不绕过验证码或风控。

首次用有界面浏览器扫码登录。会话以 Playwright storageState 保存(权限 0600),默认路径 ~/.config/ants-move/toutiao/default.json,可用 --state 覆盖。

登录 / 发布默认使用本机已安装系统浏览器--browser chrome),而不是 Playwright 自带的 Chromium for Testing。支持:

  • chrome(默认):本机 Google Chrome
  • msedge:Microsoft Edge
  • chromium:Playwright 管理的 Chromium for Testing

也可设置 ANTS_TOUTIAO_BROWSER=chrome|msedge|chromium

ants toutiao auth login [--browser chrome|msedge|chromium] [--state <path>] [--timeout-ms <ms>]
ants toutiao auth status [--browser chrome|msedge|chromium] [--state <path>]
ants toutiao auth logout [--state <path>]

创建内容默认存草稿。正式发布必须显式 --strategy publish。省略 --strategy 永远等于 draft。--dry-run 只校验入参与登录态是否存在,不写后台:

ants toutiao publish article \
  --title <title> \
  --content <text> | --content-file <path> \
  --images <path,path,path,...> \
  [--cover <path>] \
  [--covers <path,path,...>] \
  [--keywords <csv>] \
  [--category <name>] \
  [--location <名称>] \
  [--claim <name>] \
  [--first-publish] \
  [--strategy draft|publish] \
  [--browser chrome|msedge|chromium] \
  [--cdp <url>] \
  [--state <path>] \
  [--dry-run] \
  [--headed]

ants toutiao publish micro \
  --content <text> | --content-file <path> \
  --images <path,path,...> \
  [--topic <name>] \
  [--location <名称>] \
  [--claim <name>] \
  [--first-publish] \
  [--strategy draft|publish] \
  [--browser chrome|msedge|chromium] \
  [--cdp <url>] \
  [--state <path>] \
  [--dry-run] \
  [--headed]

文章图片规则

  • --images 必填,至少 3 张本地图(最多 20)。
  • 图片会嵌在正文段落之间,不只是封面。
  • 主路径:把图片写入系统剪贴板,再在折叠到文末、无选区的光标处粘贴,避免覆盖已有文字。
  • 每次插入后校验此前段落指纹仍在;若粘贴会覆盖正文,命令以 TOUTIAO_UI_CHANGED 失败。
  • 兜底路径:创作者后台工具栏插图抽屉 → 本地上传 → 确定。
  • 封面 / 主图(--cover / --covers):可选。未指定时用第一张正文图作单图。封面上传为尽力而为;封面控件失败时仍可保存带正文图的草稿,并可能回退到「无封面」。

微头条图片规则

  • --images 必填,至少 2 张本地图(最多 9)。
  • 通过微头条工具栏「图片」→「本地上传」→「确定」上传。

其他发布选项

| 选项 | 对应后台控件 | |------|----------------| | --topic <name> | 微头条创作话题(工具栏或 #话题# 文本兜底) | | --location <名称> | 添加位置 / 城市(尽力而为,失败不阻断发布) | | --claim <name> | 作品声明勾选项,例如 个人观点,仅供参考 | | --first-publish | 头条首发(正文至少 100 字) | | --keywords <csv> | 文章关键词(后台有该字段时) | | --category <name> | 文章分类(后台有该字段时) | | --headed | 自动化时显示浏览器窗口 |

成功判定与边界

草稿 / 发布成功仅以创作者保存 API 返回真实 id 为准:

  • 文章:POST /mp/agw/article/publish 返回 pgc_id
  • 微头条:POST /mp/agw/draft/save_ugc_draft 返回 gid

仅有 UI toast 不算成功。保存响应 waiter 在表单填写完成后才 arm(保存 / 发布点击之前),避免把输入过程中的自动保存误判为成功。

边界:单次调用一篇文章或一条微头条;正文最多 1 MB;文章标题 2~30 字;文章正文图 3~20 张;微头条图 2~9 张;单图最多 10 MB。同一 auth 状态文件跨进程单飞加锁,并发持有者收到 TOUTIAO_LOCK_HELD。保存 / 发布不会自动重试。

示例

# 文章草稿:3 张正文插图(段落嵌入 + 可选封面)
ants toutiao publish article --headed \
  --title "示例标题" \
  --content $'第一段内容。\n\n第二段内容。\n\n第三段内容,字数足够时可加 --first-publish。' \
  --images ./a.png,./b.png,./c.png \
  --claim "个人观点,仅供参考" \
  --first-publish

# 微头条草稿:2 张图 + 话题
ants toutiao publish micro --headed \
  --content "微头条正文……" \
  --images ./a.png,./b.png \
  --topic 科技

真实托管浏览器配置(推荐用于交互登录 / 发布)

真实 Chrome/Edge + 专用自动化配置目录(不是你日常 Chrome 配置)时,先启动可调试浏览器:

ants toutiao browser start [--browser chrome|msedge] [--port 9222] [--profile <path>]
ants toutiao browser status
ants toutiao browser stop

默认:

  • 配置目录:~/.config/ants-move/toutiao/chrome-profile
  • CDP:http://127.0.0.1:9222
  • 元数据:~/.config/ants-move/toutiao/browser.json

再通过 CDP 在该真实浏览器中登录 / 发布:

# 在托管 Chrome 窗口中按需扫码
ants toutiao auth login --cdp http://127.0.0.1:9222

# 后续发布可用同一 CDP(若 browser start 仍在运行,也可省略 --cdp)
ants toutiao publish article --title "标题2到30字" --content "正文" --cdp http://127.0.0.1:9222

ants toutiao browser start 已在运行,auth / publish 在省略 --cdp 时会自动探测 CDP URL。

这是 Playwright connectOverCDP 连接本机已安装的 Chrome/Edge 进程,不会复用 ~/Library/Application Support/Google/Chrome 下的日常个人配置。

Hacker News 命令与别名

从各 Firebase 列表拉取 1~100 条:

ants hn top [--limit 1..100] [--format json|table] [-t]
ants hn new [--limit 1..100] [--format json|table] [-t]
ants hn best [--limit 1..100] [--format json|table] [-t]

通过 Algolia 搜索,按相关度或时间排序:

ants hn search <query> [--limit 1..100] [--sort relevance|date] [--format json|table] [-t]

hackernewshn 的别名,例如 ants hackernews top 等同于 ants hn topamv 可执行文件接受上述全部命令,例如 amv hackernews search typescript

Hacker News 详情请求最多 8 并发。ID 列表与搜索响应限制 5 MB,每条 Firebase story 详情限制 256 KB。

GitHub 命令

GitHub Trending

拉取 GitHub 全语言 Trending 页上展示的全部仓库。时间周期默认 daily

ants github trending
ants github trending --since daily
ants github trending --since weekly
ants github trending --since monthly

默认 JSON。可用 --format table-t 输出表格:

ants github trending --since weekly --format table
ants github trending --since monthly -t

采集器对官方服务端渲染 HTML 发一次 GitHub 请求,不使用第三方 Trending API 或 Playwright。请求超时 30 秒,HTML 限制 5 MB。解析最多接受 100 个仓库,每个仓库最多保留 10 个展示贡献者。命令无语言过滤、结果上限、自动重试或缓存;成功但 0 行的解析会当作页面结构错误拒绝,而不是返回误导性的空榜。

GitHub README

拉取公开仓库默认分支上的首选 README:

ants github readme https://github.com/owner/repository
ants github readme https://github.com/owner/repository.git

返回 JSON,包含原始 UTF-8 README 内容以及 name、path、SHA、字节大小、HTML URL、download URL、规范仓库 URL 与 API 源 URL。使用文档化的 api.github.com/repos/{owner}/{repo}/readme 端点,一次有界 GitHub API 请求,超时 30 秒,响应限制 5 MB。不爬仓库页、不探测 Raw URL、不重试、不回退其他请求。不读取 GITHUB_TOKEN

仅支持公开仓库。未认证 REST 客户端共享源 IP 时,GitHub 通常限制为每小时 60 次请求。额度用尽返回 GITHUB_RATE_LIMITED,且不重试。

科技 / AI 媒体采集

这些采集器用公开 RSS/Atom 拉列表,用公开文章 HTML 拉正文。请求走 curl,并带稳定的浏览器伪装头(Chrome Desktop UA、AcceptAccept-LanguageSec-Fetch-*Referer/Origin)。不是各媒体官方开放 API。请保持个人低频使用;CLI 不会绕过付费墙、验证码或安全挑战页。

统一形态:

ants <source> list <channel> [--limit 1..50] [--format json|table] [-t]
ants <source> article <id-or-url> [--format json]

--limit 默认 20,上限 50。列表 JSON 在 feed 提供时包含 titlesummaryauthorNamepublishTimeurl 与图片字段。正文 JSON 包含 titlesummaryauthorpublishTimecontent.paragraphscoverImageimages[].url。拿不到正文时硬失败(MEDIA_PARSE_ERROR),不会静默返回半截内容。

| 命令 | 来源 | 频道 | 正文 | |------|------|------|------| | wired | WIRED | AItechnologybusinesssciencesecurityall | 支持 | | mtr | MIT Technology Review | AItechnology | 支持 | | techcrunch | TechCrunch | AItechnology | 支持 | | verge | The Verge | AItechnology | 支持 | | ars | Ars Technica | AItechnology | 支持 | | engadget | Engadget | AI(关键词过滤)、technology | 支持 | | ieee | IEEE Spectrum | AI(关键词过滤)、technology | 支持 | | bbc | BBC Technology | AI(关键词过滤)、technology | 支持 | | google-ai | Google AI Blog | AItechnology | 支持 | | deepmind | Google DeepMind Blog | AItechnology | 支持 | | nvidia | NVIDIA Blog | AItechnology | 支持 | | openai | OpenAI Blog | AItechnology | 支持 | | bloomberg | Bloomberg Technology | AI(关键词过滤)、technology | 仅列表 |

示例:

ants wired list AI
ants wired list AI --limit 10 -t
ants wired article ai-newsrooms-are-breaking-news-now-haha-im-in-danger
ants wired article https://www.wired.com/story/example-slug/

ants mtr list AI
ants techcrunch list AI --limit 15
ants verge list technology
ants bloomberg list technology
ants bloomberg list AI

Bloomberg 仅提供 Technology 公开 RSS 的标题与摘要。文章 HTML 有付费墙 / 反爬;没有 bloomberg article 子命令。

每次 list 一次有界 feed 请求;每次 article 一次有界 HTML 请求。响应体经 curl 缓冲限制(默认 8 MB)。无后台轮询、缓存或多页扇出。

高并发使用警告

单进程内资源使用有界,但不同进程中的相同命令没有全局去重或限流。在 Q 次并发调用下,上游工作量可接近:36 氪列表 20Q 请求;Hacker News 列表 201Q 请求;头条作者采集约 105Q 次浏览器导航及页面子资源;闲鱼搜索约 Q 次浏览器会话(含页面子资源与 MTOP);GitHub Trending 或 README 各 Q 次请求;科技 / AI 媒体 list 约 Q 次 curl(list+article 约 2Q)。README 采集还会短暂保留有界 API 响应、解析 JSON、Base64 文本与解码内容;共享源 IP 的匿名调用通常共享 GitHub 每小时 60 次限制,限流失败不会重试或回退。

每次调用保留的数据也有界:36 氪列表 5 MB;Hacker News 约 200 条候选详情共约 50 MB(过滤前);头条作者文章结果 10 MB;闲鱼搜索结果 5 MB;GitHub HTML 响应 5 MB(Cheerio 解析前)。头条在同一浏览器会话中最多还可持有 5 个活跃的 5 MB feed 缓冲;浏览器进程开销、必要子资源与 HTML 解析对象开销不计入这些 payload 上限。

不要把 CLI 直接挂在高 QPS 请求路径上。在线服务必须使用外部有界队列与共享限流器,在多进程 / 多实例间施加背压。本项目没有分布式锁、共享缓存、重试队列或多实例单飞机制。

开发与校验

安装依赖并运行确定性检查:

npm install
npm run check
npm test
npm run coverage
npm run build
npm pack --json

测试使用注入的网络 / 浏览器边界,不会访问真实网站。

许可证

基于 MIT License