dsh-zotero-flow:连接 Zotero 的机构登录全文获取流水线

前言

DeepSeek Harness(DSH Desktop)的智能体在处理文献检索与归档时,通常会遇到两个现实问题:一是机构数据库(知网、万方、ScienceDirect 等)大多需要登录权限,直接从 Node 进程发起 HTTP 请求往往只能拿到付费墙;二是即便拿到了 PDF,还需要手动拆分元数据并归档到 Zotero 的分类树里。dsh-zotero-flow 就是在这两种痛点之间搭建一条自动化流水线,让 agent 能在机构登录会话下取回全文,并连同条目一起归档进 Zotero。

插件由 YHzed 维护,定位为 DSH Desktop 插件,分类属于联网工具。它通过一组工具和技能,把「DOI/标题 → 规范元数据 → 机构登录会话里取 PDF → 归档进 Zotero」这一完整流程固化下来,供智能体按顺序调用。

核心能力

插件提供以下工具与技能,按功能拆解如下:

  • zotero_status:体检 Zotero 是否运行、连接器与本地 API 状态、当前归档目标、浏览器会话与落盘目录。确认版本号和端口连通即可视为安装成功。
  • library_sites:列出院内「数据资源数据库」里的各站点(知网、万方、ScienceDirect、WoS、Springer、IEEE、Wiley、T&F、ACS、SciFinder、IOP、MathSciNet、ProQuest、SpiScholar、科学文库、超星等)以及每站取全文的可行路径。
  • literature_lookup:用 DOI / 标题 / arXiv 号解析规范元数据(Crossref、OpenAlex、Unpaywall),免密钥,给出开放获取 PDF 直链与出版社归属。
  • scholar_session:起一个独立的资料目录的 Edge/Chrome,用户在其中登录学校 SSO / CARSI / WebVPN;之后打开页面并读回引文 DOI、citation_pdf_url、页面 PDF 链接、登录/付费/验证码迹象。
  • scholar_download:在已登录会话里抓 PDF 落盘。三条通道自动竞速:下载落盘 / Network 响应体 / 页面内 fetch;也能只监视下载目录,接管用户手动点的「下载全文」。
  • zotero_collections:查看当前归档目标与可选分类。
  • zotero_save:元数据 + PDF 一次性归档到分类(DOI/标题 + 本地或在线 PDF + 标签 + 子笔记)。
  • zotero_import_pdf:把本地已有 PDF 归档;先从 PDF 里抠 DOI 解析元数据,抠不到就交给 Zotero 自己识别。
  • zotero-literature-flow:技能,教模型按正确顺序用这些工具、以及什么时候该停下来问用户。

安装与启用

插件是一个标准的 DSH 组合包,通过目录或打包后的 .tgz 安装。

从 GitHub 取下来:

git clone https://github.com/YHzed/dsh-zotero-flow.git

从界面安装:

  1. 打开 DSH Desktop 的 侧栏 → 插件。
  2. 点 添加插件。
  3. 在输入框里填插件目录的绝对路径(或打包好的 .tgz 绝对路径),例如 clone 下来的 D:\tools\dsh-zotero-flow。
  4. 点 安装,装完点 立即启用。

如果插件装在了别处或想自己打包一个 .tgz:在插件目录下跑 npm pack,把生成的 dsh-zotero-flow-1.0.5.tgz 路径填进「添加插件」即可。

装完确认:回到对话里让 agent 调一次 zotero_status,能看到 Zotero 版本和落盘目录就通了。

改了插件代码之后要重新走一遍安装(profile 里的插件是复制进去的,不感知源码更新)。

首次使用前的准备

1. Zotero 桌面端要开着

插件走的是 Zotero 自带的连接器 HTTP 服务(127.0.0.1:23119),默认就是开的,不需要 API key。zotero_status 会打印版本号,读到版本号即通。

自动导入前必须打开本地 API(用于强制检索与查重):

