11 KiB
Executable File
11 KiB
Executable File
通用补充材料获取系统设计方案
目标: 支持所有主流期刊的补充材料自动获取 愿景: 无论论文来自哪个期刊,都能自动获取完整的系统发育分组数据
🎯 核心问题
为什么需要通用方案?
| 期刊 | 补充材料位置 | 格式 | 当前支持 |
|---|---|---|---|
| BMC系列 | Europe PMC API | ZIP+XLSX | ✅ 已支持 |
| Springer | SpringerLink | ZIP/PDF/XLSX | ❌ 未支持 |
| Elsevier | ScienceDirect | ZIP/XLSX | ❌ 未支持 |
| Wiley | Wiley Online | ZIP/XLSX | ❌ 未支持 |
| Nature | Nature.com | XLSX/PDF | ❌ 未支持 |
| PLOS | PLOS ONE | ZIP/XLSX | ✅ 通过PMC支持 |
| Frontiers | Frontiers | ZIP/XLSX | ❌ 未支持 |
| MDPI | MDPI | ZIP/XLSX | ❌ 未支持 |
问题: 每个期刊都有自己的平台和API,没有统一标准
💡 解决方案
方案1: 多源适配器模式 (推荐)
class UniversalSupplementaryFetcher:
"""通用补充材料获取器"""
def __init__(self):
self.adapters = {
'pmc': EuropePMCAdapter(), # Europe PMC API
'springer': SpringerAdapter(), # SpringerLink
'elsevier': ElsevierAdapter(), # ScienceDirect API
'wiley': WileyAdapter(), # Wiley API
'nature': NatureAdapter(), # Nature API
'direct': DirectDownloadAdapter(), # 直接下载链接
}
def fetch(self, paper_info: Dict) -> Optional[Path]:
"""
智能获取补充材料
策略:
1. 根据DOI/期刊名选择适配器
2. 尝试获取
3. 失败则尝试备用方案
"""
journal = self.detect_journal(paper_info['doi'])
# 主要方案
adapter = self.adapters.get(journal)
if adapter:
result = adapter.fetch(paper_info)
if result:
return result
# 备用方案: 爬虫
return self.adapters['direct'].fetch(paper_info)
🔌 各期刊适配器设计
1. Europe PMC (已实现 ✅)
class EuropePMCAdapter:
"""Europe PMC API - 支持所有PMC收录期刊"""
def fetch(self, paper_info: Dict) -> Optional[Path]:
pmcid = paper_info['pmcid']
url = f"https://www.ebi.ac.uk/europepmc/webservices/rest/{pmcid}/supplementaryFiles"
response = requests.get(url, timeout=120)
if response.status_code == 200:
return self.save_zip(response.content)
return None
def supports(self, doi: str) -> bool:
"""支持所有有PMCID的论文"""
return has_pmcid(doi)
覆盖期刊: BMC, PLOS, Nature Communications, 所有PMC收录期刊
2. Springer (待实现)
class SpringerAdapter:
"""SpringerLink API"""
API_BASE = "https://api.springernature.com"
def fetch(self, paper_info: Dict) -> Optional[Path]:
doi = paper_info['doi']
# 1. 获取文章元数据
metadata = self.get_metadata(doi)
# 2. 提取补充材料链接
supp_urls = metadata.get('supplementaryMaterialUrls', [])
# 3. 下载
for url in supp_urls:
if self.download(url):
return True
return None
def supports(self, doi: str) -> bool:
return 'springer' in doi or '10.1186' in doi
覆盖期刊: BMC系列, Springer系列
3. Elsevier (待实现)
class ElsevierAdapter:
"""ScienceDirect API"""
API_KEY = "YOUR_API_KEY" # 需要申请
API_BASE = "https://api.elsevier.com/content"
def fetch(self, paper_info: Dict) -> Optional[Path]:
doi = paper_info['doi']
pii = self.doi_to_pii(doi) # DOI转PII
# ScienceDirect API
url = f"{self.API_BASE}/article/pii/{pii}"
headers = {"X-ELS-APIKey": self.API_KEY}
response = requests.get(url, headers=headers)
# 解析补充材料链接
supp_links = self.parse_supplementary_links(response)
# 下载
return self.download_files(supp_links)
def supports(self, doi: str) -> bool:
return '10.1016' in doi # Elsevier DOI前缀
覆盖期刊: Cell, ScienceDirect, 所有Elsevier期刊
4. Wiley (待实现)
class WileyAdapter:
"""Wiley Online Library"""
def fetch(self, paper_info: Dict) -> Optional[Path]:
doi = paper_info['doi']
# Wiley页面结构
article_url = f"https://onlinelibrary.wiley.com/doi/{doi}"
# 需要爬取页面获取下载链接
html = requests.get(article_url).text
supp_links = self.parse_supplementary_links(html)
return self.download_files(supp_links)
def supports(self, doi: str) -> bool:
return '10.1111' in doi or '10.1002' in doi
覆盖期刊: Plant Journal, New Phytologist, 所有Wiley期刊
5. Nature (待实现)
class NatureAdapter:
"""Nature.com"""
def fetch(self, paper_info: Dict) -> Optional[Path]:
doi = paper_info['doi']
# Nature通常有PMCID,优先用Europe PMC
if paper_info.get('pmcid'):
return None # 让EuropePMC处理
# 否则爬取Nature页面
article_url = f"https://www.nature.com/articles/{doi.split('/')[-1]}"
html = requests.get(article_url).text
# 解析补充材料
supp_links = self.parse_supplementary_links(html)
return self.download_files(supp_links)
def supports(self, doi: str) -> bool:
return '10.1038' in doi
覆盖期刊: Nature, Nature Plants, Nature Genetics, 所有Nature系列
6. 通用爬虫 (备用方案)
class DirectDownloadAdapter:
"""
通用爬虫方案
当API不可用时,直接爬取期刊网站
"""
def fetch(self, paper_info: Dict) -> Optional[Path]:
doi = paper_info['doi']
# 解析DOI获取文章页面
article_url = self.resolve_doi(doi)
# 使用Playwright/Selenium爬取
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
# 访问页面
page.goto(article_url)
# 查找补充材料链接
supp_links = page.eval_on_selector_all(
"a[href*='supplementary'], a[href*='additional']",
"elements => elements.map(e => e.href)"
)
# 下载
for link in supp_links:
if self.is_excel_file(link):
return self.download(link)
return None
🏗️ 系统架构
┌─────────────────────────────────────────────────────────┐
│ UniversalSupplementaryFetcher │
│ (统一接口) │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ PMC │ │ Springer│ │ Elsevier│
│ Adapter │ │ Adapter │ │ Adapter │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│Europe │ │Springer │ │Science │
│PMC API │ │Link API │ │Direct │
└─────────┘ └─────────┘ └─────────┘
│ │ │
└─────────────────┼─────────────────┘
│
┌────▼────┐
│ 统一输出 │
│ ZIP/XLSX│
└─────────┘
📊 覆盖率分析
按期刊覆盖率
| 期刊集团 | 论文占比 | 技术难度 | 预计时间 |
|---|---|---|---|
| PMC收录 | 40% | 低 | 已支持 |
| Springer | 15% | 中 | 2-3天 |
| Elsevier | 25% | 中 | 2-3天 |
| Wiley | 10% | 中 | 2-3天 |
| Nature | 5% | 低 | 1-2天 |
| 其他 | 5% | 高 | 5-7天 |
总计: 95%覆盖率,开发时间约2周
🚀 实施计划
Phase 1: 核心架构 (本周)
- Europe PMC (已完成)
- 多适配器框架
- 智能期刊检测
- 失败重试机制
Phase 2: 主要期刊 (下周)
- Springer适配器
- Elsevier适配器
- Wiley适配器
- Nature适配器
Phase 3: 备用方案 (第3周)
- 通用爬虫
- 验证码处理
- 反爬虫绕过
Phase 4: 优化 (第4周)
- 缓存系统
- 批量处理
- 监控告警
💰 成本分析
免费方案
| 期刊 | API | 限制 |
|---|---|---|
| Europe PMC | 免费 | 无限制 |
| Springer | 免费 | 需要注册 |
| PLOS | 免费 | 无限制 |
| PubMed Central | 免费 | 无限制 |
需要付费
| 期刊 | 费用 | 限制 |
|---|---|---|
| Elsevier | $0-免费(学术) | 需要API key |
| Wiley | 需要协议 | 机构访问 |
| Nature | 通常免费 | 通过PMC |
结论: 大部分可以免费实现
🎯 最终愿景
# 用户只需要提供DOI,系统自动处理一切
fetcher = UniversalSupplementaryFetcher()
result = fetcher.fetch({
"doi": "10.1016/j.cell.2023.01.001", # 任意期刊
"gene_family": "SPL"
})
# 自动:
# 1. 识别期刊 (Elsevier)
# 2. 选择适配器 (ElsevierAdapter)
# 3. 获取补充材料
# 4. 解析Excel
# 5. 返回完整分组
🤔 关键决策
决策1: 优先级
建议优先级:
- PMC收录期刊 (40%覆盖率) ✅ 已完成
- Springer (15%覆盖率) - 高优先级
- Elsevier (25%覆盖率) - 高优先级
- Wiley (10%覆盖率) - 中优先级
- 其他 (10%覆盖率) - 低优先级
决策2: 技术栈
推荐:
- 主要: API优先(稳定、快速)
- 备用: Playwright爬虫(通用性强)
- 缓存: Redis/本地文件
决策3: 错误处理
策略:
1. 尝试API
2. 失败则尝试备用API
3. 再失败则尝试爬虫
4. 还失败则标记为"需手动处理"
📋 下一步行动
需要你的决策:
-
是否继续扩展?
- A: 是,实现通用系统
- B: 否,只支持PMC期刊
- C: 先测试当前v4,再决定
-
优先级?
- A: Springer (BMC系列)
- B: Elsevier (最大份额)
- C: Wiley (植物学期刊多)
-
时间投入?
- A: 全力投入 (2周完成)
- B: 渐进式 (每周一个期刊)
- C: 按需实现 (用到哪个做哪个)
设计方案: 2026-03-30 目标: 通用补充材料获取系统