Community研究與資料分析github.com

GreenWich-art/agent-skills

從 PMC 下載開放獲取生物醫學文獻 PDF,並支援離線求解 Proof-of-Work 驗證。觸發關鍵字:下載文獻 PDF, PMC PDF, 403/404 on PDF link, Preparing to download, reCAPTCHA 頁面, OA 全文, 補充檔案, 下載論文 PDF。

agent-skills 是什麼?

此技能專為 AI 代理(如 Claude Code、Cursor、Codex 等)設計,用於自動化下載 PubMed Central (PMC) 上的開放獲取 (OA) 生物醫學文獻 PDF。它實作了一套完整的降級策略,從最穩定的 EuropePMC 結構化全文 API 開始,逐步嘗試 Unpaywall 定位、PMC 的 Proof-of-Work (PoW) 離線求解下載、補充材料擷取,以及最終的出版社直鏈。核心功能在於離線求解 PMC 的 PoW 挑戰,透過分析挑戰頁面中的常數並計算符合難度要求的 nonce 值,以取得真正的 PDF 檔案。技能也詳細處理了 PMC 的限流機制(IP 等級限制與「一次機會」特性),並提供當路線被阻擋時的替代方案,例如透過 DOI 解析出版社官網直鏈,或在必要時使用瀏覽器工具以「列印為 PDF」的方式繞過 Cloudflare 保護。此外,技能還包含了嚴格的完整性校驗機制,確保下載的 PDF 檔案完整無損。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/GreenWich-art/agent-skills/tree/HEAD/skills/pmc-oa-pdf-fetch

Installed? Explore more 研究與資料分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

PMC / OA 文獻 PDF 獲取

適用前提

只用於開放獲取 (OA) 文獻(CC BY / CC BY-NC / CC BY-NC-ND 等)。不要用於繞過付費牆獲取訂閱制論文——那屬於規避版權保護。判斷 OA 狀態:Unpaywall 回傳 is_oa: true,或 EuropePMC 的 isOpenAccess: Y。

機構訂閱場景(重要補充)

使用者所在學校/單位訂閱了出版商資料庫時,人工單篇下載在授權範圍內完全合規,但需注意:

  • 校園網 / 機構 IP 段內:出版商認 IP 不認人,降級鏈第 5 級(出版社直鏈)通常直接回傳 200,Cloudflare 也不會攔截——此時本 skill 的現有管線可以直接拿到訂閱內容,無需任何登入邏輯。
  • 校外存取:優先使用學校提供的系統級 VPN(對腳本透明,設定一次即可);WebVPN(URL 改寫型代理)因各校改寫規則不同、且需攜帶 Session Cookie,本 skill 不做支援。
  • 不要寫 Shibboleth / OpenAthens 自動登入:需要本地儲存統一身份認證憑證,屬安全隱患;且各校 IdP 流程差異大,通用實作不可行。
  • 批次下載紅線:幾乎所有出版商的機構許可都區分「人工單篇下載」與 systematic/bulk downloading。即使有訂閱,腳本批次抓取也違反許可條款,可導致全校 IP 段被封禁。確有大規模全文挖掘需求時,應申請出版商的 TDM(文本挖掘)API(如 Elsevier TDM API、Springer Nature Meta API),走官方配額通道,而不是用本 skill 批次循環。

降級鏈(嚴格按順序)

優先級途徑命令 / 端點說明
1EuropePMC 結構化全文https://www.ebi.ac.uk/europepmc/webservices/rest/{PMCID}/fullTextXML最穩定。用於提取精確到二級標題的全文結構。回傳 JATS XML
2Unpaywall 定位 OA 位置https://api.unpaywall.org/v2/{DOI}[email protected]讀取 oa_locations[].url_for_pdf,直接給出 PDF 直鏈
3PMC PoW 求解下載scripts/pmc_pdf.py <PMCID> <out.pdf>見下文。獲取正文 PDF 的主力方案
4EuropePMC 補充材料https://www.ebi.ac.uk/europepmc/webservices/rest/{PMCID}/supplementaryFiles回傳 ZIP:原始圖片(gr1…=Figure 1…)+ 補充材料 PDF(mmc1.pdf)
5出版社直鏈各出版社 .../article-pdf/...通常 403(Cloudflare)。最後才試

