paper-search-cli 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,142 @@
1
+ import axios from 'axios';
2
+ const EASYSCHOLAR_URL = 'https://www.easyscholar.cc/open/getPublicationRank';
3
+ const REQUEST_DELAY_MS = 500;
4
+ function easyScholarKey() {
5
+ const key = process.env.EASYSCHOLAR_KEY || process.env.PAPER_SEARCH_EASYSCHOLAR_KEY || '';
6
+ if (!key.trim()) {
7
+ throw new Error('EasyScholar API key not configured. Set EASYSCHOLAR_KEY with `paper-search setup EASYSCHOLAR_KEY`.');
8
+ }
9
+ return key.trim();
10
+ }
11
+ function uniqueJournals(journals) {
12
+ const seen = new Set();
13
+ const unique = [];
14
+ for (const journal of journals.map(item => item.trim()).filter(Boolean)) {
15
+ if (seen.has(journal))
16
+ continue;
17
+ seen.add(journal);
18
+ unique.push(journal);
19
+ }
20
+ return unique;
21
+ }
22
+ function stringValue(value) {
23
+ if (typeof value !== 'string')
24
+ return undefined;
25
+ const trimmed = value.trim();
26
+ return trimmed || undefined;
27
+ }
28
+ function extractZone(value) {
29
+ const text = stringValue(value);
30
+ const match = text?.match(/(\d+)区/);
31
+ return match?.[1];
32
+ }
33
+ function extractSmallZones(value) {
34
+ const text = stringValue(value);
35
+ if (!text)
36
+ return undefined;
37
+ const matches = [...text.matchAll(/([^/。;;]+?)([1-4])区/g)].map(match => `${match[1].trim()}${match[2]}区`);
38
+ return matches.length ? matches : undefined;
39
+ }
40
+ function normalizeOfficialRank(all) {
41
+ const casUpgraded = stringValue(all.sciUp);
42
+ const casBase = stringValue(all.sciBase);
43
+ const casSmall = stringValue(all.sciUpSmall);
44
+ const core = {
45
+ impact_factor: stringValue(all.sciif),
46
+ impact_factor_5y: stringValue(all.sciif5),
47
+ jcr_quartile: stringValue(all.sci),
48
+ ssci_quartile: stringValue(all.ssci),
49
+ jci: stringValue(all.jci),
50
+ cas_base: casBase,
51
+ cas_upgraded: casUpgraded,
52
+ cas_small: casSmall,
53
+ cas_top: stringValue(all.sciUpTop),
54
+ cas_zone: extractZone(casUpgraded) || extractZone(casBase),
55
+ cas_small_zones: extractSmallZones(casSmall),
56
+ esi: stringValue(all.esi),
57
+ warning: stringValue(all.sciwarn),
58
+ pku: stringValue(all.pku),
59
+ cssci: stringValue(all.cssci),
60
+ cscd: stringValue(all.cscd),
61
+ ahci: stringValue(all.ahci),
62
+ ccf: stringValue(all.ccf),
63
+ ei: stringValue(all.eii),
64
+ china_st_core: stringValue(all.zhongguokejihexin)
65
+ };
66
+ return Object.fromEntries(Object.entries(core).filter(([, value]) => value !== undefined));
67
+ }
68
+ function formatResult(journal, data, includeRaw) {
69
+ if (data.code !== 200 || data.msg !== 'SUCCESS' || !data.data) {
70
+ return {
71
+ journal,
72
+ status: 'not_found',
73
+ source: 'easyScholar',
74
+ message: data.msg || `EasyScholar returned code ${data.code ?? 'unknown'}`,
75
+ core: {}
76
+ };
77
+ }
78
+ const officialAll = data.data.officialRank?.all || {};
79
+ const officialSelect = data.data.officialRank?.select || {};
80
+ if (Object.keys(officialAll).length === 0) {
81
+ return {
82
+ journal,
83
+ status: 'not_found',
84
+ source: 'easyScholar',
85
+ message: 'No officialRank.all fields returned for this journal.',
86
+ core: {}
87
+ };
88
+ }
89
+ const row = {
90
+ journal,
91
+ status: 'found',
92
+ source: 'easyScholar',
93
+ core: normalizeOfficialRank(officialAll)
94
+ };
95
+ if (includeRaw) {
96
+ row.official_all = officialAll;
97
+ row.official_select = officialSelect;
98
+ row.custom_rank = data.data.customRank || {};
99
+ }
100
+ return row;
101
+ }
102
+ async function delay(ms) {
103
+ await new Promise(resolve => setTimeout(resolve, ms));
104
+ }
105
+ export async function queryJournalMetrics(options) {
106
+ const secretKey = easyScholarKey();
107
+ const journals = uniqueJournals(options.journals);
108
+ if (journals.length === 0) {
109
+ throw new Error('Provide at least one journal name.');
110
+ }
111
+ const rows = [];
112
+ for (let index = 0; index < journals.length; index += 1) {
113
+ const journal = journals[index];
114
+ try {
115
+ const response = await axios.get(EASYSCHOLAR_URL, {
116
+ params: {
117
+ secretKey,
118
+ publicationName: journal
119
+ },
120
+ timeout: 15000,
121
+ headers: {
122
+ 'User-Agent': 'Paper-Search-CLI/JournalMetrics'
123
+ }
124
+ });
125
+ rows.push(formatResult(journal, response.data, Boolean(options.includeRaw)));
126
+ }
127
+ catch (error) {
128
+ rows.push({
129
+ journal,
130
+ status: 'error',
131
+ source: 'easyScholar',
132
+ message: error?.message || String(error),
133
+ core: {}
134
+ });
135
+ }
136
+ if (index < journals.length - 1) {
137
+ await delay(REQUEST_DELAY_MS);
138
+ }
139
+ }
140
+ return rows;
141
+ }
142
+ //# sourceMappingURL=JournalMetricsService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JournalMetricsService.js","sourceRoot":"","sources":["../../src/services/JournalMetricsService.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paper-search-cli",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Agent-friendly CLI for searching and downloading academic papers from multiple sources.",
5
5
  "main": "dist/cli.js",
