wos-paper-detail について
wos-paper-detail は、Web of Science の全レコードから論文メタデータを取得するスキルです。WoS 番号または URL を使ってレコードを開き、著者、抄録、キーワード、引用情報などを整理して表示します。
主な機能
- 01WoS 番号または URL でレコードを特定
- 02論文のメタデータを抽出
- 03抄録、キーワード、引用情報を取得
- 04結果を構造化して表示
活用シーン
- 01論文の書誌情報を整理
- 02論文の抄録、キーワード、引用数を確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ cookjohn/ wos-skills --skill wos-paper-detailインストール後、Claude Code で/wos-paper-detailを入力して読み込まれたか確認します。
詳細
WoS 論文詳細
WoS のフルレコードページに移動し、論文の包括的なメタデータを抽出します。
手順
ステップ 1:入力を解析する
以下のいずれかを受け取ります:
- WoS アクセッション番号:
WOS:000779183600001 - 完全な URL:
https://www.webofscience.com/wos/woscc/full-record/WOS:000779183600001
完全な URL が指定された場合は、WoS ID を抽出します。
ステップ 2:移動する
navigate_page({
url: "{BASE_URL}/wos/woscc/full-record/{WOS_ID}",
initScript: "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
})
ステップ 3:フルレコードデータを抽出する
async () => {
// Wait for full record to load
for (let i = 0; i < 30; i++) {
if (document.querySelector('[data-ta="FullRTa-fullRecordtitle-0"]')) break;
await new Promise(r => setTimeout(r, 500));
}
await new Promise(r => setTimeout(r, 1500));
// Check access
if (document.body.innerText.includes('Sign in') && !document.querySelector('[data-ta="FullRTa-fullRecordtitle-0"]')) {
return { status: 'login_required' };
}
// Helper: get value for a labeled field (h3 label -> parent's non-h3 children)
const getField = (label) => {
const h3 = [...document.querySelectorAll('h3')].find(h => h.textContent.trim() === label);
if (!h3) return '';
const parent = h3.parentElement;
const valueEls = [...parent.children].filter(el => el.tagName !== 'H3');
return valueEls.map(s => s.textContent?.trim()).join(' ').substring(0, 300) || '';
};
// Title
const title = document.querySelector('[data-ta="FullRTa-fullRecordtitle-0"]')?.textContent?.trim() || '';
// Authors
const authors = [...document.querySelectorAll('[data-ta^="SumAuthTa-DisplayName-author-en"]')]
.map(a => a.textContent?.trim());
// Abstract
const abstract = document.querySelector('div.abstract--instance')?.textContent?.trim() || '';
// Source/Journal - extract only journal name from the JCR sidenav component
let source = '';
const sourceSpan = document.querySelector('h3[data-ta="FullRTa-sourceLabel"]')?.parentElement?.querySelector('span.section-label-data');
if (sourceSpan) {
// The span contains app-jcr-sidenav with journal name + popup. Get first text content before "arrow_back"
const fullText = sourceSpan.textContent?.trim() || '';
source = fullText.split('arrow_back')[0].trim();
}
if (!source) {
source = document.querySelector('.summary-source-title-link')?.firstChild?.textContent?.trim() || '';
}
// DOI - try link first, fall back to h3 label extraction
const doiEl = document.querySelector('a[href*="doi.org"]');
const doi = doiEl?.textContent?.trim() || doiEl?.href?.replace(/.*doi\.org\//, '') || getField('DOI');
// Metadata fields
const volume = getField('Volume');
const issue = getField('Issue');
const pages = getField('Page');
const published = getField('Published');
const earlyAccess = getField('Early Access');
const docType = getField('Document Type');
const language = getField('Language');
const accessionNumber = getField('Accession Number');
const issn = getField('ISSN');
const eissn = getField('eISSN');
// Keywords - use parentElement.querySelectorAll('a') to get ALL keyword links
const getKeywords = (label) => {
const h3 = [...document.querySelectorAll('h3')].find(h => h.textContent.trim() === label);
if (!h3) return [];
return [...h3.parentElement.querySelectorAll('a')].map(a => a.textContent?.trim()).filter(Boolean);
};
const authorKeywords = getKeywords('Author Keywords');
const keywordsPlus = getKeywords('Keywords Plus');
// Categories
const researchAreas = getField('Research Areas');
const wosCategories = getField('Web of Science Categories');
// Citations - full record page uses FullRRPTa selectors, NOT stat-number selectors
const citedLinks = [...document.querySelectorAll('a[data-ta*="times-cited-count-link"]')];
// WOSCC link text is "992 In Web of Science Core Collection" - extract leading number
const extractNum = (text) => (text?.match(/^[\d,]+/) || ['0'])[0];
const wosccCited = extractNum(citedLinks.find(a => a.getAttribute('data-ta')?.includes('-WOSCC'))?.textContent?.trim());
const alldbCited = extractNum(citedLinks.find(a => a.getAttribute('data-ta')?.includes('-ALLDB'))?.textContent?.trim());
const mainCited = extractNum(citedLinks.find(a => /^\d/.test(a.textContent?.trim()))?.textContent?.trim());
const citedCount = wosccCited || mainCited || '0';
// References
const refsCount = document.querySelector('a[data-ta*="refCountLink"]')?.textContent?.trim() || '0';
// JIF - extract from JCR popup/sidenav text content
let jif = '', jifYear = '', jifFiveYear = '', jcrQuartile = '';
const jcrPopup = document.querySelector('[class*="journal-content"], app-jcr-sidenav');
if (jcrPopup) {
const jcrText = jcrPopup.textContent || '';
// Pattern: "Journal Impact Factor ™20242.8Five Year3.4"
const jifMatch = jcrText.match(/Impact Factor\s*(?:™|TM)?\s*(\d{4})\s*([\d.]+)/);
if (jifMatch) { jifYear = jifMatch[1]; jif = jifMatch[2]; }
const fyMatch = jcrText.match(/Five Year\s*([\d.]+)/);
if (fyMatch) jifFiveYear = fyMatch[1];
// Quartile: "159/316 Q3" pattern in JCR summary
const qMatch = jcrText.match(/\d+\/\d+\s*(Q[1-4])/);
if (qMatch) jcrQuartile = qMatch[1];
}
// Full text links
const ftLinks = [...document.querySelectorAll('a[data-ta^="FRLinkTa"]')].map(a => ({
text: a.textContent?.trim()?.replace(/open_in_new/g, '').trim(),
href: a.href
})).filter(l => l.text);
return {
status: 'ok',
title, authors, abstract, source, doi,
volume, issue, pages, published, earlyAccess,
docType, language, accessionNumber, issn, eissn,
authorKeywords, keywordsPlus,
researchAreas, wosCategories,
citedCount, alldbCited, refsCount,
jif, jifYear, jifFiveYear, jcrQuartile,
ftLinks
};
}
ステップ 4:結果を提示する
出力を構造化された要約として整形します:
## {Title}
**Authors**: {authors joined by "; "}
**Source**: {source}, Vol. {volume}, Iss. {issue}, pp. {pages}
**Published**: {published}
**DOI**: {doi}
**Document Type**: {docType}
**WoS ID**: {accessionNumber}
### Abstract
{abstract}
### Keywords
- **Author Keywords**: {authorKeywords}
- **Keywords Plus**: {keywordsPlus}
### Metrics
- **Times Cited (WOSCC)**: {citedCount}
- **Times Cited (All DB)**: {alldbCited}
- **References**: {refsCount}
- **JIF ({jifYear})**: {jif} (Five Year: {jifFiveYear})
- **JCR Quartile**: {jcrQuartile}
### Classification
- **Research Areas**: {researchAreas}
- **WoS Categories**: {wosCategories}
- **ISSN**: {issn} | **eISSN**: {eissn}
### Full Text Links
{list of ftLinks}
次のアクションを提案します:
- 「
/wos-export {WoS ID}を使ってこの論文をエクスポートします」 - 「
/wos-download {WoS ID}を使って PDF をダウンロードします」
主な CSS セレクター(フルレコードページ)
| 要素 | セレクター | 備考 |
|---|---|---|
| タイトル | [data-ta="FullRTa-fullRecordtitle-0"] | |
| 著者 | [data-ta^="SumAuthTa-DisplayName-author-en"] | |
| 抄録 | div.abstract--instance | |
| ソースラベル | h3[data-ta="FullRTa-sourceLabel"] | 親の span には JCR ポップアップがあるため、"arrow_back" で分割します |
| DOI | a[href*="doi.org"] | |
| 著者キーワード | h3#FRkeywordsTa-authorKeywordsLabel → 親の a タグ | parentElement.querySelectorAll('a') を使用します |
| Keywords Plus | 「Keywords Plus」ラベルと同じパターン | |
| 被引用数(WOSCC) | a[data-ta*="times-cited-count-link-WOSCC"] | フルレコードページのみ |
| 被引用数(全データベース) | a[data-ta*="times-cited-count-link-ALLDB"] | フルレコードページのみ |
| 参考文献 | a[data-ta*="refCountLink"] | フルレコードページのみ |
| メタデータフィールド | h3 ラベル → parentElement → h3 以外の子要素 | 巻、号、ページ、公開日など |
| JIF | app-jcr-sidenav 内のテキストコンテンツ | 正規表現:/Impact Factor\s*™?\s*(\d{4})\s*([\d.]+)/ |
| フルテキストリンク | a[data-ta^="FRLinkTa"] |
注意事項
- このスキルでは 2 回のツール呼び出しを使用します:
navigate_page+evaluate_script - 重要:フルレコードページでは、検索結果ページとは異なる被引用数セレクターを使用します:
- 検索結果:
a[data-ta="stat-number-citation-related-count"] - フルレコード:
a[data-ta*="times-cited-count-link-WOSCC"]
- 検索結果:
- JCR ポップアップの内容を取得しないように、ソースの抽出結果を "arrow_back" で分割する必要があります
- キーワードには
nextElementSiblingではなく、parentElement.querySelectorAll('a')を使用する必要があります - JIF は独立した要素ではなく、JCR サイドナビゲーションのポップアップテキスト内に埋め込まれています
コメント
Markdown 対応