mcpField
C
cnki-paper-detail

cnki-paper-detail

github.com/cookjohn生産性1.0k659 回インストール33 週間前に更新
リポジトリ

cnki-paper-detail について

CNKI の論文詳細ページからメタデータを抽出し、論文情報の整理や確認に使うスキルです。ページスクリプトで取得し、失敗時はアクセシビリティツリーを解析します。

主な機能

  1. 01タイトルと著者の抽出
  2. 02所属と抄録の取得
  3. 03キーワード・助成情報・分類番号の取得
  4. 04オンライン先行公開の検出
  5. 05ページ構造による解析への切り替え

活用シーン

  1. 01CNKI 論文の書誌情報の整理
  2. 02詳細ページから抄録とキーワードを収集
  3. 03認証後に論文情報の抽出を再開

MCP 対応

Chrome DevTools MCP で論文ページに移動し、認証を確認して、ページスクリプトの実行またはスナップショットの解析を行います。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/cookjohn/cnki-skills --skill cnki-paper-detail

インストール後、Claude Code で/cnki-paper-detailを入力して読み込まれたか確認します。

詳細

CNKI 論文詳細情報の抽出

CNKI の論文詳細ページからメタデータをすべて抽出します。

引数

$ARGUMENTS は CNKI の論文詳細 URL(kcms2/article/abstract を含む)を任意で指定します。指定されていない場合は、現在のページがすでに論文詳細ページであるものとします。

手順

1. 論文ページに移動する(URL が指定されている場合)

$ARGUMENTS に URL が含まれている場合:

  • URL を指定して mcp__chrome-devtools__navigate_page を使用します。
  • テキスト ["摘要"] とタイムアウト 15000 を指定して mcp__chrome-devtools__wait_for を使用します。
2. CAPTCHA を確認する

mcp__chrome-devtools__take_snapshot を使用します。「拖动下方拼图完成验证」が見つかった場合は、ユーザーに次のように知らせます。

CNKI にスライダー CAPTCHA が表示されています。Chrome ブラウザーで手動でパズルを完成させ、完了したら続行する旨をお知らせください。

3. JavaScript で論文のメタデータを抽出する

次の関数を指定して mcp__chrome-devtools__evaluate_script を使用します。

() => {
  const brief = document.querySelector('.brief');
  if (!brief) return { error: 'Paper detail section (.brief) not found' };

  // Title
  const title = brief.querySelector('h1')?.innerText?.trim()
    ?.replace(/\s*附视频\s*$/, '')  // remove "附视频" suffix
    ?.replace(/\s*网络首发\s*$/, ''); // remove "网络首发" suffix

  // Authors - first h3.author contains author links with sup tags
  const authorH3s = brief.querySelectorAll('h3.author');
  const authorSection = authorH3s[0];
  const authors = [];
  if (authorSection) {
    const authorLinks = authorSection.querySelectorAll('a');
    authorLinks.forEach(a => {
      const name = a.innerText?.replace(/\d+$/, '').trim();
      const supMatch = a.innerText?.match(/(\d+)$/);
      const affiliationNum = supMatch ? supMatch[1] : '';
      authors.push({ name, affiliationNum });
    });
  }

  // Affiliations - second h3.author contains org links
  const affiliations = [];
  if (authorH3s.length > 1) {
    const orgLinks = authorH3s[1].querySelectorAll('a');
    orgLinks.forEach(a => {
      affiliations.push(a.innerText?.trim());
    });
  }

  // Abstract
  const abstractEl = document.querySelector('.abstract-text');
  const abstract = abstractEl?.innerText?.trim() || '';

  // Keywords
  const keywordsP = document.querySelector('p.keywords');
  const keywords = keywordsP
    ? Array.from(keywordsP.querySelectorAll('a')).map(a => a.innerText?.replace(/;$/, '').trim())
    : [];

  // Fund
  const fundsP = document.querySelector('p.funds');
  const fund = fundsP?.innerText?.trim() || '';

  // Classification code
  const clcCode = document.querySelector('.clc-code');
  const classification = clcCode?.innerText?.trim() || '';

  // Journal/source
  const docTop = document.querySelector('.doc-top');
  const journal = docTop?.querySelector('a')?.innerText?.trim() || '';

  // Online first / publication info
  const headTime = document.querySelector('.head-time');
  const pubInfo = headTime?.innerText?.trim() || '';

  // Is online first?
  const isOnlineFirst = !!brief.querySelector('.icon-shoufa');

  // Article outline/TOC
  const catalogList = document.querySelector('.catalog-list, .catalog-listDiv');
  const toc = catalogList?.innerText?.trim() || '';

  // Citation network counts
  const citationTabs = document.querySelectorAll('ul.module-tab.tpl_lieteratures li');
  const citationInfo = {};
  citationTabs.forEach(li => {
    const id = li.getAttribute('data-id');
    const text = li.innerText?.trim();
    const countMatch = text.match(/(\d+)/);
    if (id) {
      citationInfo[id] = {
        label: text.replace(/\d+/, '').trim(),
        count: countMatch ? parseInt(countMatch[1]) : 0
      };
    }
  });

  return {
    title,
    authors,
    affiliations,
    abstract,
    keywords,
    fund,
    classification,
    journal,
    pubInfo,
    isOnlineFirst,
    toc,
    citationInfo
  };
}
4. 出力を整形して表示する
## {title} {isOnlineFirst ? "[网络首发]" : ""}

**Authors:**
{For each author: "- {name} ({affiliation})"}

**Affiliations:**
{For each affiliation: "- {affiliation}"}

**Journal:** {journal}
**Publication Info:** {pubInfo}

**Abstract:**
{abstract}

**Keywords:** {keywords joined by ", "}

**Fund:** {fund}
**Classification:** {classification}

**Citation Network:**
{For each citation type: "- {label}: {count}"}
5. フォールバック:スナップショットに基づく解析

JavaScript による抽出に失敗した場合は、mcp__chrome-devtools__take_snapshot を使用し、アクセシビリティツリーを解析します。

  • タイトル:レベル 1 の heading 要素
  • 著者:URL に kcms2/author/detail を含む link 要素
  • 所属機関:URL に kcms2/organ/detail を含む link 要素
  • 要旨:「摘要:」に続く StaticText
  • キーワード:URL に kcms2/keyword/detail を含む link 要素
  • 資金助成:「基金资助:」に続く link 要素
  • 分類:「分类号:」に続く StaticText

検証済み DOM セレクター

データセレクター備考
論文セクション.brief論文情報のメインコンテナー
タイトル.brief h1アイコンが含まれる場合があるため、テキストの整形が必要です
著者.brief h3.author:first-of-type aテキストには上付き番号が含まれます(例:「張三1」)
所属機関.brief h3.author:nth-of-type(2) aテキストは「N.」で始まります(例:「1.北京大学」)
要旨.abstract-text要旨全文
キーワードp.keywords aセミコロン区切りのキーワードリンク
資金助成p.funds資金助成情報のテキスト
分類.clc-codeCLC 分類コード
ジャーナル.doc-top a出典ジャーナルへのリンク
オンライン先行公開.brief .icon-shoufa論文がオンライン先行公開の場合に表示されます
引用タブul.module-tab.tpl_lieteratures lidata-id 属性が種類を識別します

コメント