剑鱼标讯发现与回链采集
1. 触发条件
满足任一条件时启用本技能:
- 用户明确要求抓取/监测剑鱼标讯的招标信息;
- 用户给出"地区 + 业务关键词"的招标商机发现需求,且允许使用第三方聚合平台做发现层;
- shaanxi-tender-monitor 等监测流程需要剑鱼作为 discovery_only 来源运行。
前置条件:agent-browser 可用。本机安装于托管 Node 工作区,执行前设置:
export PATH="/Users/omega/.workbuddy/binaries/node/workspace/node_modules/.bin:$PATH"
export NODE_PATH="/Users/omega/.workbuddy/binaries/node/workspace/node_modules"
agent-browser --version # 实测可用性,以命令输出为准
2. 输入参数
| 参数 | 必填 | 默认 | 说明 |
|---|---|---|---|
query |
是 | — | 检索词,建议"地域词 + 业务词"(如 陕西 办公设备);多词空格分隔默认 OR 匹配 |
and_match |
否 | false | true 时先勾选「多个关键词」复选框实现 AND 匹配 |
max_pages |
否 | 1 | 列表翻页上限,最大 3(低频合规约束) |
region_filter |
否 | 空 | 候选地区过滤词(如 陕西),命中才进入详情提取 |
detail_limit |
否 | 50 | 详情页批量提取条数上限 |
trace_back |
否 | true | 是否执行回链:标题精确匹配公开搜索定位白名单原始公告 |
whitelist |
否 | 空 | 允许入库的原始平台域名清单;不回链到白名单的候选不入库 |
output_dir |
是 | — | 输出目录(发现清单、详情、状态文件均写入此处) |
3. 执行流程
S1 环境检查 → S2 登录态探针 →(未登录→S3 登录交接)→ S4 检索列表
→ S5 候选解析落盘 → S6 登录态批量详情提取 → S7 回链白名单原文
→ S8 入库与状态记录 → S9 关闭会话 → S10 定时任务交互(两页跳转式提问)
S1 环境检查
设置 PATH/NODE_PATH,agent-browser --version 实测。失败则终止并报告,不得降级为静态抓取(搜索页为 JS 渲染,静态 HTML 零数据)。
S2 登录态探针(每次运行必做)
打开任一详情页或首页,eval 探针:
JSON.stringify({
loginBtnGone: !document.querySelector('.login-btn, .loginBtn, [class*=login-btn]'),
hasAvatar: !!document.querySelector('img[class*=avatar], .avatar, [class*=Avatar]'),
cookieLen: document.cookie.length
})
hasAvatar:true 且 loginBtnGone:true 判定为已登录,直接进入 S4。否则进入 S3。
S3 登录交接机制(核心:自动暂停 → 人工登录 → 确认续跑)
原则:不绕过、不读取日常浏览器 Cookie、状态全落盘、用户确认后断点续跑。
- 暂停与落盘:先将当前已发现候选(如有)完整写入
{output_dir}/jianyu-discovery.jsonl,并写{output_dir}/pending-login.json(含 query、已完成的列表页码、时间戳),保证暂停不丢任何进度。 - 呈现登录入口:打开剑鱼首页,点击登录入口调出微信扫码弹窗,截图保存
{output_dir}/jianyu-login-qr.png并展示给用户。 - 明确等待指令:结束当前执行,向用户输出:"请在预览的浏览器窗口中扫码完成剑鱼登录,完成后回复『已登录』,我将自动验证并继续后续步骤。"同时在来源状态中记录
manual_action_required。 - 确认后验证(不信任口头确认):用户回复后重新执行 S2 探针。通过 → 从
pending-login.json断点续跑;未通过 → 重新截图引导,最多重试 2 次,仍失败则报告并保留现场。 - 批量任务中掉线:详情提取循环中若探针检测到掉登录,立即停循环、保存已完成部分,回到步骤 1。
S4 检索列表(交互细节已经实测,不得臆测)
- 在关键词输入框输入
query后,必须点击「搜 索」提交键;「精准搜索」是搜索模式下拉按钮,不是提交键,误点会返回全国混合噪声。 - 空格分隔多词默认 OR 匹配;
and_match:true时先勾选输入框下方「多个关键词」复选框。 - URL 的
searchword参数不会自动触发检索,不能靠拼 URL 绕过交互。 - 同域串行,操作间隔 ≥2 秒,最多
max_pages页。
S5 候选解析落盘
列表每条提取:序号、标题、相对时间(入库前按抓取时间折算绝对时间)、地区(省-市-区县)、阶段标签、行业、内容摘要、混淆 dataid。注意:列表条目无直接详情 URL,详情地址格式为 https://www.jianyu360.cn/nologin/content/{dataid}.html(/content/{dataid}.html 会 404,此格式已经 window.open 拦截实测)。按 region_filter 过滤后写入 jianyu-discovery.jsonl,trace_status: pending_login 或 pending_trace。
S6 登录态批量详情提取
agent-browser 为全捆绑包、无 playwright-core,不能用 CDP/Playwright 脚本,用 bash 循环驱动 CLI:
while read DATAID; do
agent-browser open "https://www.jianyu360.cn/nologin/content/${DATAID}.html"
sleep 4 # 等待 SPA 渲染
agent-browser eval "$(cat scripts/jianyu-detail-extract.js)" >> details_raw.jsonl
sleep 2.5 # 低频间隔
done < dataids.txt
提取器输出字段与可靠性矩阵(2026-09-03 实测):
| 字段 | 可靠性 | 说明 |
|---|---|---|
| title | ✅ 可信 | 取 document.title;h1 被混淆字体渲染,不可用 |
| date / region | ✅ 可信 | 信息区未混淆 |
| buyer / project_id / phone | ⚠️ 部分 | 免费账号可能 **** 遮罩,空值勿猜 |
| amount | ⚠️ 校验 | 上下文关键词+单位锚定;amount_suspicious:true(>5000万元)需人工复核 |
| content | ❌ 仅结构参考 | MyNewFont 字体混淆 + 数字遮罩;以 content_obfuscated / masked_field_count 标记,禁止直接用于分析或入库 |
CLI 对 eval 输出双层 JSON 包装,解析时必须两次 JSON.parse / json.loads。
S7 回链白名单原文
- 对每条候选执行"标题精确匹配公开搜索"(WebSearch 或白名单平台站内搜索),定位
whitelist域名内的原始公告页。 - 打开原文页一次,全部字段以原始公告为准(剑鱼侧字段仅作线索)。
- 以项目编号 + 发布日期双重校验,防止同系列多年度项目误配。
- 免费账号「查看原文链接」额度有限,不得依赖该功能;回链不到白名单原文的候选只保留在发现清单,记录原因,不入库。
S8 入库与状态记录
- 按消费方 schema 写入(配合 shaanxi-tender-monitor 时写
raw-notices.jsonl,source_id用白名单平台 ID,discovery_url指向剑鱼详情页)。 - 写
source-status.json:success / no_new_items / manual_action_required / failed,附列表页数、详情页数、入库数与备注。
S9 关闭会话
无论成功失败:agent-browser close。
S10 定时任务交互(任务收尾的固定动作,两页跳转式提问)
当次任务完成、结果已交付后,必须通过交互式提问引导用户决定是否开启定时监测。禁止替用户默认创建,也禁止省略提问直接结束。
第一页提问(是否开启),使用 AskUserQuestion:
- 问题:"本次监测已完成。是否将剑鱼标讯监测设为定时任务,后续自动运行?"
- 选项 A:「开启定时监测(推荐)」——说明:按选定周期自动检索、回链并生成日报;
- 选项 B:「暂不需要」——说明:仅本次手动运行,之后需要时可随时再开;
- 用户也可选"其他"自定义(如"先跑一周看看")。
第二页提问(选择时间):仅当用户选择开启时发起,同样使用 AskUserQuestion:
- 问题:"希望什么时间自动运行?(建议避开目标网站访问高峰)"
- 选项:「每工作日 08:30」(上班前出日报)/「每日 08:30」(含周末)/「每日 12:30」(午间更新)/「每周一 08:30」(周报节奏);
- 用户选"其他"时按其指定的时间与频率表达。
创建与确认:
- 用
automation_update(mode=create)创建 recurring 自动化,rrule 按用户选择生成(如每工作日 08:30 →FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=8;BYMINUTE=30),prompt 需自包含:写明检索词、地区过滤、输出目录、白名单回链要求及"遇登录墙暂停等待人工"的交接规则; - 创建前先用
automation_update(mode=list)检查是否已存在同类任务,存在则改为 update 而非重复创建; - 创建后用自然语言向用户复述生效时间(不展示 RRULE 原文),并告知暂停/修改入口;
- 用户选择"暂不需要"时,礼貌收尾并提示"之后任何一次运行结束时都可以再开启"。
4. 异常处理
| 异常 | 处理 |
|---|---|
| agent-browser 不可用 | 终止并报告;禁止静态抓取冒充结果 |
| 登录墙 | 走 S3 交接;状态记 manual_action_required,绝不绕过 |
| 检索结果与查询词无关 | 检查是否误点「精准搜索」;用「搜 索」重试 |
| 详情 URL 404 | 确认使用 /nologin/content/ 前缀 |
| eval JSON 解析失败 | 二次解析双层包装 |
| 正文乱码/金额遮罩 | 正常预期,依赖 content_obfuscated 标记与回链原文;不视为失败 |
| 批量中途掉登录 | 停循环、存进度、回 S3 |
| 网络超时/5xx | 单条重试 1 次(间隔 ≥5 秒),仍失败记录跳过,不中断整批 |
| 回链未命中 | 记录原因(如"原始平台非白名单"/"未检到原文"),候选留发现清单 |
5. 输出格式
| 文件 | 内容 |
|---|---|
jianyu-discovery.jsonl |
全部候选:rank/title/relative_time/region/stage_tag/excerpt/dataid/discovery_url/trace_status |
jianyu-details.json |
详情提取结果(含混淆与遮罩标记) |
raw-notices.jsonl |
回链成功记录(字段以白名单原文为准,可选,配合外部管线) |
pending-login.json |
登录暂停断点(query、进度、时间戳) |
jianyu-login-qr.png |
登录二维码截图 |
source-status.json |
来源运行状态与统计 |
6. v2.x 相比初版流程的改进点
- 登录交接机制从无到有:初版遇登录墙流程中断、候选丢失;v2.0 候选与断点先落盘(
pending-login.json),自动暂停并呈现二维码,用户确认后探针验证、断点续跑,最多重试 2 次,全程不丢进度。 - 登录验证客观化:不再依赖用户口头确认,以头像/登录按钮/Cookie 探针双重判定;批量中途掉线可自愈式暂停。
- 交互知识固化:「搜 索」提交键 vs「精准搜索」下拉、「多个关键词」AND 复选框、
/nologin/content/详情 URL 格式,全部写入流程,杜绝同类误操作。 - 数据可信度分层:新增字段可靠性矩阵与混淆/遮罩检测标记,正文乱码与金额误读(旧版 9162.11 元误作万元)被系统性拦截,金额带单位锚定与 >5000 万元人工复核阈值。
- 批量提取方式纠偏:明确 agent-browser 无 playwright-core,标准做法为 bash 循环驱动 CLI(含 sleep 节奏),并注明 eval 双层 JSON 解析要点。
- 回链路径去付费依赖:确认免费账号「查看原文链接」额度不可依赖,回链固定走标题精确匹配公开搜索 + 项目编号/日期双重校验。
- 可恢复性与可审计性:全环节状态落盘(发现清单/详情/断点/来源状态),任何中断均可从最近状态续跑。
- 定时任务收尾交互(v2.1 新增):任务完成后固定执行两页跳转式提问——先问"是否开启定时监测",确认后再跳转第二页选择运行时间,最后创建自动化并用自然语言复述生效时间;不默认创建、不省略提问,用户可随时开启或跳过。