已確認失效的端點(不要浪費時間)

  • …/rest/{PMCID}/fullTextPDF → 404(已廢棄)
  • …/rest/{PMCID}/fulltextRepo → 403
  • https://europepmc.org/articles/{PMCID}?pdf=render → 403
  • https://europepmc.org/backend/ptpmcrender.fcgi?accid=…&blobtype=pdf → 403
  • https://www.ncbi.nlm.nih.gov/pmc/utils/oa/oa.fcgi?id=… → 404(OA service 已遷移)
  • ashpublications.org 文章頁在無頭瀏覽器中停留於 Cloudflare「請稍候…」挑戰頁,不可用

★ 先決條件:PMC 的 PDF 檔案名稱不固定,必須先解析

https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/pdf/<檔案名稱>.pdf 中的檔案名稱隨期刊與年份變化,硬編碼 main.pdf 在多數情況下會 404。

實測期刊真實檔案名稱
Am J Hematolmain.pdf
Blood Advancesmain.pdf
HemaSphereHEM3-10-e70338.pdf
Am J HematolAJH-101-1790.pdf
Liver InternationalLIV-46-0.pdf
Haematologica111300.pdf(卷 111 + 起始頁 300,省略期刊縮寫)
Blood(NIH 作者稿)nihms-2192199.pdf

解析方法(按優先級;實測多例全部命中第 1 條)

  1. 文章頁 <meta name="citation_pdf_url" content="https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/pdf/XXX.pdf"> ← 最可靠
  2. grep -oE 'href="[^"]*?/pdf/[^"]+?\.pdf"' 取第一個命中
  3. 兜底 pdf/main.pdf

命名規律參考(不可依賴,僅用於人工判斷是否解析正確):Wiley 系 OA 常見 <期刊縮寫>-<印刷卷>-0.pdf(如 LIV-46-0.pdf);帶文章號時為 <期刊縮寫>-<卷>-<文章號>.pdf(如 HEM3-10-e70338.pdf);同刊常為 <縮寫>-<卷>-<起始頁>.pdf(如 AJH-101-1790.pdf);亦有「卷+起始頁、無期刊縮寫」變體(如 Haematologica 的 111300.pdf = 卷 111 + 起始頁 300)。

抓文章頁時務必丟棄 Cookie:用一個獨立的、不保留 Cookie 的請求去讀文章頁,PDF 請求仍必須從全新 Cookie 會話發起。若把文章頁產生的 ncbi_sid / ncbi_pinger 帶到 PDF 請求上,會被直接升級為 reCAPTCHA(實測)。scripts/pmc_pdf.py 已按此實作。

核心方案:離線求解 PMC Proof-of-Work

原理

https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/pdf/<檔案名稱>.pdf 會按風險策略在兩種挑戰頁之間切換:

  • PoW 頁(1817 位元組,標題 Preparing to download ...)→ 可離線求解,這是我們要的通道;
  • reCAPTCHA 頁(約 20 KB,標題含 reCAPTCHA)→ 無法離線求解。

觸發 PoW 而非 reCAPTCHA 的關鍵:使用簡約 UA,且不要在請求 PDF 之前存取文章頁。

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)

反例(會被升級為 reCAPTCHA,實測):

  • 完整 Chrome UA(…AppleWebKit/537.36 … Chrome/1xx.0.0.0 Safari/537.36)
  • 先 GET 文章頁(攜帶 ncbi_sid / ncbi_pinger)再請求 PDF

PoW 演算法(從 pow-*.js 反解,已確認)

PoW 頁內嵌四個常數:POW_CHALLENGE / POW_DIFFICULTY / POW_COOKIE_NAME / POW_COOKIE_PATH。

  1. 求最小非負整數 nonce,使得 sha256(challenge + str(nonce)).hexdigest() 的前綴等於 '0' * difficulty;
  2. 設定 Cookie:<POW_COOKIE_NAME> = challenge + "," + nonce(路徑為 POW_COOKIE_PATH);
  3. 攜帶該 Cookie 與 Referer: https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/ 重新請求 PDF 直鏈 → 應回傳 200 與 Content-Type: application/pdf。