Zotero → 编辑 → 设置 → 高级 → 常规 → 勾选「允许本机其他应用与 Zotero 通信」。

  • 关着:只能看到「当前选中的分类」与「最近使用过的分类」,库内条目检索不可用。
  • 打开:能读到带 key 的完整分类树,并能在库内检索、查重。

Zotero 10+ 的本地 API 支持经过用户授权的写入和附件上传;旧版可能仅支持读取。首次写入会弹出「DSH Zotero Flow」的授权窗口;选择允许或始终允许,不要提供 zotero.org 云端 API key。

2. 先登录一次机构账号

第一次需要取全文时,agent 会调 scholar_session action=start,弹出一个独立的浏览器窗口(资料目录默认 %USERPROFILE%\.dsh-zotero-flow\edge-profile,和你日常用的浏览器互不干扰)。

在这个窗口里完成学校登录(图书馆统一身份认证 / CARSI / WebVPN),登录状态会长期保留,之后每次取全文都复用它。

如果你的学校需要走 WebVPN 或 EZproxy 前缀,把前缀填进插件配置的 institutionProxy,例如:

institutionProxy: https://webvpn.example.edu.cn/http/

典型用法

对 agent 说:

帮我下 10.1038/nature12373 这篇,存到 Zotero 的「纳米测温」分类

agent 会:zotero_status 体检 → literature_lookup 拿元数据 → scholar_session 打开 DOI 落地页 → scholar_download 抓 PDF → zotero_save 归档。

中文库这类只能人工点击的:

从知网找「高熵合金 金属陶瓷」那篇,下载后存进 Zotero

agent 会打开知网检索页并把下载这一步交给你:你在弹出的窗口里点「下载全文」,然后 agent 用 scholar_download(不传 url)接管下载目录里新出现的 PDF,再 zotero_import_pdf 归档。

配置与使用边界

在 profile 的 cordis.patch.yml 里覆写(用户层补丁会在插件层之后生效):

- id: dsh-zotero-flow
  name: 'dsh-zotero-flow'
  config:
    zoteroPort: 23119        # Zotero 本地 HTTP 服务端口
    mailto: you@example.edu  # Crossref / Unpaywall 的「礼貌池」邮箱,建议填
    browserPath: ''          # 留空自动探测 Edge / Chrome
    browserProfileDir: ''    # 机构登录用的资料目录
    cdpPort: 9333            # 浏览器调试端口
    downloadDir: ''          # PDF 落盘目录
    institutionProxy: ''     # WebVPN / EZproxy 前缀
    proxyUrl: ''             # 插件自身 HTTP 抓取的出口代理(不影响浏览器)

使用时需要遵守几条边界:

  • Zotero 连接器只能归档到「当前选中的分类」或「最近使用过的分类」。要让文献进某个分类,应先在 Zotero 左侧点选那个分类,再让 agent 归档。归档时插件会调 updateSession 把目标分类落到条目上,Zotero 界面里选中的分类会跟着切过去,这是 Zotero 连接器协议本身的行为。
  • 全文权限来自用户的机构会话,不来自插件的 HTTP 请求。从 Node 进程直接 fetch 出版社页面通常只会拿到付费墙或登录页,要全文就必须走浏览器会话。
  • 附件必须带一个非空的来源 URL。Zotero 的 Zotero.Attachments.importFromNetworkStream 在 url 为空 / 缺失 / null 时直接抛异常,插件已做兜底处理。
  • 中文库基本没有可自动下载的 PDF 直链。知网、万方、ProQuest 学位论文、科学文库、读秀都是 JS 应用,插件改为「打开页面 → 用户点击 → 接管下载目录」。
  • 浏览器会被设成「PDF 一律下载」。Chromium 默认用内建阅读器显示 PDF,此时响应体既不进网络栈也落不了盘,CDP 根本拿不到字节。插件在自己的资料目录里把 plugins.always_open_pdf_externally 设为 true,PDF 直接进 downloadDir。
  • 已有条目补附件需要 Zotero 10+ 本地 API 与原生写入授权。连接器的 saveAttachment 仅适用于同次会话新建条目;已有条目通过本地 API 追加附件。自动导入先查重,复用已有父条目并保留分类,确认不存在才新建。

