import requestsimport timeimport osimport re# ================= 配置区 =================# 如果设为 True: 不仅会将 txt 中的文献加入 EndNote,还会把它们附带的几百条参考文献也拉取下来。# 如果设为 False: 只转换 txt 列表中的文献本身(非常适合纯文本参考文献列表的批量格式化)。FETCH_ITS_REFERENCES = True# ==========================================def get_doi_from_text(text): """ 智能识别:支持 DOI、文章题目、或是完整的纯文本参考文献(如 "[1] Yan M, Fan X...") """ text = text.strip() if not text: return None # 如果输入带 [1] 或 1. 这种前缀,先把它切掉,提高搜索准确率 text = re.sub(r'^(\[\d+\]|\d+\.\s*)', '', text).strip() # 如果文本直接是 DOI (例如 10.1038/s41467-020-14979-6) if re.match(r'^10\.\d{4,9}/[-._;()/:A-Za-z0-9]+$', text): return text # 如果是题目或文本参考文献,调用数据库搜索 print(f" 🔍 正在全球数据库中智能匹配: '{text[:45]}...'") url = "https://api.crossref.org/works" params = {"query.bibliographic": text, "rows": 1, "select": "DOI"} try: response = requests.get(url, params=params, timeout=10) if response.status_code == 200: items = response.json().get("message", {}).get("items", []) if items: return items[0].get("DOI") except Exception as e: pass return Nonedef get_references_by_doi(target_doi): """通过文章的 DOI,拉取其包含的所有参考文献""" url = f"https://api.crossref.org/works/{target_doi}" try: response = requests.get(url, timeout=15) if response.status_code == 200: return response.json().get("message", {}).get("reference", []) except Exception: pass return []def convert_doi_to_enw(doi): """将参考文献的 DOI 转换为 EndNote/RIS 标准格式""" url = f"https://api.crossref.org/works/{doi}/transform" headers = {'Accept': 'application/x-research-info-systems'} # 请求 RIS 格式 try: response = requests.get(url, headers=headers, timeout=10) if response.status_code == 200: return response.text except: pass return Nonedef main(): input_file = "target.Ref.txt" output_file = "Batch_All_References.ris" if not os.path.exists(input_file): print(f"❌ 找不到文件 '{input_file}'!请在当前目录下创建并填入数据。") return with open(input_file, 'r', encoding='utf-8') as f: target_list = [line.strip() for line in f if line.strip()] if not target_list: print(f"⚠️ '{input_file}' 是空的,请输入内容后重试。") return print(f"🚀 成功读取到 {len(target_list)} 条目标数据!准备开始批量处理...\n") # 初始化输出文件(清空旧数据) with open(output_file, "w", encoding="utf-8") as f: f.write("") total_targets_saved = 0 total_refs_saved = 0 for idx, target in enumerate(target_list): print(f"========== 正在处理第 [{idx+1}/{len(target_list)}] 项 ==========") target_doi = get_doi_from_text(target) if not target_doi: print(f"❌ 无法在数据库中找到该文献的记录,已跳过。\n") continue print(f" ✅ 锁定目标 DOI: {target_doi}") # --------------------------------------------------------- # 新增核心功能:将 txt 中的文献【本身】转换并加入 EndNote # --------------------------------------------------------- print(f" 📥 正在将目标文献本身写入文件...") target_ris = convert_doi_to_enw(target_doi) if target_ris: with open(output_file, "a", encoding="utf-8") as f: f.write(target_ris + "\n\n") total_targets_saved += 1 print(f" 🌟 目标文献本身已成功添加!") else: print(f" 🔴 目标文献本身转换失败。") time.sleep(0.3) # --------------------------------------------------------- # 根据配置决定是否拉取它引用的所有参考文献 # --------------------------------------------------------- if FETCH_ITS_REFERENCES: refs = get_references_by_doi(target_doi) if not refs: print(f" ⚠️ 数据库中没有该文献的引文列表数据,已跳过引文拉取。\n") continue print(f" 📚 找到它引用的 {len(refs)} 条参考文献,开始转换...") with open(output_file, "a", encoding="utf-8") as f: for i, ref in enumerate(refs): ref_doi = ref.get("DOI") if ref_doi: ris_data = convert_doi_to_enw(ref_doi) if ris_data: f.write(ris_data + "\n\n") f.flush() total_refs_saved += 1 print(f" [{i+1}/{len(refs)}] 🟢 引文转换成功") else: print(f" [{i+1}/{len(refs)}] 🔴 引文转换失败") else: print(f" [{i+1}/{len(refs)}] 🟡 无 DOI 数据,已跳过") time.sleep(0.3) print("\n") print("="*50) print(f"🎉 全部处理完成!") print(f"🏆 成功存入【txt目标文献本身】: {total_targets_saved} 条") if FETCH_ITS_REFERENCES: print(f"🏆 成功存入【连带的参考文献】: {total_refs_saved} 条") print(f"📁 结果已保存至: {output_file}") print(f"💡 您可以现在将 {output_file} 直接拖入 EndNote 中。") print("="*50)if __name__ == "__main__": main()