6
6
  "type": "module",
@@ -4,11 +4,13 @@ description: |
4
4
  学术文献检索与论文获取调度器,基于 paper-search CLI,而不是 MCP server。
5
5
  用于:搜索论文、查找相似研究、做文献综述初筛、验证 PMID/DOI、下载论文 PDF、
6
6
  调用 Crossref/OpenAlex/PubMed/PMC/Europe PMC/arXiv/bioRxiv/medRxiv/Semantic Scholar/CORE/OpenAIRE/DBLP/ACM/USENIX/OpenReview/IACR 等来源,
7
- 以及使用 Semantic Scholar Open Access snippet 索引检索论文正文片段中的方法学细节。
7
+ 使用 Semantic Scholar Open Access snippet 索引检索论文正文片段中的方法学细节,
8
+ 以及通过 EasyScholar 查询期刊影响因子、JCR/SSCI 分区、中科院分区、JCI、ESI、预警和等级指标。
8
9
  当用户提到“搜文献”“找论文”“文献检索”“search papers”“find papers”“literature search”
9
10
  “查一下有没有相关研究”“帮我找几篇参考文献”“看看别人怎么做的”“下载论文 PDF”
10
11
  “验证 PMID”“验证 DOI”“正文片段检索”“snippet search”“Methods 里怎么做的”
11
- “方法学细节检索”等任务时使用。
12
+ “方法学细节检索”“影响因子”“IF”“JCR 分区”“中科院分区”“期刊分区”
13
+ “期刊等级”“目标期刊指标”“journal metrics”等任务时使用。
12
14
  此 skill 只负责指导 agent 调用 paper-search CLI;API key 必须通过 paper-search setup、
13
15
  paper-search config、.env 或环境变量配置,绝不要写入 Skill 文件。
14
16
  ---
@@ -26,7 +28,7 @@ command -v paper-search
26
28
  paper-search status --pretty
27
29
  ```
28
30
 
29
- 如果涉及 Semantic Scholar 正文片段、CORE、Unpaywall、Web of Science、IEEE Xplore、Scopus、ScienceDirect、Springer/SpringerLink 或 Wiley 等需要 key/邮箱的能力,再运行:
31
+ 如果涉及 Semantic Scholar 正文片段、EasyScholar 期刊指标、CORE、Unpaywall、Web of Science、IEEE Xplore、Scopus、ScienceDirect、Springer/SpringerLink 或 Wiley 等需要 key/邮箱的能力,再运行:
30
32
 
31
33
  ```bash
32
34
  paper-search config doctor --pretty
@@ -37,6 +39,7 @@ paper-search config doctor --pretty
37
39
  ```bash
38
40
  paper-search setup
39
41
  paper-search config set SEMANTIC_SCHOLAR_API_KEY your_key
42
+ paper-search setup EASYSCHOLAR_KEY
40
43
  paper-search config doctor --pretty
41
44
  ```
