自动化文献检索与下载工作流 (Phase 3 逻辑树)

自动化文献检索与下载工作流 (Phase 3 逻辑树)

文档记录了当前工作流从启动到下载完成的端到端判断逻辑,按实际代码执行路径整理。

0. 启动入口

文件 : scripts/phase3_download_pipeline.py

  • 读取 .env 配置文件。
  • 解析终端参数(--keywords--research-direction 为必填项)。
  • 初始化 settings(用户目录、下载目录、浏览器配置)。
  • 调用 launch_persistent(settings) 启动持久化浏览器。

1. 浏览器启动判定

文件 : src/wos_rpa/browser.py

  • 1.1 启动 : 尝试执行 launch_persistent_context,使用 USER_DATA_DIR + BROWSER_CHANNEL + BROWSER_EXECUTABLE
  • 1.2 异常处理 :
    • 如果启动失败且命中 exitCode=21(Profile 锁冲突):
      • 自动执行 taskkill 强制关闭残留的 Edge/Chrome 进程。
      • 清理 Singleton* 相关的锁文件。
      • 重新尝试启动一次。
  • 1.3 彻底失败 : 如果重试仍然失败,抛出 RuntimeError,流程终止。

2. 进入 WoS 并搜索

  • 2.1 访问主页 : 执行 page.goto(WOS basic-search)
    • 成功则继续。
    • 失败(如遇到 ERR_CONNECTION_RESET) -> 保存 phase3_failure.png 截图 -> 流程终止。
  • 2.2 等待搜索框 (_wait_for_search_ready) :
    • 检测到搜索框 -> 继续下一步。
    • 未检测到搜索框:
      • 识别是否处于登录页,并尝试点击 institution access
      • 每 5 秒进行一次轮询检测。
      • 超过设定的最大等待时间 -> 报错结束。
  • 2.3 执行搜索 (_do_search) :
    • 模拟输入关键词。
    • 优先按下 Enter 键回车。
    • 发现 URL 未发生变化,则主动点击 Search 按钮作为兜底。

3. 列表抓取

文件 : src/wos_rpa/scraper.py

  • 3.1 等待结果加载 (wait_for_results_loaded) :
    • 优先寻找"卡片容器" DOM 元素。
    • 找不到则降级寻找"标题链接"元素。
    • 都找不到且超时 -> 报错结束。
  • 3.2 抓取模式选择 :
    • 模式A : 若 卡片数 >= 标题链接数 -> 采用卡片驱动抓取
    • 模式B : 否则采用标题链接驱动抓取
  • 3.3 字段提取 (每条数据) :
    • 提取 title (标题)、authors (作者)、abstract (摘要)。
    • 提取 detail_url (详情页链接,内部逻辑过滤掉 /author/ 等误抓链接)。
    • 提取 year (利用正则匹配 19xx/20xx,取出现的最大值)。

4. LLM 相关性判定

文件 : src/wos_rpa/llm_filter.py

对每一篇抓取到 titleabstract 的 paper 执行以下操作:

  • 4.1 调用 API (evaluate_paper_relevance_with_reason) :
    • 使用 OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL 请求大模型。
    • Prompt 强制要求返回 JSON 格式:{"relevant": bool, "reason": str}
  • 4.2 返回结果解析 :
    • relevant=False -> 直接跳过该论文。
    • relevant=True -> 该文献进入最终下载流程。
  • 4.3 API 失败分支 :
    • 遇到 429 频率限制或 overloaded 服务器过载 -> 触发指数退避自动重试
    • 返回 JSON 不合法 -> 抛错(注意:当前版本会直接中断整次 run 循环)

5. 下载总策略

对每篇被 LLM 判定为 relevant=True 的文献,执行"先 A 后 B"的降级下载策略:

A. 原站下载 (download_from_publisher)

  • A1 : 打开论文的 detail_url。若打开失败 -> 返回 None
  • A2 : 尝试点击 Publisher 入口(如 "Full Text at Publisher" 按钮)。若找不到 -> 返回 None
  • A3: 进入出版社独立页面(新 Tab 或同页),自动尝试点击接受 Cookies 的弹窗。
  • A4 : 通过多选择器机制查找 PDF 下载按钮。
    • 找到 : 触发 click_and_expect_download
      • 成功: 文件保存至 downloads/ 目录,按照 [year]-[first_author]-[title5].pdf 格式重命名,结束当前论文处理。
      • 失败: 拦截超时,进入兜底链 A5。
    • 未找到: 直接进入兜底链 A5。
  • A5 失败兜底链 :
    1. 保存当前页面的 Debug 截图(download_debug_*)。
    2. Vision API 视觉点击 (若 ENABLE_VISION_CLICK=true):
      • 新规则 : 若视觉大模型明确回复 found=false -> 立即返回 None (跳过处理下一篇)。
      • found=true 且成功返回坐标触发下载 -> 成功并返回路径。
    3. OCR 点击 (若 ENABLE_OCR_CLICK=true):
      • 新规则: 检测 Tesseract 是否可用,不可用自动跳过不崩溃。若成功点击并下载 -> 返回路径。
    4. 人工介入 (若 MANUAL_INTERVENTION=true):
      • 程序挂起,等待用户手动点击网页上的下载按钮,程序在后台拦截下载流。
    5. 若以上全部失败 -> 返回 None,准备执行策略 B。

B. Scholar 代偿 (download_from_scholar,仅当 A 返回 None 时触发)

  • B1 : 开启新 Tab 页进入 Google Scholar。
    • 自动检测 CAPTCHA 验证码。如果触发,挂起等待用户手动完成验证并回车。
  • B2 : 在学术搜索框内精确搜索 paper.title
    • 再次检测 CAPTCHA 验证码(必要时再次等待人工完成)。
  • B3 : 寻找搜索结果右侧的 [PDF] 直链标签。
    • 找到 : 触发 expect_download 进行直接下载。
    • 找不到: 进入兜底链 B4。
  • B4 失败兜底链 (逻辑同 A5) :
    1. 保存 Debug 截图。
    2. Vision API 视觉判定(found=false 直接跳过)。
    3. OCR 视觉点击。
    4. 人工点击介入。
    5. 最终彻底失败 -> 返回 None

6. 结果输出

  • 针对每一篇 relevant=True 的文献,在终端实时输出状态:
    • 原站成功 / 原站失败转 Scholar / Scholar 成功 / Scholar失败跳过
  • 遍历结束后,打印最终统计报告:相关文献通过数:N

相关推荐
Thomas.Sir2 小时前
第二章:Python3 之 列表与元组
python·列表·元组
不一样的故事1262 小时前
核心预测未来 10 年
运维·安全·自动化
忘忧记2 小时前
Fixture详解
开发语言·python
echome8883 小时前
Python 装饰器实战:用@syntax 优雅地增强函数功能
开发语言·python
路小雨~3 小时前
如何快速用测试用例来入门一个项目
python
不良人天码星3 小时前
GUI自动化基础(一)
python·ui·自动化
卷Java3 小时前
Python字典:键值对、get()方法、defaultdict,附通讯录实战
开发语言·数据库·python
七夜zippoe3 小时前
区块链开发:从智能合约到DApp
python·区块链·智能合约·开发·dapp
hhhjllhj3 小时前
如何用关键词优化报表提升网站流量?
python·搜索引擎·facebook
明月(Alioo)3 小时前
Python 并发编程详解 - Java 开发者视角
java·开发语言·python