mcpField
C
cnki-advanced-search

cnki-advanced-search

github.com/cookjohn生产力1.0k739 次安装33 周前更新
代码仓库

关于 cnki-advanced-search

用于按自然语言条件检索 CNKI 的技能,可组合主题、篇名、作者、来源、年份和来源类别筛选,并读取结果数量。

主要功能

  1. 01按字段解析检索条件
  2. 02组合作者、期刊与年份筛选
  3. 03选择 SCI、EI、CSSCI 等来源类别
  4. 04获取检索结果数量

适用场景

  1. 01限定年份和来源类别查找论文
  2. 02按作者或期刊缩小检索范围

MCP 相关

通过 Chrome DevTools MCP 导航 CNKI,并在页面中填写条件、执行检索和读取结果。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cookjohn/cnki-skills --skill cnki-advanced-search

安装后在 Claude Code 中输入/cnki-advanced-search确认已加载。

详细介绍

CNKI 高级检索

使用旧版高级检索界面在 CNKI 上执行筛选检索(这是唯一提供来源类别复选框的界面)。

参数

$ARGUMENTS 用自然语言描述检索条件。解析内容以识别:

  • 主题关键词(主题)——默认字段
  • 篇名关键词(篇名)
  • 关键词(关键词)
  • 作者姓名(作者)——独立字段 #au_1_value1
  • 期刊/来源(文献来源)——独立字段 #magazine_value1
  • 日期范围(时间范围)——#startYear / #endYear
  • 来源类别(来源类别:SCI、EI、北大核心、CSSCI、CSCD)

步骤

1. 导航

使用 mcp__chrome-devtools__navigate_page → https://kns.cnki.net/kns/AdvSearch?classid=7NS01R8M

2. 检索并获取结果(单次异步 evaluate_script)

将占位值替换为实际检索条件:

async () => {
  // --- Config: fill in actual values ---
  const query = "KEYWORDS";          // row 1 search keywords
  const fieldType = "SU";           // SU=主题, TI=篇名, KY=关键词, TKA=篇关摘, AB=摘要
  const query2 = "";                // row 2 keywords (optional, "" to skip)
  const fieldType2 = "KY";          // row 2 field type
  const rowLogic = "AND";           // AND=并且, OR=或者, NOT=不含 (between row 1 and 2)
  const sourceTypes = ["CSSCI"];    // any of: "SCI", "EI", "hx", "CSSCI", "CSCD" ([] = all)
  const startYear = "";             // e.g. "2020" or "" for no limit
  const endYear = "";               // e.g. "2025" or "" for no limit
  const author = "";                // author name or ""
  const journal = "";               // journal name or ""

  // --- Wait for form ---
  await new Promise((r, j) => {
    let n = 0;
    const c = () => { if (document.querySelector('#txt_1_value1')) r(); else if (n++ > 30) j('timeout'); else setTimeout(c, 500); };
    c();
  });

  // Captcha check
  const cap = document.querySelector('#tcaptcha_transform_dy');
  if (cap && cap.getBoundingClientRect().top >= 0) return { error: 'captcha' };

  const selects = Array.from(document.querySelectorAll('select')).filter(s => s.offsetParent !== null);

  // --- Source type: uncheck 全部, check targets ---
  if (sourceTypes.length > 0) {
    const gjAll = document.querySelector('#gjAll');
    if (gjAll && gjAll.checked) gjAll.click();
    for (const st of sourceTypes) {
      const cb = document.querySelector('#' + st);
      if (cb && !cb.checked) cb.click();
    }
  }

  // --- Row 1: field type + keyword ---
  selects[0].value = fieldType;
  selects[0].dispatchEvent(new Event('change', { bubbles: true }));
  const input = document.querySelector('#txt_1_value1');
  input.value = query;
  input.dispatchEvent(new Event('input', { bubbles: true }));

  // --- Row 2: field type + keyword (optional) ---
  if (query2) {
    selects[5].value = rowLogic; // row logic: AND/OR/NOT
    selects[5].dispatchEvent(new Event('change', { bubbles: true }));
    selects[6].value = fieldType2;
    selects[6].dispatchEvent(new Event('change', { bubbles: true }));
    const input2 = document.querySelector('#txt_2_value1');
    input2.value = query2;
    input2.dispatchEvent(new Event('input', { bubbles: true }));
  }

  // --- Author (optional) ---
  if (author) {
    const auInput = document.querySelector('#au_1_value1');
    if (auInput) { auInput.value = author; auInput.dispatchEvent(new Event('input', { bubbles: true })); }
  }

  // --- Journal (optional) ---
  if (journal) {
    const magInput = document.querySelector('#magazine_value1');
    if (magInput) { magInput.value = journal; magInput.dispatchEvent(new Event('input', { bubbles: true })); }
  }

  // --- Date range (optional) ---
  if (startYear) { selects[14].value = startYear; selects[14].dispatchEvent(new Event('change', { bubbles: true })); }
  if (endYear) { selects[15].value = endYear; selects[15].dispatchEvent(new Event('change', { bubbles: true })); }

  // --- Submit ---
  document.querySelector('div.search')?.click();

  // Wait for results
  await new Promise((r, j) => {
    let n = 0;
    const c = () => {
      if (document.body.innerText.includes('条结果')) r();
      else if (n++ > 40) j('timeout');
      else setTimeout(c, 500);
    };
    setTimeout(c, 2000);
  });

  // Captcha check again
  const cap2 = document.querySelector('#tcaptcha_transform_dy');
  if (cap2 && cap2.getBoundingClientRect().top >= 0) return { error: 'captcha' };

  return {
    query, fieldType, query2, fieldType2, rowLogic,
    sourceTypes, startYear, endYear, author, journal,
    total: document.querySelector('.pagerTitleCell')?.innerText?.match(/([\d,]+)/)?.[1] || '0',
    page: document.querySelector('.countPageMark')?.innerText || '1/1',
    url: location.href
  };
}
3. 报告