典型 difficulty = 4(期望約 65536 次哈希,本地亞秒級完成)。

一鍵腳本

# 推薦:自動解析真實 PDF 檔案名稱(走 citation_pdf_url),再離線求解 PoW
python3 scripts/pmc_pdf.py PMC13575452 ./out.pdf

# 已自行解析出檔案名稱時可直接指定,跳過文章頁請求
python3 scripts/pmc_pdf.py PMC13575452 ./out.pdf --pdf-name LIV-46-0.pdf

# 靜默模式(只輸出結果行)
python3 scripts/pmc_pdf.py PMC13575452 ./out.pdf --quiet

腳本行為:先以簡約 UA、丟棄 Cookie 地請求文章頁解析真實 PDF 直鏈 → 再以全新 Cookie 會話冷請求該 PDF → 若直接得到 PDF 則儲存;否則解析 PoW 常數、求解、回填 Cookie 重試。 如需強制重取 challenge,重跑即可(腳本不落盤 Cookie,每次都是全新會話)。

★★ 兩條必須記住的硬規則(實測血淚教訓)

1. 第二個位置參數是輸出檔案完整路徑,不是目錄。 傳目錄會在已經拿到 PDF 之後拋 IsADirectoryError: [Errno 21] Is a directory,前面那次 PoW 白解、那份 PDF 白拿。 ❌ pmc_pdf.py PMC13482240 --outdir /path/to/dir  ✅ pmc_pdf.py PMC13482240 /path/to/dir/xxx.pdf

2. PMC 的 PDF 通道有「一次機會」特性。 首次冷請求基本都能走通 PoW 並拿到真 PDF; 緊接著對同一 PDF 再請求一次,幾乎必然升級為 reCAPTCHA(不是「換 UA 就好」的普通限流)。 因此第一次就要把輸出路徑寫對,絕對不要「先試跑看看」。 實測:首輪 status=200 type=application/pdf bytes=23970819,數秒後重跑同一 URL 即變為 type=text/html bytes=21329(reCAPTCHA 挑戰頁)。 一旦浪費掉這次機會,直接跳到下一節的「出版社官網降級路線」,不要在 PMC 上反覆重試。

故障排查

現象原因處置
回傳 HTML 且含 POW_CHALLENGE進入了 PoW 通道(正常)交給腳本求解
回傳 HTML 且含 recaptcha被升級為 reCAPTCHA換簡約 UA、清會話 Cookie、稍等重試;仍失敗則改用途徑 4/5
404 / 「Article not found」PDF 檔案名稱猜錯了回到文章頁解析 citation_pdf_url,不要硬編碼 main.pdf
nonce 長時間不收斂difficulty 被調高列印 difficulty 判斷;>5 時考慮非同步或多進程求解
求解成功但 PDF 仍是 HTMLCookie 域 / 路徑不匹配確認 Cookie 域為 pmc.ncbi.nlm.nih.gov、路徑取 POW_COOKIE_PATH
IsADirectoryError: Is a directory把輸出參數當成了目錄第二參數是輸出檔案完整路徑。此時 PDF 其實已經拿到了,只是沒落盤——不要立刻重跑(會觸發 reCAPTCHA),先改對路徑,若已升級則直接走出版社官網路線
首次成功、第二次立刻 reCAPTCHAPMC 對同一 PDF 路徑的「一次機會」限流見上文硬規則 2;放棄 PMC,走出版社官網降級路線
citation_pdf_url 回傳 -mmc1.pdf該文 PDF 未入庫,解析到的是補充材料Blood 等刊常見「有 JATS 全文但正文 PDF 未入庫」。立刻放棄 PMC 路線,不要拿補充材料冒充正文(實測)