安全与测试

  • 优先提取当前文献的 PDF 直链,核对 DOI/PII,避免误取参考文献链接;没有直链的中文库仍由用户点击。
  • 成功后仅关闭插件创建的取全文页及仍停在原地址的关联文献页。失败、验证码和用户自行打开的登录页保留;浏览器和登录资料目录不关闭、不清理。
  • 浏览器已经下载的 PDF 复用原路径,不另存重复副本。saveAs 只用于从内存响应体新建文件。
  • 校验 PDF 文件头、常规文件类型及 128 MiB 上限;新建文件使用独占创建,拒绝覆盖已有文件或符号链接目标。
  • 参数只接受不含账号密码的 HTTP(S) URL;阻止 localhost、私网 IP 字面量和非网页协议。文档请求重定向同样检查。这不是完整 SSRF/DNS 重绑定防火墙:域名解析及浏览器子资源仍由浏览器/操作系统管理,机构 WebVPN 域名可正常使用。
  • CDP 仅使用本机地址,取消任意来源通配符,验证调试端点;Zotero 只接受 loopback IP,禁止跟随 HTTP 重定向。
  • 403、429 和检测到的人机校验停止自动下载及归档,不自动调用 Zotero 解析器换入口。页面检测为启发式,不能保证识别所有站点校验。
  • 单控制器拒绝重叠导航/取全文操作,等待参数有明确上限。

离线回归测试:

npm test

默认测试全部使用模拟 CDP、fetch 和 Zotero,不启动真实浏览器、不联网、不写真实文献库。原联网体检移到 npm run selftest:integration,需要人工明确选择;浏览器/Zotero 写入自检同样不是默认测试的一部分。

人机配合的规矩

这个插件不是全自动爬虫。有三件事按规矩来:

  • 人机校验交给用户。页面出现验证码、滑块、点选或 Cloudflare 验证时,agent 会停下手上的步骤,请你在机构浏览器窗口里手工过一次,等你回话再继续。它不会自动识别验证码,也不会注入脚本伪装成人类。
  • 机构登录只提醒一次,之后复用。某个平台第一次需要机构登录时,agent 会提醒你在机构浏览器窗口登录你的学校(SSO / CARSI / WebVPN);之后同一个平台再取全文,它默认你已经登录好,先核实会话状态就直接继续,不会反复打断你。机构和平台的登录情况记在 %USERPROFILE%\.dsh-zotero-flow\institution-login-record.md(只记状态,不记密码、验证码、cookie 值或令牌)。
  • 不做反检测规避。站点起疑时(403 / 429 / 验证页)正确反应是放慢节奏、交给用户、如实说明,而不是想办法骗过检测:不注入脚本改写 navigator.webdriver 或指纹、不伪造 UA、不用打码服务、不伪造登录态。一次只处理一篇,不做批量抓取。

适用场景

  • 已有 Zotero 库,希望把机构数据库的文献自动拉入分类。
  • 需要在机构登录会话下批量获取全文,并自动归档元数据。
  • 希望用自然语言让智能体完成「检索 → 获取 → 归档」的完整流水线。

插件以当前 dsh 进程权限运行,安装前应检查源码与许可证(MIT)。它依赖 Node.js >= 22,在 DSH Desktop 环境中作为插件 bundle 加载。

结尾

dsh-zotero-flow 把「检索 → 获取 → 归档」这一整套流程用工具和技能固化下来,让智能体能按固定顺序调用,并在机构登录会话下获取全文。它不是全自动爬虫,需要人工过验证、保留浏览器窗口与登录状态,但通过查重与权限控制,能避免重复建条目与误取链接。

  • 目录页:https://www.skillhub.cn/plugins/YHzed/dsh-zotero-flow
  • GitHub:https://github.com/YHzed/dsh-zotero-flow
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye