mcpField
W
wos-parse-results

wos-parse-results

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

wos-parse-results について

WoS Parse Resultsは、Web of Scienceの検索結果から構造化レコードを抽出する内部スキルです。検索APIのNDJSON応答を優先して解析し、APIにアクセスできない場合はDOMスクレイピングを代替手段として使います。

主な機能

  1. 01NDJSON API応答の解析
  2. 02構造化された検索レコードの抽出
  3. 03代替手段としてのDOMスクレイピング
  4. 04セレクターより構造化データを優先

活用シーン

  1. 01Web of Science API結果の処理
  2. 02表示中の検索結果ページからレコードを抽出

インストール

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

$npx skills add https://github.com/cookjohn/wos-skills --skill wos-parse-results

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

詳細

WoS 解析結果

WoS から構造化データを抽出するための内部スキルです。2 つのモードがあります。API レスポンスの解析(推奨)または DOM スクレイピング(フォールバック)です。

モード A:API レスポンスの解析(推奨)

runQuerySearch API を使用する場合、レスポンスは NDJSON です。records ペイロードからレコードを解析します。

// Parse NDJSON response text
const lines = text.trim().split('\n').map(l => { try { return JSON.parse(l); } catch(e) { return null; } }).filter(Boolean);
const searchInfo = lines.find(l => l.key === 'searchInfo')?.payload;
const recordsData = lines.find(l => l.key === 'records')?.payload;

const records = Object.entries(recordsData).map(([idx, rec]) => ({
  idx: parseInt(idx),
  wosId: rec.colluid,
  title: rec.titles?.item?.en?.[0]?.title || '',
  authors: rec.names?.author?.en?.filter(Boolean).map(a => a.wos_standard).join('; ') || '',
  source: rec.titles?.source?.en?.[0]?.title || '',
  year: rec.pub_info?.pubyear || '',
  vol: rec.pub_info?.vol || '',
  issue: rec.pub_info?.issue || '',
  pages: rec.pub_info?.page_no || '',
  doi: rec.doi || '',
  citations: rec.citation_related?.counts?.WOSCC || 0,
  citationsAll: rec.citation_related?.counts?.ALLDB || 0,
  refCount: rec.ref_count || 0,
  abstract: rec.abstract?.basic?.en?.abstract?.replace(/<[^>]*>/g, '') || '',
  docType: rec.doctypes?.[0] || '',
  oa: rec.oa || false
}));

モード B:DOM スクレイピング(フォールバック)

ブラウザーが検索結果ページを表示しており、API を利用できない場合:

async () => {
  for (let i = 0; i < 20; i++) {
    if (document.querySelector('app-record')) break;
    await new Promise(r => setTimeout(r, 500));
  }

  const records = [...document.querySelectorAll('app-record')].map((rec, idx) => {
    const titleEl = rec.querySelector('a[data-ta="summary-record-title-link"]');
    const title = titleEl?.textContent?.trim() || '';
    const href = titleEl?.href || '';
    const wosId = href.match(/WOS:\w+/)?.[0] || '';
    const authorEls = rec.querySelectorAll('a[data-ta*="DisplayName-author"]');
    const authors = [...authorEls].map(a => a.textContent?.trim()).join('; ');
    const sourceEl = rec.querySelector('a[data-ta="jcr-link-menu"]');
    const source = sourceEl?.textContent?.trim()?.replace('arrow_drop_down', '') || '';
    const citedEl = rec.querySelector('a[data-ta="stat-number-citation-related-count"]');
    const citations = citedEl?.textContent?.trim() || '0';
    return { idx: idx + 1, title, wosId, authors, source, citations };
  });

  return { status: 'ok', recordCount: records.length, records };
}

注意事項

  • モード A を常に優先します。構造化された JSON を使用するため、セレクターが不安定になりません。
  • API にアクセスできず、すでに検索結果ページを表示している場合は、モード B をフォールバックとして使用します。
  • 遅延読み込みや動的レンダリングにより、DOM セレクターでレコードを取得できないことがあります。

コメント