★ 存在 IP 級限流(實測) 短時間內對 PMC 重複請求 PDF(例如連續下載多篇)後,即使使用正確的簡約 UA,也會被直接升級為 reCAPTCHA, 且等待 45 秒仍不恢復。表現為「首次成功、隨後全部失敗」。 處置: ① 批次下載時在兩次請求之間留出足夠間隔;② 一旦進入 reCAPTCHA 狀態,不要反覆重試(只會延長封禁), 改為先完成其他工作,或改用途徑 4(supplementaryFiles)與出版社直鏈;③ 若確有多篇需求,優先按需下載而非批次預熱。

★★ 降級路線:PMC 被 reCAPTCHA 卡死時改走出版社官網(實測有效)

當 PMC 直鏈兩次均被升級為 reCAPTCHA(IP 級限流,等待後仍不恢復)時,若目標刊是全 OA 刊,走出版社官網比繼續重試 PMC 更可靠:

UA="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
# 1) DOI 解析 → 觀察最終落到哪個出版社文章頁
curl -s -o /dev/null -w "final: %{url_effective}\nHTTP: %{http_code}\n" -A "$UA" -L "https://doi.org/<DOI>"
# 2) 在文章頁解析真實 PDF 直鏈
curl -s -A "$UA" "https://<publisher-article-page>" | grep -oiE '<meta name="citation_pdf_url"[^>]*>|href="[^"]*\.pdf[^"]*"' | sort -u | head
# 3) 帶 Referer 直取(出版社幾乎不校驗 Referer,但帶上更穩)
curl -sL --retry 3 -A "$UA" -e "$ARTICLE_PAGE" -o "$OUT" "$PDF_URL"

★★ 出版社頁被 Cloudflare 完全攔死時:用瀏覽器「列印為 PDF」(實測有效)

ashpublications.org(ASH 系期刊)本輪出現 Cloudflare 完全攔截, 此前「等 10 秒再 open」的經驗未能復現。有效替代路徑:

  1. 打開 PMC 全文頁(非 PDF),繞過出版社站點
  2. 用瀏覽器工具列印該頁為 PDF:agent-browser pdf
  3. reCAPTCHA 首次彈出時再執行一次 open 即可通過

判定要點:目標刊屬於 ASH / ScienceDirect 一類強 Cloudflare 防護時, 不要在 curl 上反覆重試——成功率低且會加深封禁,直接切瀏覽器通道。

  • 已驗證可行:Haematologica / Ferrata Storti —— doi.org/10.3324/haematol.2025.287698 → haematologica.org/article/view/12187 → haematologica.org/article/download/12187/78653 → 2.91 MB / 14 頁。
  • 不可行:仍受 Cloudflare 類挑戰攔截的出版社(ASH ashpublications.org、Wiley onlinelibrary.wiley.com/doi/pdfdirect/...、De Gruyter、Thieme)——這些只能回 PMC 通道或瀏覽器會話。
  • 前置判斷:只有全 OA / Gold OA 刊才值得試這條路線(訂閱刊會撞付費牆,禁止繞過)。

★ 完整性校驗:大檔案下載被中斷會導致 xref 損壞

curl 取 PDF 時若被 SIGTERM / 超時中斷,檔案頭仍是正常的 %PDF-1.6、體積也看似合理,但 pdfinfo 會報 Invalid XRef entry。因此下載後不能只看檔案頭與檔案大小,必須同時滿足:

head -c 8 "$OUT"                                  # %PDF-…
tail -c 32 "$OUT" | od -c | tail -3               # 應能看到 startxref … %%EOF
pdfinfo "$OUT" | grep -E "Pages|Page size"        # 頁數應與「卷期頁」推算一致

三者齊全才算完整;缺失則重新完整下載(加 --retry 3),不要拿損壞檔案交差。

補充材料與圖片

正文 PDF 受阻時,supplementaryFiles 端點仍通常可用,且內容往往正是隨文圖片與補充方法:

curl -sL -o sup.zip "https://www.ebi.ac.uk/europepmc/webservices/rest/PMC13049628/supplementaryFiles"
unzip -o sup.zip -d sup/

命名約定(Wiley / ASH 系):*-gr1…*-grN 對應 Figure 1…N,*-ga1 為圖形摘要,*-mmc1.pdf 為補充材料。

使用瀏覽器工具時

