科研写论文可以使用的skill.md以及引用覆盖率测试脚本
引用覆盖率测试
这个Python脚本可以检查bibtex和latex是否针对被引用文献完成了双向覆盖
# coding = utf-8
# Arch = manyArch
#
# @File name: check_biCoverRate.py
# @brief: LaTeX-BibTeX 双向覆盖率测试脚本
# 检测 .tex 文件中的 \cite{} 引用与 .bib 文件中的条目之间的覆盖率
# @attention: None
# @Author: wyb
# @History: 2026-07-29 Create
import re
import os
from pathlib import Path
from collections import Counter
# ============== 配置文件路径 ==============
TEX_FILE_PATH = "main.tex" # LaTeX 文件路径
BIB_FILE_PATH = "myref.bib" # BibTeX 文件路径
def extract_citations_from_tex(tex_path):
"""
从 .tex 文件中提取所有 \cite{} 命令中的引用键
Args:
tex_path: LaTeX 文件路径
Returns:
set: 所有引用键的集合
"""
citations = set()
if not os.path.exists(tex_path):
print(f"❌ 错误: LaTeX 文件不存在: {tex_path}")
return citations
with open(tex_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# 匹配 \cite{...} 模式,支持多个引用键(如 \cite{key1, key2})
# 同时支持 \citep{}, \citet{}, \citealp{} 等变体
cite_pattern = r'\\cite[a-z]*\*?\s*\{([^}]+)\}'
matches = re.findall(cite_pattern, content)
for match in matches:
# 分割多个引用键(用逗号分隔)
keys = [key.strip() for key in match.split(',')]
citations.update(keys)
return citations
def extract_entries_from_bib(bib_path):
"""
从 .bib 文件中提取所有条目的键
Args:
bib_path: BibTeX 文件路径
Returns:
set: 所有条目键的集合
"""
entries = set()
if not os.path.exists(bib_path):
print(f"❌ 错误: BibTeX 文件不存在: {bib_path}")
return entries
with open(bib_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# 匹配 @type{key, 模式
# 支持 @article{key, @book{key, @inproceedings{key, 等
entry_pattern = r'@\w+\s*\{\s*([^,\s]+)\s*,'
matches = re.findall(entry_pattern, content)
entries.update(matches)
return entries
def count_citations_in_tex(tex_path):
"""
统计 .tex 文件中每个引用键出现的次数
Args:
tex_path: LaTeX 文件路径
Returns:
Counter: 引用键及其出现次数
"""
citation_counts = Counter()
if not os.path.exists(tex_path):
return citation_counts
with open(tex_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
cite_pattern = r'\\cite[a-z]*\*?\s*\{([^}]+)\}'
matches = re.findall(cite_pattern, content)
for match in matches:
keys = [key.strip() for key in match.split(',')]
citation_counts.update(keys)
return citation_counts
def analyze_coverage(tex_path, bib_path):
"""
分析 LaTeX 和 BibTeX 之间的双向覆盖率
Args:
tex_path: LaTeX 文件路径
bib_path: BibTeX 文件路径
"""
print("=" * 60)
print("📊 LaTeX-BibTeX 双向覆盖率测试报告")
print("=" * 60)
print(f"📄 LaTeX 文件: {tex_path}")
print(f"📚 BibTeX 文件: {bib_path}")
print()
# 提取引用和条目
citations = extract_citations_from_tex(tex_path)
bib_entries = extract_entries_from_bib(bib_path)
# 统计引用次数
citation_counts = count_citations_in_tex(tex_path)
# 计算覆盖率
cited_in_bib = citations & bib_entries # 在 bib 中存在的引用
missing_in_bib = citations - bib_entries # 在 tex 中引用但不在 bib 中
unused_in_bib = bib_entries - citations # 在 bib 中存在但未被引用
# 打印统计信息
print(f"📈 统计信息:")
print(f" • LaTeX 中的引用键数量: {len(citations)}")
print(f" • BibTeX 中的条目数量: {len(bib_entries)}")
print(f" • 成功匹配的引用: {len(cited_in_bib)}")
print()
# 覆盖率
if len(citations) > 0:
coverage_rate = len(cited_in_bib) / len(citations) * 100
print(f"✅ 引用覆盖率: {coverage_rate:.1f}% ({len(cited_in_bib)}/{len(citations)})")
print()
# 报告缺失的 BibTeX 条目
if missing_in_bib:
print("=" * 60)
print(f"⚠️ 在 LaTeX 中引用但在 BibTeX 中缺失的条目 ({len(missing_in_bib)} 个):")
print("=" * 60)
for key in sorted(missing_in_bib):
count = citation_counts.get(key, 0)
print(f" ❌ {key} (引用 {count} 次)")
print()
print(f"💡 建议: 请在 BibTeX 文件中添加以上 {len(missing_in_bib)} 个缺失的条目")
print()
else:
print("✅ 所有引用都在 BibTeX 中存在!")
print()
# 报告未使用的 BibTeX 条目
if unused_in_bib:
print("=" * 60)
print(f"📝 在 BibTeX 中存在但未被 LaTeX 引用的条目 ({len(unused_in_bib)} 个):")
print("=" * 60)
for key in sorted(unused_in_bib):
print(f" ⚪ {key}")
print()
print(f"💡 建议: 可以考虑删除以上 {len(unused_in_bib)} 个未使用的条目以精简文献库")
print()
else:
print("✅ 所有 BibTeX 条目都被引用!")
print()
# 打印最常引用的条目
if citation_counts:
print("=" * 60)
print("🏆 最常被引用的条目 (Top 10):")
print("=" * 60)
for key, count in citation_counts.most_common(10):
status = "✅" if key in bib_entries else "❌"
print(f" {status} {key}: {count} 次")
print()
# 总结
print("=" * 60)
print("📋 总结:")
print("=" * 60)
if missing_in_bib:
print(f" 🔴 需要添加 {len(missing_in_bib)} 个 BibTeX 条目")
if unused_in_bib:
print(f" 🟡 可以删除 {len(unused_in_bib)} 个未使用的 BibTeX 条目")
if not missing_in_bib and not unused_in_bib:
print(" 🟢 LaTeX 引用与 BibTeX 条目完全匹配!")
print("=" * 60)
def main():
"""主函数"""
# 检查文件是否存在
if not os.path.exists(TEX_FILE_PATH):
print(f"❌ 错误: 找不到 LaTeX 文件: {TEX_FILE_PATH}")
print(" 请检查 TEX_FILE_PATH 配置是否正确")
return
if not os.path.exists(BIB_FILE_PATH):
print(f"❌ 错误: 找不到 BibTeX 文件: {BIB_FILE_PATH}")
print(" 请检查 BIB_FILE_PATH 配置是否正确")
return
# 执行覆盖率分析
analyze_coverage(TEX_FILE_PATH, BIB_FILE_PATH)
if __name__ == "__main__":
main()
寻找IEEE xplore参考文献的技能
需要首先配置fetch,playwright等mcp服务器
并且你的网络环境得支持访问并获取IEEE的论文,不然也是白搭
# IEEE xplore检索文章方法
当前网络已经具备企业环境,可以直接访问IEEE xplore的付费论文。你可以尝试使用fetch这个mcp工具,然后利用如下url尝试搜索关键词
```
https://ieeexplore.ieee.org/search/searchresult.jsp?newsearch=true&queryText=Diffusion%20Model%20Radar
```
捕获的页面包含检索列表,然后选择与任务相关的论文,尝试访问他们的请求,一般类似于
```
https://ieeexplore.ieee.org/document/10645014/
```
这种形式的链接。
你在获取论文后,可以阅读整个论文,也可以仅阅读摘要,然后判断是否相关。
你需要等待整个页面获取到后,通过“cite this”按钮获取bib格式的引用。如果缺失摘要,你需要将摘要补充到bib引用中。这个很重要,也就是修改完了,可能需要手动的将论文摘要补充到bib中
将所有新增的bib引用添加到当前论文的bib参考中。
如果cite this按钮无法交互,那么不添加bib,而是将当前论文的摘要,标题等信息,以及当前论文的url链接,追加到一个名叫`reference.md`的Markdown中。由人类稍后添加
你必须寻找到足够的论文才能结束任务。如果没有明确指定,那么默认找至少10篇论文。
不能用subagent模式,因为IEEE限制高并发,你应该亲自慢慢的寻找所有论文,而非通过写脚本或者子代理的方式批量寻找。
应该只寻找那些与主题相关的论文。如果你查看了一个关系不是很大的论文,那么这个论文不要被作为引用,并且也不能算作成功的找到了一个引用。
即使存储的是bib也应该附带当前论文的url。以便于人类验证。
注意!IEEE加载需要时间,并且需要jsp环境,也许得通过playwright之类的有头浏览器才能正常访问。
访问完成后需要等一下才能看见结果,如果你发现浏览器返回的内容是空白的,那么可以不急着刷新,也不要急着重新请求,而是重新获取一遍当前页面的信息,可能就有了。
不要尝试用bing等搜索方式,他们的效果很差,请不要心急,老老实实的慢慢查找IEEE论文即可。
不要编造不存在的论文信息
核验参考文献真实性
下面这个技能用于检查找到的参考引用是否真实,然而实测感觉效果一般
# IEEE论文验证法则
如果你的任务是验证引文是否存在,那么参考本文档。
bib和Markdown格式的一些内容可能是用户导出的,这部分内容无需查找,如果有必要,请主动询问用户从哪里开始检查。或者你可以看一下git提交情况,当前的未提交更改你可以认为就是新增的。只核查校准这些,其他的不管。
git查看diff的时候,注意应该让git一次在终端内输出所有差分信息,而非交互式的,否则会卡住agent loop的正常执行。例如使用指令`git --no-pager diff`增加一个参数即可。
reference.md是Markdown格式的引用论文
你需要做的:
不用subagent模式,亲自验证每个论文的url或者标题去搜索,都是确实存在并且相关的,而非编造存在的论文。
如果你想偷懒,可以将所有url放到一个Python脚本或者PowerShell脚本内,依次验证这些页面确实存在(获取返回信息并且查看他们,确定不是404之类的而是确实有内容。由于IEEE 需要jsp,因此直接curl可能内容就是空白的,得用其他方式)
如果你获取的页面是空的,可能得等一会,让浏览器完全渲染再尝试获取一次,而不是直接重新请求一次或者刷新页面,大概率只需要重新获取一次网页信息即可了。
但是请注意访问次数限制,因为IEEE禁止爬虫,因此即使是脚本的话,也请确保一个页面加载完成后等几秒再下一个。
