@geoly-ai/social-hub-cli 0.3.43 → 0.3.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/cli-error-channels.test.js +40 -0
- package/dist/cli-error-channels.test.js.map +1 -1
- package/dist/client.d.ts +7 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +19 -2
- package/dist/client.js.map +1 -1
- package/dist/cmd-manifest.json +12 -2
- package/dist/cmd-manifest.test.js +13 -0
- package/dist/cmd-manifest.test.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/output.d.ts +12 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +42 -0
- package/dist/output.js.map +1 -1
- package/dist/permissions-gates-restrictions.d.ts +10 -0
- package/dist/permissions-gates-restrictions.d.ts.map +1 -0
- package/dist/permissions-gates-restrictions.js +53 -0
- package/dist/permissions-gates-restrictions.js.map +1 -0
- package/dist/permissions-gates-restrictions.test.d.ts +2 -0
- package/dist/permissions-gates-restrictions.test.d.ts.map +1 -0
- package/dist/permissions-gates-restrictions.test.js +37 -0
- package/dist/permissions-gates-restrictions.test.js.map +1 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +2 -0
- package/dist/permissions.js.map +1 -1
- package/dist/register-restrictions.d.ts +64 -0
- package/dist/register-restrictions.d.ts.map +1 -0
- package/dist/register-restrictions.js +431 -0
- package/dist/register-restrictions.js.map +1 -0
- package/dist/register-restrictions.test.d.ts +2 -0
- package/dist/register-restrictions.test.d.ts.map +1 -0
- package/dist/register-restrictions.test.js +315 -0
- package/dist/register-restrictions.test.js.map +1 -0
- package/package.json +3 -3
- package/skills/integrity.json +26 -25
- package/skills/manifest.json +2 -2
- package/skills/reddit-answers-research/SKILL.md +1 -1
- package/skills/reddit-matrix.lock.json +5 -5
- package/skills/reddit-phase-brief/references/phase4-brief-workflow.md +2 -2
- package/skills/reddit-phase-research/references/phase01-research.md +2 -2
- package/skills/reddit-strategy-shared/references/version-manifest.md +2 -2
- package/skills/reddit-voc-volume/SKILL.md +35 -28
- package/skills/reddit-voc-volume/matrix-contract.md +1 -1
- package/skills/reddit-voc-volume/references/arctic-shift.md +8 -7
- package/skills/reddit-voc-volume/references/browser-fallback.md +9 -4
- package/skills/reddit-voc-volume/requirements.txt +3 -1
- package/skills/reddit-voc-volume/scripts/reddit_voc_volume.py +3 -20
- package/skills/reddit-voc-volume/services/firecrawl/examples/o1_web_crawler/o1_web_crawler.py +152 -152
- package/skills/reddit-voc-volume/tests/test_links_fallback.py +87 -0
- package/skills/social-hub-admin/SKILL.md +33 -0
- package/skills/social-hub-calendar-directives/SKILL.md +14 -1
- package/skills/social-hub-calendar-jobs/SKILL.md +14 -0
- package/skills/social-hub-cli/SKILL.md +2 -0
- package/skills/social-hub-content-classification/SKILL.md +4 -0
- package/skills/social-hub-graph-compliance/SKILL.md +42 -0
- package/skills/social-hub-intelligence/SKILL.md +24 -1
- package/skills/social-hub-openclaw-context/SKILL.md +21 -16
- package/skills/social-hub-ops-runtime/SKILL.md +44 -0
- package/skills/social-hub-publishing/SKILL.md +12 -0
- package/skills/social-hub-scrape/SKILL.md +18 -16
|
@@ -10,8 +10,8 @@ description: |
|
|
|
10
10
|
|
|
11
11
|
## Arctic Shift 归档后端(v2.12.27)
|
|
12
12
|
|
|
13
|
-
`history` / `comments`
|
|
14
|
-
reddit.com
|
|
13
|
+
`history` / `comments` 模式与 `keyword` / `subreddit` 的 Emergency Acquisition 都走 Arctic Shift
|
|
14
|
+
归档 API,不经 reddit.com(v2.12.28 起后端固定,**没有** `--backend` 参数)。**使用前读 [references/arctic-shift.md](references/arctic-shift.md)**,
|
|
15
15
|
尤其是「能力边界」表:正文 / `num_comments` / `upvote_ratio` / 版规 / wiki 可用;
|
|
16
16
|
**`score` 不可信**(实测约 1/3 归档行是发帖瞬间的陈旧值,逐条标 `score_status`,
|
|
17
17
|
只有 `Backfilled` 允许用于声量);此刻置顶、当前 hot、About 页周指标是 live 语义,
|
|
@@ -46,7 +46,8 @@ reddit.com。**使用前读 [references/arctic-shift.md](references/arctic-shift
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
Python 3.10
|
|
49
|
+
Python 3.10+;网络可访问 **arctic-shift.photon-reddit.com**(历史/评论/版规/wiki/about)与 Social Hub / 本机 Firecrawl(渲染页证据);建议配置 HTTPS_PROXY。
|
|
50
|
+
**本机不直连 reddit.com**:渲染页由 Hub / Firecrawl 代为访问。`curl`、`curl_cffi`、`browser_cookie3` 与 `--via-curl` 均为 v2.12.28 前的遗留物,当前代码路径用不到(见下节「请求身份」)。
|
|
50
51
|
|
|
51
52
|
## 何时用 / 不用
|
|
52
53
|
|
|
@@ -55,9 +56,9 @@ Python 3.10+;可选 curl、curl_cffi、browser_cookie3;网络可访问 reddi
|
|
|
55
56
|
| 品牌词/关键词 Reddit 声量 | 单条链接只要 score → `reddit-link-engagement` |
|
|
56
57
|
| 指定 r/xxx 内关键词扫描 | 大规模全站监控、分钟级轮询 |
|
|
57
58
|
| 批量 Reddit URL 汇总:帖子 permalink、`/about`、`/about/rules`、`/wiki/*` | 绕过私密版/验证码/登录墙 |
|
|
58
|
-
|
|
|
59
|
+
| 通过 Social Hub 取得当前置顶帖 / pinned / stickied / megathread 公开证据;Hub 不可用时标 NotVisible | 读取 AutoModerator 配置或 mod apps 后台 |
|
|
59
60
|
| 公开渲染 About 页里的周访客/周贡献/每周活跃用户兼容字段、可见 Installed Apps、公开 flair filter / page signals | 保证完整后台 Installed Apps 或 flair template 列表 |
|
|
60
|
-
|
|
|
61
|
+
| Hub / Arctic 取不到时的 Social Hub / Firecrawl / 浏览器低频兜底采样 | 并发刷搜索页 |
|
|
61
62
|
|
|
62
63
|
## 一步执行(Emergency Acquisition——仅四级链路 L3 时使用,默认先走 Hub,见上节)
|
|
63
64
|
|
|
@@ -123,9 +124,9 @@ python3 "$VOC" comments t3_abc123 --source search --body "battery life" \
|
|
|
123
124
|
# 按评论 ID 批查(最多 500;空格或逗号分隔)
|
|
124
125
|
python3 "$VOC" comments --ids t1_def456 ghi789 --pretty
|
|
125
126
|
|
|
126
|
-
#
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
# ⛔ 没有 --backend 这个参数(v2.12.28 起后端固定 Arctic Shift)。
|
|
128
|
+
# 传它会被 argparse 直接拒掉:error: unrecognized arguments: --backend
|
|
129
|
+
# 旧文档里的 `--backend arctic-shift` / `--backend reddit-json` 两条都跑不了,别照抄。
|
|
129
130
|
|
|
130
131
|
# 检查 Social Hub scrape fallback
|
|
131
132
|
python3 "$VOC" social-hub-check --pretty
|
|
@@ -136,7 +137,7 @@ python3 "$VOC" firecrawl-check --pretty
|
|
|
136
137
|
# 检查 skill 内置的 Firecrawl 自托管源码快照
|
|
137
138
|
python3 "$HOME/.cursor/skills/reddit-voc-volume/scripts/setup_firecrawl_service.py" --check --pretty
|
|
138
139
|
|
|
139
|
-
#
|
|
140
|
+
# 渲染页证据:显式启用 Social Hub 页面 fallback(Arctic 不提供渲染页信号时)
|
|
140
141
|
python3 "$VOC" links \
|
|
141
142
|
"https://www.reddit.com/r/espresso/wiki/rules" \
|
|
142
143
|
--fallback social-hub \
|
|
@@ -162,7 +163,7 @@ python3 "$VOC" links \
|
|
|
162
163
|
| `subreddit` | Hub-First 子版内关键词 VOC | `-r/--subreddit` 可重复;同上 acquisition-policy/sort/time |
|
|
163
164
|
| `links` | 批量 Reddit URL;支持帖子 permalink、subreddit about、about/rules、wiki 页面;可显式启用 Social Hub / Firecrawl 页面 fallback | URL 列表或 `--file`;`--fallback social-hub/firecrawl/auto` |
|
|
164
165
|
| `comments` | **v2.12.31 新增。** 从 Arctic Shift 读取帖子历史评论正文;默认树模式,另有筛选搜索和评论 ID 批查 | positional 帖子 URL/ID;`--source tree/search`;`--body` / `--author` / `--after` / `--before` / `--parent-id`;`--ids` |
|
|
165
|
-
| `stickies` |
|
|
166
|
+
| `stickies` | Hub-First 读取当前置顶证据;本地无有效兜底,取不到标 NotVisible | `-r/--subreddit` 可重复;`--limit` 为历史兼容参数 |
|
|
166
167
|
| `about-page` | 用 Social Hub 或自托管 Firecrawl 渲染公开 subreddit About 页,提取 weekly visitors、weekly contributions、weekly active users 兼容字段、公开 Installed Apps | `-r/--subreddit` 可重复;`--provider social-hub/firecrawl/auto`;`--firecrawl-base-url` |
|
|
167
168
|
| `page-signals` | 用 Social Hub 或自托管 Firecrawl 渲染任意公开 Reddit 页,统一解析页面 links/Markdown 里的公开信号 | URL 列表或 `--file`;`--provider social-hub/firecrawl/auto` |
|
|
168
169
|
| `flair-filters` | 渲染 subreddit home/hot/new/top,合并公开可见 flair filter 链接 | `-r/--subreddit` 可重复;`--provider social-hub/firecrawl/auto` |
|
|
@@ -272,7 +273,7 @@ python3 "$VOC" page-signals "https://www.reddit.com/r/espresso/" \
|
|
|
272
273
|
|
|
273
274
|
### Social Hub / Firecrawl 页面 fallback(可选)
|
|
274
275
|
|
|
275
|
-
页面 fallback 只在 `links`
|
|
276
|
+
页面 fallback 只在 `links` 模式按 `--fallback` 开启;当 Arctic 归档查询失败或未返回可解析的目标内容时触发。`social-hub` 需要 Social Hub CLI 已登录且 `social-hub scrape status` 可用;`firecrawl` 需要本机自托管 Firecrawl 服务。当前已验证出口上,Social Hub scrape 的 Reddit 渲染页也可能返回 captcha;`auto` 会接着尝试本机 Firecrawl,两者都失败时标 NeedsAcquisition,不把页面缺口判作内容不存在。
|
|
276
277
|
|
|
277
278
|
```bash
|
|
278
279
|
python3 "$VOC" links "https://www.reddit.com/r/espresso/wiki/rules" \
|
|
@@ -374,7 +375,7 @@ Installed Apps 只代表公开渲染 About 页可见的 app 链接,例如页
|
|
|
374
375
|
|
|
375
376
|
若页面 provider 可达但 Reddit 返回空壳页或 anti-bot 内容,`about-page` 会输出 `ok=false`、`about_page_failed: ... about_page_empty_rendered_content`。这时不要写 `NotVisible` 或“没有数据”,而是在 Phase 0.5 报告里标 `AboutPageEvidenceStatus: NeedsAcquisition`,可低频稍后重试,或要求用户提供 About 页截图/文本。
|
|
376
377
|
|
|
377
|
-
Social Hub / Firecrawl 只能提供公开 HTML/Markdown
|
|
378
|
+
Social Hub / Firecrawl 只能提供公开 HTML/Markdown 页面证据;不要把渲染页信号当成完整结构化数据。帖子 `num_comments`、`upvote_ratio` 与 flair 字段可来自 Hub 或 Arctic 归档;Arctic `score` 仅在 `score_status=Backfilled` 时可用于声量,`VerifiedLive` 则以实时核验值为准。归档 `stickied` 不证明当前置顶;当前置顶只用 Hub 的 live 证据。
|
|
378
379
|
|
|
379
380
|
## 风控(默认严格,勿随意放宽)
|
|
380
381
|
|
|
@@ -385,24 +386,30 @@ Social Hub / Firecrawl 只能提供公开 HTML/Markdown 页面证据;不要把
|
|
|
385
386
|
- 默认 `--sleep-sec 6`,每次请求后 **+1.5–4.5s** 随机抖动
|
|
386
387
|
- 默认 `--max-pages 1`,单次运行最多 **20** 个 HTTP 请求
|
|
387
388
|
- 遇 **429** → 立即熔断,输出 `rate_limited: true`
|
|
388
|
-
-
|
|
389
|
+
- 渲染页(Social Hub / Firecrawl)遇 **403/captcha/HTML challenge** → 停止扩量,见 [`references/browser-fallback.md`](references/browser-fallback.md);reddit.com `.json` 已不在采集路径内(见下节)
|
|
389
390
|
|
|
390
391
|
长期监控:按**小时/天**排程、缓存结果、只增量查询;勿同一 IP 高频轮询。
|
|
391
392
|
|
|
392
393
|
v2.12.23 沿用 v2.12.12 引入的安全默认采样:`limit=10 / sleep=6`,目的是降低单次误触发风控的概率。Phase 0.5 / Phase 1 如需更大样本,应在命令中显式传 `--limit` 和 `--sleep-sec`,不要依赖默认值。
|
|
393
394
|
|
|
394
|
-
##
|
|
395
|
+
## 请求身份(v2.12.28 起不再打 reddit.com `.json`)
|
|
395
396
|
|
|
396
|
-
|
|
397
|
+
🔴 **本脚本已不向 reddit.com 发 `.json` 请求。** v2.12.28 把 `search.json` / `<permalink>.json` /
|
|
398
|
+
`about.json` / `rules.json` / `wiki/*.json` 全部换成 Arctic Shift 端点(对照表见
|
|
399
|
+
[`references/arctic-shift.md`](references/arctic-shift.md) §「v2.12.28:reddit `.json` 直采已全部移除」),
|
|
400
|
+
渲染页证据走 Social Hub / Firecrawl。**2026-09-18 实测:`.json` 对住宅代理同样 403**,
|
|
401
|
+
Reddit 侧封控已不是「换个指纹/加 cookie 就能过」的问题,别再把它当可选通道。
|
|
397
402
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
403
|
+
遗留物盘点:`RedditHttpClient` / `CookieStore` 仍有定义,但主流程不再实例化客户端,也不会读取浏览器 cookie;
|
|
404
|
+
`--via-curl` 是保留的空开关;`fetch_via_curl_cffi` / `http_get_json_via_curl` 只有定义没有调用。
|
|
405
|
+
`requirements.txt` 的 `curl_cffi`、`browser_cookie3` 当前路径用不到。输出信封里的
|
|
406
|
+
`request_identity.*` 是兼容字段,**不表示真的打过 reddit.com**。
|
|
402
407
|
|
|
403
|
-
|
|
408
|
+
`links` 模式四种目标现在全部走 Arctic:帖子 permalink → `arctic_post_by_permalink`,
|
|
409
|
+
about / rules / wiki → 对应的 `arctic_*_as_reddit_payload`;取不到才按 `--fallback` 走 Hub / Firecrawl 渲染页。
|
|
404
410
|
|
|
405
|
-
|
|
411
|
+
出站身份现在只剩两类:Arctic Shift 归档 API(普通 HTTPS,可用 `HTTPS_PROXY`)与
|
|
412
|
+
Social Hub / Firecrawl 渲染页。
|
|
406
413
|
|
|
407
414
|
## 输出 JSON 结构
|
|
408
415
|
|
|
@@ -485,8 +492,8 @@ Cookie **仅**用于减少公开页误判,不用于私密版/验证码。输
|
|
|
485
492
|
> | `selftext_chars` / `selftext_words` | 正文真实长度(截断前) |
|
|
486
493
|
> | `selftext_truncated` | `false`=全文可信;`true`=被截断;**`null`=来源未声明(Hub 的 `selftextExcerpt` 即为此类),下游须按已截断处理** |
|
|
487
494
|
>
|
|
488
|
-
>
|
|
489
|
-
>
|
|
495
|
+
> **`selftext_truncated=false` 的合法来源** —— Hub 记录声明 `selftextCompleteness: full`;
|
|
496
|
+
> Arctic Shift 归档。(v2.12.27 原列的第三项「reddit `.json` 直采」自 v2.12.28 起已不存在。)
|
|
490
497
|
> Hub 的 `unknown` / 无声明仍是 `null`。Hub dispatch run 的 `resultPayload`
|
|
491
498
|
> **不带正文字段**,脚本会从 `intelligence hot-posts` 回填,回填不到保持 `null`。
|
|
492
499
|
>
|
|
@@ -507,13 +514,13 @@ Cookie **仅**用于减少公开页误判,不用于私密版/验证码。输
|
|
|
507
514
|
|
|
508
515
|
|
|
509
516
|
- `score` 是 Reddit 展示分,≠ 纯点赞数;`upvote_ratio` 更有参考价值。
|
|
510
|
-
- `flair_*`
|
|
517
|
+
- `flair_*` 从 Hub 或 Arctic 帖子记录的 `link_flair_*` 字段映射;无 flair 时字段保持 `null` 或空数组。帖子 item 还包含来源记录中可见的 `flair_template_id`、`flair_filter_query`、`author_flair_text`、`author_flair_type`、NSFW/spoiler/gallery/video 等辅助字段。
|
|
511
518
|
- `item_type=post` 是帖子;`item_type=subreddit_about` / `subreddit_rules` / `wiki_page` 是非帖子公开页面证据,`score` / `num_comments` 置 0 仅为 schema 兼容。
|
|
512
519
|
- `item_type=comment` 来自 `comments`,`body` 为不截断的归档评论正文;`parent_id` 加树坐标可还原层级。其 `score_status=ArchivedSnapshot`、`score_realtime=false`,不得当实时热度。
|
|
513
|
-
- `item_type=pinned_post`
|
|
514
|
-
- `item_type=firecrawl_page` 是 Social Hub / Firecrawl 页面 fallback 结果,含 `markdown_excerpt`、`html_excerpt`、`metadata`、`page_provider` 和 `page_signals`;只在 `--fallback social-hub|firecrawl|auto` 且
|
|
520
|
+
- `item_type=pinned_post` 只能来自 Hub 的当前置顶证据;`stickies` 的本地 Emergency Acquisition 不再产出它。Hub 取不到时标 NotVisible / NeedsAcquisition,不用归档 `stickied` 冒充。
|
|
521
|
+
- `item_type=firecrawl_page` 是 Social Hub / Firecrawl 页面 fallback 结果,含 `markdown_excerpt`、`html_excerpt`、`metadata`、`page_provider` 和 `page_signals`;只在 `--fallback social-hub|firecrawl|auto` 且 Arctic 查询失败或未返回可解析目标时出现。
|
|
515
522
|
- `item_type=subreddit_about_page` 是 `about-page` 的 Social Hub / Firecrawl 渲染结果,含 `weekly_visitors`、`weekly_contributions`、`weekly_active_users`、`weekly_active_users_source`、`installed_apps`、`installed_apps_status`、`flair_filters`、`page_signals`、`page_provider`,只能作为公开渲染 About 页证据。
|
|
516
|
-
- `item_type=reddit_page_signals` / `subreddit_flair_filters` 来自 `page-signals` / `flair-filters
|
|
523
|
+
- `item_type=reddit_page_signals` / `subreddit_flair_filters` 来自 `page-signals` / `flair-filters`,只表示公开渲染页可见链接和正文信号;不能单凭它们证明实时 score/comment/current-pinned,也不能证明后台 flair template 或 Installed Apps 完整列表。
|
|
517
524
|
- `subreddit_rules` items 含 `rules[]`、`rule_count`、`rules_text_excerpt`;`wiki_page` items 含 `wiki_page`、`content_md_excerpt`;`subreddit_about` items 含 `public_description`、`description_excerpt`、`submit_text_excerpt`、`allow_images/videos/polls/galleries`、`link_flair_enabled`、`user_flair_enabled_in_sr`、`wiki_enabled`、banner/sidebar 元数据。
|
|
518
525
|
- `subreddit_metrics` 是 best-effort 板块公开指标。v2.12.28 起 `subscribers` 等来自 **Arctic Shift 的 subreddit 元数据**,`metrics_status=ArchivedSnapshot` —— Arctic 的 subreddit 列表更新不频繁,这是**快照值,不是实时订阅数**。另附 `num_posts` / `num_comments` / `metrics_updated_at`(来自 `_meta`,刷新更勤)。取不到时字段为 `null` 且 `metrics_status=Unavailable`。要实时规模指标走 `about-page` 渲染页或 Hub。
|
|
519
526
|
- `subreddit_metrics.weekly_visitors` / `subreddit_metrics.weekly_active_users` 不是稳定公开 JSON 字段,默认输出 `null`;需要周访客/周贡献时运行 `about-page`,并在报告中标注来源为 `public_rendered_about_page`。
|
|
@@ -522,7 +529,7 @@ Cookie **仅**用于减少公开页误判,不用于私密版/验证码。输
|
|
|
522
529
|
|
|
523
530
|
## 浏览器兜底
|
|
524
531
|
|
|
525
|
-
|
|
532
|
+
Arctic 查询缺口或渲染页取不到时,先按 Hub-First 决策表处理;`links` 可显式启用 `--fallback auto`。若 Social Hub 和本地 Firecrawl 都不可用,再读 [`references/browser-fallback.md`](references/browser-fallback.md):低频打开搜索页/子版页,只读首屏,回填同一 schema(`fetch_mode: browser_fallback`,`confidence: sampled`)。
|
|
526
533
|
|
|
527
534
|
## 安装与依赖
|
|
528
535
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
- archived comment bodies and reconstructable thread hierarchy from Arctic Shift
|
|
20
20
|
(`comments`; `parent_id` plus tree coordinates; archive score is not live)
|
|
21
21
|
- public subreddit rules/wiki/about/submit-text evidence
|
|
22
|
-
-
|
|
22
|
+
- current pinned/stickied/megathread evidence from Social Hub (no local archive substitute)
|
|
23
23
|
|
|
24
24
|
## Evidence Role
|
|
25
25
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Arctic Shift 归档后端(v2.12.27;v2.12.31 增加评论正文)
|
|
2
2
|
|
|
3
|
-
> **何时读本文件:** 使用 `history` / `comments` 模式,或 Emergency Acquisition
|
|
4
|
-
> `--backend
|
|
5
|
-
>
|
|
3
|
+
> **何时读本文件:** 使用 `history` / `comments` 模式,或 Emergency Acquisition 取数时
|
|
4
|
+
> (v2.12.28 起后端固定 Arctic Shift,**没有** `--backend` 参数可选)。判断某个字段能不能用,
|
|
5
|
+
> 以本文件的「能力边界」表为准。
|
|
6
6
|
|
|
7
7
|
上游项目:<https://github.com/ArthurHeitmann/arctic_shift>
|
|
8
8
|
Base URL:`https://arctic-shift.photon-reddit.com`
|
|
@@ -130,12 +130,13 @@ python3 "$VOC" comments "https://www.reddit.com/r/example/comments/abc123/slug/"
|
|
|
130
130
|
python3 "$VOC" comments abc123 --source search --body "battery life" --parent-id top --pretty
|
|
131
131
|
python3 "$VOC" comments --ids t1_def456 ghi789 --pretty
|
|
132
132
|
|
|
133
|
-
# Emergency Acquisition
|
|
134
|
-
python3 "$VOC" keyword "PLAUD recorder" --
|
|
135
|
-
|
|
133
|
+
# Emergency Acquisition:后端固定 Arctic Shift,直接跑即可
|
|
134
|
+
python3 "$VOC" keyword "PLAUD recorder" --pretty
|
|
135
|
+
# ⛔ 没有 --backend 参数。旧文档里的 `--backend arctic-shift` / `--backend reddit-json`
|
|
136
|
+
# 都会被 argparse 拒掉:error: unrecognized arguments: --backend
|
|
136
137
|
```
|
|
137
138
|
|
|
138
|
-
|
|
139
|
+
后端不可切换:v2.12.28 起固定 Arctic Shift。(旧文档提到的 `REDDIT_VOC_BACKEND` 环境变量脚本里并不存在,设了也没有任何效果。)
|
|
139
140
|
|
|
140
141
|
## 输出信封新增字段
|
|
141
142
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 浏览器低频兜底(渲染页也取不到时)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **v2.12.28 起的前提变化**:主路径已不打 reddit.com `.json`(历史走 Arctic Shift,证据走
|
|
4
|
+
> Social Hub / Firecrawl 渲染页)。**2026-09-18 实测 `.json` 对住宅代理同样 403**,所以这里的
|
|
5
|
+
> 触发条件应读作「Hub 与 Firecrawl 渲染页都取不到」,而不是「JSON 挂了」。
|
|
6
|
+
|
|
7
|
+
当 Arctic / Hub 无法提供所需证据,且 Social Hub / Firecrawl 渲染页返回 `403` / captcha
|
|
8
|
+
或连续 `429` 熔断后,才考虑浏览器兜底。**不是**默认路径;验证码或登录墙必须停止,不得绕过。
|
|
4
9
|
|
|
5
10
|
## 原则
|
|
6
11
|
|
|
@@ -8,7 +13,7 @@
|
|
|
8
13
|
- 只读 **首屏/少量可见** 帖子,不自动滚动扫全量
|
|
9
14
|
- 页面间等待 **≥10–20s**,加随机停顿;不连续刷新同一 URL
|
|
10
15
|
- 不用登录态绕过私密/受限内容;不处理验证码;不自动换 IP
|
|
11
|
-
-
|
|
16
|
+
- 输出必须复用 VOC 的结构化 schema,并标记:
|
|
12
17
|
- `fetch_mode: "browser_fallback"`
|
|
13
18
|
- `confidence: "sampled"`
|
|
14
19
|
- `notes`: 说明为浏览器首屏采样,非完整结果
|
|
@@ -25,7 +30,7 @@ https://www.reddit.com/r/SUBREDDIT/search/?q=QUERY&restrict_sr=1&sort=relevance&
|
|
|
25
30
|
1. 先读 `browser-element-finder` skill 的连接规范(profile + targetId)
|
|
26
31
|
2. `browser(action="open", url=<search_url>, profile=...)`
|
|
27
32
|
3. `browser(action="snapshot", ...)` 读取可见帖子标题、链接、score、评论数(若 snapshot 含)
|
|
28
|
-
4. 手动解析为 `items[]`,字段对齐
|
|
33
|
+
4. 手动解析为 `items[]`,字段对齐 VOC 输出 schema
|
|
29
34
|
5. 等待 ≥10s 再开下一页(通常本次任务只开一页)
|
|
30
35
|
|
|
31
36
|
## 回填 JSON 示例片段
|
|
@@ -3078,9 +3078,7 @@ def collect_subreddit_metrics(
|
|
|
3078
3078
|
subreddit_names: list[str],
|
|
3079
3079
|
*,
|
|
3080
3080
|
user_agent: str,
|
|
3081
|
-
force_curl: bool,
|
|
3082
3081
|
tracker: RequestTracker,
|
|
3083
|
-
http: RedditHttpClient,
|
|
3084
3082
|
notes: list[str],
|
|
3085
3083
|
errors: list[str],
|
|
3086
3084
|
) -> list[dict[str, Any]]:
|
|
@@ -4008,9 +4006,7 @@ def run_stickies_mode(
|
|
|
4008
4006
|
limit: int,
|
|
4009
4007
|
sleep_sec: float,
|
|
4010
4008
|
user_agent: str,
|
|
4011
|
-
force_curl: bool,
|
|
4012
4009
|
tracker: RequestTracker,
|
|
4013
|
-
http: RedditHttpClient,
|
|
4014
4010
|
) -> tuple[list[dict[str, Any]], list[str], list[str]]:
|
|
4015
4011
|
notes: list[str] = []
|
|
4016
4012
|
errors: list[str] = []
|
|
@@ -4071,9 +4067,7 @@ def run_links_mode(
|
|
|
4071
4067
|
*,
|
|
4072
4068
|
sleep_sec: float,
|
|
4073
4069
|
user_agent: str,
|
|
4074
|
-
force_curl: bool,
|
|
4075
4070
|
tracker: RequestTracker,
|
|
4076
|
-
http: RedditHttpClient,
|
|
4077
4071
|
fallback: str = "none",
|
|
4078
4072
|
firecrawl_base_url: str | None = None,
|
|
4079
4073
|
verify_rules: bool = False,
|
|
@@ -4243,7 +4237,7 @@ def run_links_mode(
|
|
|
4243
4237
|
else:
|
|
4244
4238
|
errors.append(f"{url}: {msg}")
|
|
4245
4239
|
notes.append(
|
|
4246
|
-
"
|
|
4240
|
+
"Arctic lookup failed. To try page fallback, rerun links with "
|
|
4247
4241
|
"--fallback social-hub, --fallback firecrawl, or --fallback auto."
|
|
4248
4242
|
)
|
|
4249
4243
|
except Exception as e:
|
|
@@ -4253,7 +4247,7 @@ def run_links_mode(
|
|
|
4253
4247
|
else:
|
|
4254
4248
|
errors.append(f"{url}: {e}")
|
|
4255
4249
|
notes.append(
|
|
4256
|
-
"
|
|
4250
|
+
"Arctic lookup failed. To try page fallback, rerun links with "
|
|
4257
4251
|
"--fallback social-hub, --fallback firecrawl, or --fallback auto."
|
|
4258
4252
|
)
|
|
4259
4253
|
jitter = sleep_with_jitter(sleep_sec)
|
|
@@ -4941,7 +4935,7 @@ def main() -> int:
|
|
|
4941
4935
|
if _env_truthy("REDDIT_SOCIAL_HUB_ENABLED")
|
|
4942
4936
|
else "none"
|
|
4943
4937
|
),
|
|
4944
|
-
help="Optional page fallback when
|
|
4938
|
+
help="Optional page fallback when the Arctic archive lookup fails or returns nothing. auto tries social-hub first, then local Firecrawl.",
|
|
4945
4939
|
)
|
|
4946
4940
|
pl.add_argument(
|
|
4947
4941
|
"--firecrawl-base-url",
|
|
@@ -5346,7 +5340,6 @@ def main() -> int:
|
|
|
5346
5340
|
|
|
5347
5341
|
tracker = RequestTracker()
|
|
5348
5342
|
mode_acquisition: dict[str, Any] | None = None
|
|
5349
|
-
http = RedditHttpClient(args.user_agent if hasattr(args, "user_agent") else DEFAULT_UA, force_curl=getattr(args, "via_curl", False))
|
|
5350
5343
|
|
|
5351
5344
|
if args.mode in ("keyword", "subreddit"):
|
|
5352
5345
|
effective_limit, limit_truncated = clamp_limit(args.limit)
|
|
@@ -5413,9 +5406,7 @@ def main() -> int:
|
|
|
5413
5406
|
subreddit_metrics = collect_subreddit_metrics(
|
|
5414
5407
|
metric_subreddits,
|
|
5415
5408
|
user_agent=args.user_agent,
|
|
5416
|
-
force_curl=args.via_curl,
|
|
5417
5409
|
tracker=tracker,
|
|
5418
|
-
http=http,
|
|
5419
5410
|
notes=notes,
|
|
5420
5411
|
errors=errors,
|
|
5421
5412
|
)
|
|
@@ -5474,9 +5465,7 @@ def main() -> int:
|
|
|
5474
5465
|
limit=effective_limit,
|
|
5475
5466
|
sleep_sec=args.sleep_sec,
|
|
5476
5467
|
user_agent=args.user_agent,
|
|
5477
|
-
force_curl=args.via_curl,
|
|
5478
5468
|
tracker=tracker,
|
|
5479
|
-
http=http,
|
|
5480
5469
|
)
|
|
5481
5470
|
notes.extend(local_notes)
|
|
5482
5471
|
errors.extend(local_errors)
|
|
@@ -5488,9 +5477,7 @@ def main() -> int:
|
|
|
5488
5477
|
subreddit_metrics = collect_subreddit_metrics(
|
|
5489
5478
|
subreddits,
|
|
5490
5479
|
user_agent=args.user_agent,
|
|
5491
|
-
force_curl=args.via_curl,
|
|
5492
5480
|
tracker=tracker,
|
|
5493
|
-
http=http,
|
|
5494
5481
|
notes=notes,
|
|
5495
5482
|
errors=errors,
|
|
5496
5483
|
)
|
|
@@ -5688,9 +5675,7 @@ def main() -> int:
|
|
|
5688
5675
|
urls,
|
|
5689
5676
|
sleep_sec=args.sleep_sec,
|
|
5690
5677
|
user_agent=args.user_agent,
|
|
5691
|
-
force_curl=args.via_curl,
|
|
5692
5678
|
tracker=tracker,
|
|
5693
|
-
http=http,
|
|
5694
5679
|
fallback=args.fallback,
|
|
5695
5680
|
firecrawl_base_url=args.firecrawl_base_url,
|
|
5696
5681
|
verify_rules=getattr(args, "verify_rules", False),
|
|
@@ -5702,9 +5687,7 @@ def main() -> int:
|
|
|
5702
5687
|
subreddit_metrics = collect_subreddit_metrics(
|
|
5703
5688
|
[str(item.get("subreddit") or "") for item in items],
|
|
5704
5689
|
user_agent=args.user_agent,
|
|
5705
|
-
force_curl=args.via_curl,
|
|
5706
5690
|
tracker=tracker,
|
|
5707
|
-
http=http,
|
|
5708
5691
|
notes=notes,
|
|
5709
5692
|
errors=errors,
|
|
5710
5693
|
)
|