只有在需要點擊、登入或渲染 JS 頁面時才動用 agent-browser。純下載場景不要啟動瀏覽器—— PoW 可離線求解,啟動 Chromium 只增加數百 MB 開銷與失敗面。若確需瀏覽器:

  • 必須先把可用的 node 加入 PATH(否則 daemon 啟動逾時);
  • 任務結束務必 agent-browser close,避免殭屍 daemon。

複核清單

  • 下載前確認目標文獻為 OA(或確認當前處於機構訂閱 IP 段內——此情形下出版社直鏈可直接用, 但仍僅限人工量的單篇下載,禁止批次)
  • 從文章頁 citation_pdf_url 解析出真實 PDF 檔案名稱(不要硬編碼 main.pdf)
  • 儲存後校驗檔案頭為 %PDF
  • 尾部校驗 startxref / %%EOF(大檔案被中斷會留下頭正常、xref 損壞的半成品;pdfinfo 能識別)
  • 核驗頁數:用 re.findall(rb'/Count\s+(\d+)', data) 或 /Type /Page 計數, 不要相信 file out.pdf 的頁數(macOS 上常誤報為 "1 pages");也可用 mdls -name kMDItemNumberOfPages
  • 抽首末頁核對內容(pdftotext -f 1 -l 1 / -f N -l N),確認不是補充材料或其它文章
  • 記錄 PMCID / DOI / 落盤路徑,便於後續複核
  • 未成功時如實說明失敗原因,不要以補充材料或圖片冒充正文 PDF

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

GreenWich-art/agent-skills

桌面 GUI 操作的统一编排入口。当用户要求操作一个只有图形界面的应用(改设置、点按钮、填表单、操作无 CLI/连接器的软件)时使用此 skill。提供四级能力:①路由决策——判断任务该走连接器、浏览器控制、Office 技能、命令行还是 computer use 桌面接管;②授权引导——检测并引导用户完成 macOS 辅助功能/屏幕录制权限授权,处理授权不生效等常见坑;③任务派发与验证——按目标/边界/失败处理三段式描述派发 GUI 任务,并以最终截图为准确认结果;④AX 兜底层——内置 axctl 工具做元素级无障碍读写(AXPress 语义点击,不碰鼠标不抢焦点),适用于 computer use 不可用或轻量场景。台前调度全场景实测(macOS 15 + 27.0.1 复检)。触发词:操控电脑、操作某个软件、点某个按钮、GUI 操作、电脑设置。

GreenWich-art/agent-skills

按学术论文规范(小三黑体一级标题/四号黑体二级/小四正文宋体1.5倍行距/三线表/中西文混排Times New Roman/统计量斜体) 批量重整 Markdown 或已有 docx 的格式。用户说"按学术格式排版""三线表""小三号黑体标题""1.5倍行距" "数字英文用Times New Roman""P值斜体"时使用。基于 python-docx 直接生成 docx,不走逐段插入。 不适用:高校课程论文/作业的字体字号约定(标准不同);党政机关公文国标 GB/T 9704 (又是另一套标准)。三套标准不可混用。

GreenWich-art/agent-skills

参考文献的 GB/T 7714-2015 著录规范化,以及 URL / DOI / PMID / PMC 链接的 可访问性批量核验与"假失效"识别。 触发场景: - 论文 / 综述 / 作业要交,需要核对参考文献格式 - "帮我按国标改一下参考文献" - 要交付一份文献清单,需要确认链接没死 - 已经有一堆 links,要批量验证哪些还能打开 含一个可复用脚本 `scripts/check_refs.py`,能自动判别 URL / DOI / PMID / PMC 并并发核验,且能区分「真死」与「被反爬」——后者不该判为失效。 不适用:从零生成一份带引文的正文(那是写作任务); Zotero 样式定制(见正文第六节,按需手工改 CSL)。

GreenWich-art/agent-skills

Local OCR using the macOS Vision framework. Triggers: OCR, 识别图片文字, 提取截图内容, 扫描件转文字, 图片转文字, 扫描版PDF转文字, read text from image/screenshot/photo/scanned PDF. Local-first and offline; prefer it over cloud OCR whenever data is sensitive or the machine is offline.

相關技能