9b395f5cc3
Build Chrome Extension / build (push) Waiting to run
Trigger Website Rebuild (Docs Updated) / dispatch (push) Waiting to run
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
93 lines
3.7 KiB
JavaScript
93 lines
3.7 KiB
JavaScript
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
import { CommandExecutionError } from '@jackwener/opencli/errors';
|
|
import { clampInt, requireNonEmptyQuery } from '../_shared/common.js';
|
|
|
|
cli({
|
|
site: 'google-scholar',
|
|
name: 'profile',
|
|
access: 'read',
|
|
description: 'View a Google Scholar author profile',
|
|
domain: 'scholar.google.com',
|
|
strategy: Strategy.PUBLIC,
|
|
browser: true,
|
|
args: [
|
|
{ name: 'author', positional: true, required: true, help: 'Author name or Scholar user ID (e.g. JicYPdAAAAAJ)' },
|
|
{ name: 'limit', type: 'int', default: 10, help: 'Max papers to show (max 20)' },
|
|
],
|
|
columns: ['rank', 'title', 'cited', 'year'],
|
|
func: async (page, kwargs) => {
|
|
const author = requireNonEmptyQuery(kwargs.author, 'author');
|
|
const limit = clampInt(kwargs.limit, 10, 1, 20);
|
|
|
|
const isUserId = /^[A-Za-z0-9_-]{12}$/.test(author);
|
|
if (isUserId) {
|
|
await page.goto(`https://scholar.google.com/citations?user=${author}&hl=en&sortby=citedby`);
|
|
} else {
|
|
await page.goto(`https://scholar.google.com/citations?view_op=search_authors&mauthors=${encodeURIComponent(author)}&hl=en`);
|
|
await page.wait(3);
|
|
|
|
const profileClicked = await page.evaluate(`(() => {
|
|
var link = document.querySelector('.gs_ai_pho, .gsc_oai_photo, a[href*="citations?user="]');
|
|
if (link) { link.click(); return true; }
|
|
return false;
|
|
})()`);
|
|
|
|
if (!profileClicked) {
|
|
throw new CommandExecutionError(`No profile found for: ${author}`);
|
|
}
|
|
}
|
|
|
|
await page.wait(3);
|
|
|
|
const data = await page.evaluate(`(() => {
|
|
var name = (document.querySelector('#gsc_prf_in') || {}).textContent || '';
|
|
var affiliation = (document.querySelector('.gsc_prf_il') || {}).textContent || '';
|
|
|
|
var stats = document.querySelectorAll('#gsc_rsb_st td.gsc_rsb_std');
|
|
var citations = stats[0] ? stats[0].textContent.trim() : '';
|
|
var hIndex = stats[2] ? stats[2].textContent.trim() : '';
|
|
var i10Index = stats[4] ? stats[4].textContent.trim() : '';
|
|
|
|
var papers = [];
|
|
var rows = document.querySelectorAll('#gsc_a_b .gsc_a_tr');
|
|
for (var i = 0; i < rows.length && i < ${limit}; i++) {
|
|
var titleEl = rows[i].querySelector('.gsc_a_at');
|
|
var citedEl = rows[i].querySelector('.gsc_a_ac');
|
|
var yearEl = rows[i].querySelector('.gsc_a_y span');
|
|
if (titleEl) papers.push({
|
|
rank: i + 1,
|
|
title: titleEl.textContent.trim(),
|
|
cited: citedEl ? citedEl.textContent.trim() : '0',
|
|
year: yearEl ? yearEl.textContent.trim() : '',
|
|
});
|
|
}
|
|
|
|
return {
|
|
name: name.trim(),
|
|
affiliation: affiliation.trim(),
|
|
citations: citations,
|
|
hIndex: hIndex,
|
|
i10Index: i10Index,
|
|
papers: papers,
|
|
};
|
|
})()`);
|
|
|
|
if (!data?.name) {
|
|
throw new CommandExecutionError(`Could not load Google Scholar profile for: ${author}`);
|
|
}
|
|
|
|
if (!data.papers || data.papers.length === 0) {
|
|
throw new CommandExecutionError(`No papers found for: ${data.name || author}`);
|
|
}
|
|
|
|
const summary = {
|
|
rank: 0,
|
|
title: data.name + (data.affiliation ? ' (' + data.affiliation + ')' : ''),
|
|
cited: 'h=' + data.hIndex + ' i10=' + data.i10Index + ' total=' + data.citations,
|
|
year: '-',
|
|
};
|
|
|
|
return [summary, ...data.papers];
|
|
},
|
|
});
|