42
45
 
@@ -87,6 +90,20 @@ paper-search run get_paper_by_doi --arg doi="10.xxxx/xxxxx" --pretty
87
90
  paper-search run search_semantic_scholar --json-args '{"query":"graph neural network medicine","maxResults":5,"year":"2020-2025"}' --pretty
88
91
  ```
89
92
 
93
+ ### 期刊指标查询
94
+
95
+ 当用户询问影响因子、JCR/SSCI 分区、中科院分区、JCI、ESI、预警、北大核心、南大核心、CSCD、A&HCI、CCF、EI 或目标期刊等级时,使用 EasyScholar 原生 CLI 工具,而不是通用论文检索。
96
+
97
+ ```bash
98
+ paper-search journal-metrics "Nature" "BMJ" --pretty
99
+ paper-search journal-metrics --file journals.txt --include-raw --pretty
100
+ paper-search run query_journal_metrics --json-args '{"journals":["Nature"],"includeRaw":true}' --pretty
101
+ ```
102
+
103
+ 返回时优先解释标准化的 `core` 字段:`impact_factor`、`impact_factor_5y`、`jcr_quartile`、`ssci_quartile`、`jci`、`cas_base`、`cas_upgraded`、`cas_small`、`cas_top`、`cas_zone`、`esi`、`warning`、`pku`、`cssci`、`cscd`、`ahci`、`ccf`、`ei`、`china_st_core`。如果需要完整字段,使用 `--include-raw` 并检查 `official_all`、`official_select`、`custom_rank`。
104
+
105
+ EasyScholar 文档要求每秒最多 2 次请求;批量查询时不要并发调用。
106
+
90
107
  ### 下载 PDF
91
108
 
92
109
  ```bash
@@ -107,6 +124,7 @@ paper-search run download_with_fallback --json-args '{"source":"crossref","paper
107
124
  | 计算机文献目录/会议元数据 | `dblp` | `acm`, `usenix`, `openreview`, `ieee` 需要 key |
108
125
  | 跨学科广覆盖 | `crossref` | `openalex`, `semantic` |
109
126
  | 开放获取全文发现 | `pmc`, `europepmc`, `core`, `openaire`, `unpaywall` | `download_with_fallback` |
127
+ | 期刊影响因子/分区/等级 | `journal-metrics` | `query_journal_metrics` |
110
128
  | 密码学 | `iacr` | `arxiv` |
111
129
  | 引用统计排序 | `semantic`, `crossref`, `openalex` | `webofscience`, `scopus` 需要 key |
112
130
  | 出版商/付费数据库 | `webofscience`, `ieee`, `scopus`, `sciencedirect`, `springer`/`springerlink`, `wiley` | 仅在 key 已配置时使用 |
@@ -190,7 +208,9 @@ paper-search run search_crossref --arg query="full paper title" --arg maxResults
190
208
  |---|---|
191
209
  | CLI 不存在 | 提示安装 `npm install -g paper-search-cli` |
192
210
  | API key 缺失 | 提示运行 `paper-search setup`;不要索要或保存 key |
211
+ | EasyScholar key 缺失 | 提示运行 `paper-search setup EASYSCHOLAR_KEY`;不要让用户在聊天中发送 SecretKey |
193
212
  | 429 限流 | 降低 `--max-results`,换平台,或提示配置可选 key |
213
+ | EasyScholar 批量查询 | 控制在每秒最多 2 次请求;优先使用单次 `journal-metrics` 多期刊输入,不要并发 |
194
214
  | 0 结果 | 放宽关键词,换英文同义词,换平台,或用 `--sources` 扩展 |
195
215
  | 下载失败 | 优先开放获取来源和 `download_with_fallback`,报告失败原因 |
196
216
  | 用户要求完整正文 | 先下载 PDF;再交给当前环境可用的 PDF/MinerU 解析流程 |
@@ -200,4 +220,3 @@ paper-search run search_crossref --arg query="full paper title" --arg maxResults
200
220
  - 不管理 Zotero、Obsidian 或其他文献库。
201
221
  - 不写论文正文,不做语言润色。
202
222
  - 不把 API key、token、cookie 写入 Skill、README 或回复。
203
- - 当前公开 CLI 不提供期刊 IF、JCR 分区或中科院分区查询;遇到这类请求时说明能力边界,除非用户另行指定本地私有工具。