高级检索:“{query}”({fieldType})+ 来源:{sourceTypes} → {total} 条结果。

工具调用:2 次(navigate + evaluate_script)

已验证的选择器(旧版界面)

表单字段
元素选择器 / Select 索引说明
第 1 行字段类型selects[0]SU=主题,TI=篇名,KY=关键词,TKA=篇关摘,AB=摘要
第 1 行关键词#txt_1_value1主要关键词输入框
第 1 行行内第二个词#txt_1_value2与第一个关键词使用同一行的 AND/OR/NOT
第 1 行行内逻辑selects[2]AND=并含,OR=或含,NOT=不含
行间逻辑selects[5]AND=并且,OR=或者,NOT=不含
第 2 行字段类型selects[6]与第 1 行选项相同
第 2 行关键词#txt_2_value1第 2 行关键词
第 2 行行内第二个词#txt_2_value2
作者#au_1_value1占位提示“中文名/英文名/拼音”
作者单位#au_1_value2占位提示“全称/简称/曾用名”
文献来源#magazine_value1占位提示“期刊名称/ISSN/CN”
基金#base_value1
起始年份selects[14] / #startYear<select> 1915-2026
结束年份selects[15] / #endYear<select> 2026-1915
检索按钮div.search不是 input/button
来源类型复选框(来源类型)
来源复选框 ID说明
全部期刊#gjAll默认勾选,选择其他选项前需取消勾选
SCI 来源期刊#SCIvalue="Y"
EI 来源期刊#EIvalue="Y"
北大核心期刊#hxvalue="Y"
CSSCI#CSSCIvalue="Y"
CSCD#CSCDvalue="Y"

可同时勾选多个来源类型(OR 逻辑)。

结果
元素选择器说明
结果数.pagerTitleCell文本“共找到 X 条结果”
页码指示器.countPageMark文本“1/300”

验证码检测

检查 #tcaptcha_transform_dy 元素的 getBoundingClientRect().top >= 0。

重要说明

  • 必须使用旧版 URL(kns.cnki.net/kns/AdvSearch)。新版界面(kns8s/AdvSearch)没有来源类别复选框。
  • classid=7NS01R8M 参数可确保加载正确的表单布局。
  • 结果页兼容 cnki-parse-results 和 cnki-navigate-pages 技能。

评论

支持 Markdown