#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 文献质量评估报告生成器 功能: 1. 交互式生成单篇文献评估报告 2. 批量生成多篇文献评估报告 3. 自动计算部分分数(时效性、信源权威性) 4. 手动输入其他维度分数 5. 生成标准OFM格式评估报告 使用方式: python 质量评估报告生成器.py # 交互式单篇评估 python 质量评估报告生成器.py --batch # 批量评估(从文献库JSON读取) python 质量评估报告生成器.py --help # 查看帮助 """ import sys import os import json import argparse from datetime import datetime from pathlib import Path # 配置路径 BASE_DIR = Path(__file__).parent.parent LIBRARY_DIR = BASE_DIR / "文献库" LIBRARY_JSON = LIBRARY_DIR / "文献索引数据库.json" OUTPUT_DIR = BASE_DIR / "文献库" class QualityAssessment: """文献质量评估系统""" def __init__(self): self.current_year = datetime.now().year self.assessment_dimensions = { "timeliness": {"name": "时效性", "max_score": 15}, "source_authority": {"name": "信源权威性", "max_score": 20}, "data_quality": {"name": "数据质量", "max_score": 20}, "method_rigor": {"name": "方法严谨性", "max_score": 20}, "empirical_basis": {"name": "实证基础", "max_score": 20}, "theoretical_framework": {"name": "理论框架", "max_score": 15}, "impact": {"name": "影响力", "max_score": 15} } def calculate_timeliness_score(self, year): """ 计算时效性分数(15分制) 规则: - 2026年(当年):15分 - 2025年:12分 - 2024年:9分 - 2023年:6分 - 2022年及以前:3分 """ age = self.current_year - year if age == 0: return 15 elif age == 1: return 12 elif age == 2: return 9 elif age == 3: return 6 else: return 3 def calculate_source_authority(self, source_info): """ 计算信源权威性分数(20分制) 规则: - Nature/Science/Cell:20分 - 顶刊/顶会(如Scientific Reports、Computers and Education、AIED):18分 - 一区期刊(如Frontiers系列、IEEE/ACM):16分 - 顶级会议(如arXiv预印本):16分 - ERIC/官方报告:18分 - 其他知名期刊:14分 - 未明确来源:12分 """ if not source_info: return 12 source_lower = source_info.lower() # 顶级期刊 if any(j in source_lower for j in ["nature", "science", "cell"]): return 20 # 顶刊/顶会 if any(j in source_lower for j in ["scientific reports", "computers and education", "aied", "eric"]): return 18 # 一区期刊/顶会 if any(j in source_lower for j in ["frontiers", "ieee", "acm", "arxiv", "preprint"]): return 16 # 官方报告/政策文件 if any(j in source_lower for j in ["report", "guidelines", "whitepaper"]): return 18 # 知名期刊 if any(j in source_lower for j in ["springer", "taylor", "elsevier", "sage"]): return 14 # 未明确来源 return 12 def input_score(self, dimension_key, auto_score=None): """ 交互式输入分数 Args: dimension_key: 维度键值 auto_score: 自动计算的分数(如有) Returns: int: 输入的分数 """ dim = self.assessment_dimensions[dimension_key] dim_name = dim["name"] max_score = dim["max_score"] if auto_score is not None: print(f"\n📊 {dim_name}({max_score}分):自动计算得 {auto_score} 分") confirm = input("是否确认?(Y/n,默认Y): ").strip().lower() if confirm != "n": return auto_score while True: try: score = int(input(f"📊 请输入 {dim_name} 分数(0-{max_score}分): ")) if 0 <= score <= max_score: return score else: print(f"❌ 分数必须在 0-{max_score} 之间,请重新输入!") except ValueError: print("❌ 请输入有效的数字!") def generate_single_assessment(self): """ 交互式生成单篇文献评估报告 """ print("\n" + "="*60) print("📚 文献质量评估报告生成器") print("="*60) # 输入基本信息 print("\n📝 第一步:输入文献基本信息") print("-"*60) paper_id = input("文献ID(如 Entry 1 输入 1,或留空自动编号): ").strip() title = input("文献标题: ").strip() authors = input("作者(多个作者用逗号分隔): ").strip() source = input("来源/期刊/会议: ").strip() year_str = input("发表年份(如 2025,留空默认当年): ").strip() pdf_path = input(f"PDF路径(相对于 {LIBRARY_DIR},如 PDFs/paper.pdf): ").strip() # 默认值处理 if not paper_id: # 自动生成ID(简单策略:使用时间戳) paper_id = f"auto-{datetime.now().strftime('%Y%m%d%H%M%S')}" year = self.current_year if not year_str else int(year_str) # 自动计算部分分数 print("\n📊 第二步:自动计算分数") print("-"*60) timeliness_score = self.calculate_timeliness_score(year) source_authority_score = self.calculate_source_authority(source) print(f"✅ 时效性分数:{timeliness_score}/15") print(f"✅ 信源权威性分数:{source_authority_score}/20") # 手动输入其他维度分数 print("\n📊 第三步:输入其他维度分数") print("-"*60) scores = { "timeliness": timeliness_score, "source_authority": source_authority_score, "data_quality": self.input_score("data_quality"), "method_rigor": self.input_score("method_rigor"), "empirical_basis": self.input_score("empirical_basis"), "theoretical_framework": self.input_score("theoretical_framework"), "impact": self.input_score("impact") } # 计算总分和质量等级 total_score = sum(scores.values()) quality_grade = self.calculate_quality_grade(total_score) # 输入核心发现与价值 print("\n📝 第四步:核心发现与价值(选填,可留空)") print("-"*60) key_findings = [] print("输入核心发现(留空结束,最多3条):") for i in range(1, 4): finding = input(f" {i}. ").strip() if not finding: break key_findings.append(finding) strengths = [] print("\n输入文献优势(留空结束,最多3条):") for i in range(1, 4): strength = input(f" {i}. ").strip() if not strength: break strengths.append(strength) limitations = [] print("\n输入文献局限(留空结束,最多3条):") for i in range(1, 4): limitation = input(f" {i}. ").strip() if not limitation: break limitations.append(limitation) # 输入适用场景与使用建议 print("\n📝 第五步:适用场景与使用建议(选填,可留空)") print("-"*60) use_cases = [] print("输入适用场景(留空结束,最多3条):") for i in range(1, 4): use_case = input(f" {i}. ").strip() if not use_case: break use_cases.append(use_case) recommendations = [] print("\n输入使用建议(留空结束,最多3条):") for i in range(1, 4): recommendation = input(f" {i}. ").strip() if not recommendation: break recommendations.append(recommendation) # 生成报告 report_content = self.generate_report_content( paper_id=paper_id, title=title, authors=authors, source=source, year=year, pdf_path=pdf_path, scores=scores, total_score=total_score, quality_grade=quality_grade, key_findings=key_findings, strengths=strengths, limitations=limitations, use_cases=use_cases, recommendations=recommendations ) # 保存报告 output_filename = f"论文质量评估-{paper_id}-{datetime.now().strftime('%Y%m%d')}.md" output_path = OUTPUT_DIR / output_filename with open(output_path, "w", encoding="utf-8") as f: f.write(report_content) print(f"\n✅ 评估报告已生成:{output_path}") print(f"✅ 总分:{total_score}/105,质量等级:{quality_grade}") return output_path def calculate_quality_grade(self, total_score): """ 根据总分计算质量等级 规则: - A+级:95分及以上 - A级:90-94分 - A-级:85-89分 - B+级:80-84分 - B级:70-79分 - B-级:60-69分 - C级:60分以下 """ if total_score >= 95: return "A+级" elif total_score >= 90: return "A级" elif total_score >= 85: return "A-级" elif total_score >= 80: return "B+级" elif total_score >= 70: return "B级" elif total_score >= 60: return "B-级" else: return "C级" def generate_report_content(self, paper_id, title, authors, source, year, pdf_path, scores, total_score, quality_grade, key_findings, strengths, limitations, use_cases, recommendations): """ 生成评估报告内容(OFM格式) """ # 构建评估维度表格 dimensions_table = "| 评估维度 | 满分 | 得分 | 说明 |\n" dimensions_table += "|---------|------|------|------|\n" for key, dim in self.assessment_dimensions.items(): dim_name = dim["name"] max_score = dim["max_score"] score = scores[key] # 添加说明 if key == "timeliness": note = f"发表年份:{year}" elif key == "source_authority": note = f"来源:{source}" else: note = "手动评估" dimensions_table += f"| {dim_name} | {max_score} | {score} | {note} |\n" dimensions_table += f"| **总分** | **105** | **{total_score}** | **质量等级:{quality_grade}** |\n" # 生成报告内容 content = f"""--- created: {datetime.now().strftime('%Y-%m-%d')} title: 论文质量评估 - {title} tags: [质量评估, {quality_grade}] source: {source} category: quality_assessment --- # 论文质量评估报告 ## 文献基本信息 | 字段 | 内容 | |------|------| | **文献ID** | {paper_id} | | **标题** | {title} | | **作者** | {authors} | | **来源** | {source} | | **年份** | {year} | | **PDF路径** | `{pdf_path if pdf_path else '未指定'}` | | **评估日期** | {datetime.now().strftime('%Y-%m-%d')} | --- ## 质量评估得分 {dimensions_table} --- ## 核心发现与价值 """ # 添加核心发现 if key_findings: for i, finding in enumerate(key_findings, 1): content += f"{i}. {finding}\n" else: content += "> 未提供核心发现\n" content += "\n" # 添加文献优势 if strengths: content += "### 优势\n\n" for i, strength in enumerate(strengths, 1): content += f"{i}. {strength}\n" content += "\n" # 添加文献局限 if limitations: content += "### 局限\n\n" for i, limitation in enumerate(limitations, 1): content += f"{i}. {limitation}\n" content += "\n" # 添加适用场景与使用建议 content += "---\n\n## 适用场景与使用建议\n\n" if use_cases: content += "### 适用场景\n\n" for i, use_case in enumerate(use_cases, 1): content += f"{i}. {use_case}\n" content += "\n" if recommendations: content += "### 使用建议\n\n" for i, recommendation in enumerate(recommendations, 1): content += f"{i}. {recommendation}\n" content += "\n" # 添加质量等级说明 content += "---\n\n## 质量等级说明\n\n" content += f"**本次评估总分:{total_score}/105**\n\n" content += f"**质量等级:{quality_grade}**\n\n" content += f"**评分标准**:\n" content += f"- A+级(≥95分):顶尖文献,可作为核心引用源\n" content += f"- A级(90-94分):高质量文献,可作为重要引用源\n" content += f"- A-级(85-89分):良好文献,可作为辅助引用源\n" content += f"- B+级(80-84分):合格文献,特定场景有用\n" content += f"- B级(70-79分):一般文献,谨慎使用\n" content += f"- B-级(60-69分):较差文献,尽量少用\n" content += f"- C级(<60分):低质量文献,不建议引用\n" return content def generate_batch_assessments(self): """ 批量生成多篇文献评估报告(从文献库JSON读取) """ print("\n" + "="*60) print("📚 批量文献质量评估") print("="*60) # 检查文献库JSON是否存在 if not LIBRARY_JSON.exists(): print(f"❌ 文献库文件不存在:{LIBRARY_JSON}") print("请先运行文献库管理器创建文献库。") return # 读取文献库JSON with open(LIBRARY_JSON, "r", encoding="utf-8") as f: library_data = json.load(f) if "entries" not in library_data: print("❌ 文献库格式错误:缺少 'entries' 字段") return entries = library_data["entries"] # 过滤未评估的文献 unassessed = [] for entry in entries: if "quality_assessment" not in entry or not entry["quality_assessment"]: unassessed.append(entry) if not unassessed: print("✅ 所有文献已评估完毕!") return print(f"\n📊 发现 {len(unassessed)} 篇未评估文献") print("-"*60) # 列出未评估文献 for i, entry in enumerate(unassessed[:10], 1): print(f"{i}. [{entry['id']}] {entry['title'][:60]}...") if len(unassessed) > 10: print(f"... 还有 {len(unassessed) - 10} 篇未显示") # 询问是否继续 confirm = input(f"\n是否开始批量评估前 {min(10, len(unassessed))} 篇文献?(Y/n,默认Y): ").strip().lower() if confirm == "n": return # 批量评估(限制前10篇,避免时间过长) for entry in unassessed[:10]: print(f"\n{'='*60}") print(f"📚 评估文献 [{entry['id']}]") print(f"{'='*60}") print(f"标题: {entry['title']}") print(f"作者: {entry['authors']}") print(f"来源: {entry['source']}") print(f"年份: {entry.get('year', '未知')}") # 自动计算分数 year = entry.get("year", self.current_year) timeliness_score = self.calculate_timeliness_score(year) source_authority_score = self.calculate_source_authority(entry.get("source", "")) print(f"\n✅ 自动计算:") print(f" - 时效性分数:{timeliness_score}/15") print(f" - 信源权威性分数:{source_authority_score}/20") # 简化版批量评估:只输入总分 print(f"\n📊 请输入其他维度分数(简化版,直接输入5个维度的平均分):") avg_score = input(" 数据质量/方法严谨性/实证基础/理论框架/影响力 的平均分(0-20): ").strip() try: avg_score = int(avg_score) if not (0 <= avg_score <= 20): print("❌ 分数无效,跳过此篇") continue except ValueError: print("❌ 输入无效,跳过此篇") continue scores = { "timeliness": timeliness_score, "source_authority": source_authority_score, "data_quality": avg_score, "method_rigor": avg_score, "empirical_basis": avg_score, "theoretical_framework": avg_score, "impact": avg_score } total_score = sum(scores.values()) quality_grade = self.calculate_quality_grade(total_score) # 生成简化版报告 report_content = f"""--- created: {datetime.now().strftime('%Y-%m-%d')} title: 论文质量评估-{entry['id']}-{entry.get('year', '')} tags: [质量评估, {quality_grade}, 批评估] source: {entry.get('source', '')} category: quality_assessment --- # 论文质量评估报告(简化版) ## 文献基本信息 | 字段 | 内容 | |------|------| | **文献ID** | {entry['id']} | | **标题** | {entry['title']} | | **作者** | {entry['authors']} | | **来源** | {entry.get('source', '')} | | **年份** | {entry.get('year', '')} | | **评估日期** | {datetime.now().strftime('%Y-%m-%d')} | --- ## 质量评估得分 | 评估维度 | 满分 | 得分 | 说明 | |---------|------|------|------| | 时效性 | 15 | {timeliness_score} | 发表年份:{year} | | 信源权威性 | 20 | {source_authority_score} | 来源:{entry.get('source', '')} | | 数据质量 | 20 | {avg_score} | 简化评估 | | 方法严谨性 | 20 | {avg_score} | 简化评估 | | 实证基础 | 20 | {avg_score} | 简化评估 | | 理论框架 | 15 | {avg_score} | 简化评估 | | 影响力 | 15 | {avg_score} | 简化评估 | | **总分** | **105** | **{total_score}** | **质量等级:{quality_grade}** | --- ## 简化评估说明 此报告为批量评估的简化版本,数据质量、方法严谨性、实证基础、理论框架、影响力五个维度采用相同的平均分评估。如需详细评估,请运行单篇评估模式。 --- **质量等级:{quality_grade}** **总分:{total_score}/105** """ # 保存报告 output_filename = f"论文质量评估-{entry['id']}-{datetime.now().strftime('%Y%m%d')}.md" output_path = OUTPUT_DIR / output_filename with open(output_path, "w", encoding="utf-8") as f: f.write(report_content) print(f"\n✅ 评估报告已生成:{output_path}") print(f"✅ 总分:{total_score}/105,质量等级:{quality_grade}") print(f"\n{'='*60}") print("✅ 批量评估完成!") print(f"{'='*60}") def main(): """主函数""" parser = argparse.ArgumentParser( description="文献质量评估报告生成器", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" 使用示例: python 质量评估报告生成器.py # 交互式单篇评估 python 质量评估报告生成器.py --batch # 批量评估(从文献库JSON读取) python 质量评估报告生成器.py --help # 查看帮助 """ ) parser.add_argument( "--batch", action="store_true", help="批量评估模式(从文献库JSON读取)" ) args = parser.parse_args() # 创建评估器实例 assessor = QualityAssessment() if args.batch: # 批量评估模式 assessor.generate_batch_assessments() else: # 交互式单篇评估模式 assessor.generate_single_assessment() if __name__ == "__main__": main()