scholar-tracing
ASecurityTrace a researcher from a Google Scholar profile link and build an interactive, bilingual (中文 / English) journal-style report — ego-centred co-author network, partner institutions / countries and the scholar's own affiliation history, research topics and how they shifted across phases of years, and a paper–topic network that identifies the research core, central papers and cross-topic bridge papers and explains why every two papers are linked. Use when the user gives a scholar.google.com/cita...
- 3 stars
- 0 votes
- 0 copies
- 1 view
- Added October 11, 2026
Works with
Security analysis
100/100Pro scans all 7 files and shows the line behind each finding
npx -y skills add wq2581/scholar-tracing --agent claude-codeAre you the author of scholar-tracing?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/wq2581-scholar-tracing)---
name: scholar-tracing
description: Trace a researcher from a Google Scholar profile link and build an interactive, bilingual (中文 / English) journal-style report — ego-centred co-author network, partner institutions / countries and the scholar's own affiliation history, research topics and how they shifted across phases of years, and a paper–topic network that identifies the research core, central papers and cross-topic bridge papers and explains why every two papers are linked. Use when the user gives a scholar.google.com/citations?user=... link or asks to analyse a researcher's collaborations, institutions, research trajectory or topics. 中文触发:谷歌学术链接、学术画像、合作网络、单位分布、研究演化 / 转变、研究主题网络、找研究中心。
---
# Scholar Tracing
Google Scholar profile → interactive report (single HTML file, Chinese and English versions with an in-page toggle).
Reply to the user in their language; the report itself is always built in both languages.
## How it works
```
Google Scholar ──► scholar.json paper list (source of truth), citations, h-index, sidebar co-authors
OpenAlex API ────► openalex.json full author lists, affiliations / countries, abstracts, keywords, references
report_template ─► report.html + report_en.html all analysis runs in the browser (no Python / Node):
TF-IDF + OpenAlex topic tags → consensus community-detection topics → dynamic-programming phases
→ paper network (similarity kNN + citations) → PageRank / betweenness
window.SCHOLAR_ANALYSIS ─► Claude writes insights.json (topic names, phase titles, takeaways in zh + en) ─► rebuild
```
Requires Windows PowerShell 5.1+ (or `pwsh`) and internet access. The report loads ECharts from cdnjs when viewed.
`<skill>` = this skill directory; `<out>` = `<working dir>/scholar_reports/<scholar_id>`. Run every script as
`powershell -ExecutionPolicy Bypass -File <skill>/scripts/<script> ...`.
## Steps
### 1. Fetch the Google Scholar profile
```
fetch_scholar.ps1 -Url "<profile link>" -Out <out>/scholar.json
```
Any link containing `user=<id>` works (`hl=`, `authuser=` etc. are ignored).
**Exit code 2 = blocked by Google** (CAPTCHA / 429). Fall back to the browser:
1. Open `https://scholar.google.com/citations?user=<id>&hl=en` in the built-in browser.
2. If a CAPTCHA appears, ask the user to solve it in the browser pane themselves — never solve it for them.
3. Run `await ` + the full text of `scripts/scholar_extract.js` with javascript_exec. It returns the JSON string; write it verbatim to `<out>/scholar.json`.
If it returns `LARGE: ...`, read `window.__SCH_STR.slice(i*40000,(i+1)*40000)` chunk by chunk and append each chunk with a Bash heredoc.
### 2. Find the OpenAlex author ID(s)
```
fetch_openalex.ps1 -Mode discover -Scholar <out>/scholar.json
```
It searches OpenAlex for the most-cited Scholar titles, keeps authors whose name matches, and checks each candidate by
**overlap** (Scholar titles found under that ID) and **purity** (overlap / works of that ID).
- Use `SUGGESTED_AUTHOR_IDS` (one person is often split across several OpenAlex IDs; they are listed together).
- **Do not** add `PARTIAL_IDS` — those are other people with the same name whose profiles absorbed a few of the papers; step 3 recovers those papers by title.
- No suggestion: skip `-AuthorIds` in step 3 (every paper is then matched by title), or try `-Mode search -Name "<name>" -Scholar <out>/scholar.json`.
- Two high-overlap IDs at very different institutions that may or may not be the same person: ask the user.
### 3. Download the OpenAlex works
```
fetch_openalex.ps1 -Mode works -AuthorIds <id1,id2> -Scholar <out>/scholar.json -Out <out>/openalex.json
```
Downloads the works of the IDs, then completes every Scholar paper still missing:
1. OpenAlex title search;
2. Crossref title search → DOI → OpenAlex by DOI (many "missing" papers are in OpenAlex under a slightly different title);
3. the paper's Google Scholar citation page (at most 40 per run, with pauses) → publisher link / DOI → OpenAlex by DOI;
4. otherwise Crossref (by DOI) or the citation page itself supplies full author names, venue and abstract (`details` in
openalex.json) — so patents and very new papers still get full names instead of Scholar initials.
The summary line reports how many papers were found by DOI, completed from details, and left title-only — tell the user.
`OPENALEX_API_KEY` / `OPENALEX_MAILTO` environment variables are used when set (the mailto also goes to Crossref).
### 4. Build the reports
```
build_report.ps1 -Dir <out>
```
Writes `<out>/report.html` (Chinese first) and `<out>/report_en.html` (English first); both have a 中文 / EN toggle and
`?lang=en|zh` also works. `-Lang zh|en -Out <file>` builds a single file. `insights.json` is injected when present.
### 5. Read the analysis and write insights.json
The preview pane cannot open large local files, so serve them over HTTP:
1. Add a configuration to `.claude/launch.json`: `"runtimeExecutable": "powershell"`, `"runtimeArgs": ["-ExecutionPolicy","Bypass","-File","<skill>/scripts/serve.ps1","-Root","<working dir>/scholar_reports","-Port","8765"]`, `"port": 8765`.
2. `preview_start` it and open `http://localhost:8765/<id>/report.html`.
3. Read `JSON.stringify(window.SCHOLAR_ANALYSIS)` with javascript_exec and check the console for errors.
`SCHOLAR_ANALYSIS` holds every topic (terms, OpenAlex topic, all titles), every phase (terms, rising / fading terms,
topic mix, co-authors, affiliation, representative papers), the network core, top co-authors, institutions, countries,
and **`qa` — automatic data-quality checks. Resolve every non-empty `qa` list before writing insights:**
| `qa` field | What to do |
|---|---|
| `suspicious_titles`, `non_research_items` | Scholar entries that are author lists, replies, corrections, editor's summaries… Exclude real non-papers with `exclude_papers`. |
| `author_mismatch`, `year_mismatch` | Compare the Scholar entry with the matched record. A different paper → `exclude_papers` it or tell the user; Scholar's own garbled author string → ignore. |
| `scholar_missing_from_byline` | The scholar was not found in the paper's authors (consortium author, name variant, wrong record). Check and mention in the chat if it matters. |
| `duplicate_names`, `initials_only_names` | Usually resolved automatically; persistent cases (an ambiguous "W Zhang") go to the chat. |
| `topic_outliers` | Papers closer to another topic's centre. Read the titles; move the ones that clearly belong elsewhere with `paper_topics`. |
| `own_affiliations` | Must be plausible against the Scholar profile; anything odd goes to the chat, never into the report. |
Topics come from consensus community detection on the paper-similarity network; the page offers the alternative topic
counts in `k_candidates` (the recommended one is `k`). Write `<out>/insights.json` with **both languages** for every text field:
```json
{
"k": 4,
"phases": 3,
"exclude_papers": ["<title or its beginning>"],
"paper_topics": {"<title or its beginning>": 0},
"summary": {"zh": "2–4 句:整体研究轨迹与当前重心", "en": "2–4 sentences: overall trajectory and current focus"},
"topic_labels": {"zh": ["主题 0 名称", "..."], "en": ["Topic 0 name", "..."]},
"topic_notes": {"zh": ["每个主题一句话"], "en": ["One sentence per topic"]},
"phase_titles": {"zh": ["阶段 1 标题", "..."], "en": ["Phase 1 title", "..."]},
"phase_notes": {"zh": ["每个阶段 1–2 句:做了什么、相对上一阶段转向了哪里"], "en": ["1–2 sentences per phase: what changed and why it matters"]},
"evolution_note": {"zh": "图 4 要点", "en": "Takeaway for Fig. 4"},
"collab_note": {"zh": "图 2 要点", "en": "Takeaway for Fig. 2"},
"inst_note": {"zh": "图 3 要点", "en": "Takeaway for Fig. 3"},
"network_note": {"zh": "图 5 要点", "en": "Takeaway for Fig. 5"}
}
```
- `k` and `phases` **must** equal `SCHOLAR_ANALYSIS.k` and `phases_count`; otherwise the report falls back to automatic labels.
- `topic_labels` are indexed by topic id. Make them specific (2–6 words naming object and method, e.g. "spatial transcriptomics × histology"), not a list of keywords.
- A plain string instead of `{"zh","en"}` is accepted but then shows in both languages — always write both.
- Write for the **report's readers** (the scholar, colleagues, committees), not for the person running the skill: describe the research only. Never mention data sources, parsing or matching problems, file names, tools or algorithms in insights — the report's Methods section already covers data and methods in plain words.
- Every statement must be traceable to `SCHOLAR_ANALYSIS`; never invent.
- If something in the data looks wrong (an implausible affiliation, a merged namesake), tell the user in the chat and fix it at the data level — never explain it inside the report.
- `paper_topics` moves clearly misplaced papers to the right topic (topic ids as in `SCHOLAR_ANALYSIS`; keys are a title or its
beginning). Read every topic's `titles` (start with `qa.topic_outliers`) and fix misfits *before* writing labels; topic keywords
are recomputed from the corrected membership. Papers that bridge two topics may stay where they are.
- `exclude_papers` drops Scholar entries that are not research papers (see `qa`); it changes all counts, so rebuild and re-read.
Rebuild with `build_report.ps1`, reload, and **re-read `SCHOLAR_ANALYSIS`** (corrections change counts), then fact-check before delivering:
1. **People** — every co-author is one node with the name printed in the bylines (no duplicates in `top_collaborators`, no
OpenAlex-only name variants); spot-check the top 15 against the Scholar profile's co-author list.
2. **Affiliations** — the scholar's own affiliations (`ego_affiliations`) are plausible against the Scholar profile; anything odd
goes to the chat, not into the report.
3. **Topics** — each title fits its topic label and note.
4. **Numbers** — every number and comparative claim in insights ("doubled", "most", "N papers with …") matches the rebuilt
analysis (per-year counts, phase sizes and mixes, collaborator counts, institution and country counts).
Then check that both pages have no console errors and look at Fig. 2 and Fig. 4 once in each language.
### 6. Deliver
- Give the paths of `report.html` and `report_en.html` (they open by double-click).
- Summarise in 5–8 lines: research core, how the phases shifted, main co-authors and institutions, data coverage.
- Offer in one line to publish it as a private Artifact for sharing.
## Report contents
Laid out like a journal article: masthead (name, affiliation, key-figure strip, summary) and five "Fig. N |" figures,
each with lowercase panel letters and a self-contained legend.
| Figure | Panels |
|---|---|
| Masthead | papers, citations, h-index, co-authors, institutions, countries, years, topics; summary (`summary`, auto-generated if absent) |
| Fig. 1 Output & impact | a papers per year; b citations per year; c core keywords (lollipop, colour = topic) |
| Fig. 2 Collaboration | a ego-centred force graph (colour by institution / country / first-collaboration phase, optional hiding of the scholar); b 15 most frequent co-authors; c new vs returning co-authors per year; click-through details |
| Fig. 3 Institutions | a top 15 partner institutions (colour = country); b countries; c institution × year heatmap; d institution types; e the scholar's own affiliations over time |
| Fig. 4 Evolution | a topic composition per year (stacked bars, shaded phases); b phase strip (topic mix, keywords, + emerging / − fading, representative papers, co-authors, affiliation); c topic table; topic and phase counts adjustable |
| Fig. 5 Paper network | a paper network (colour = topic, size = citations; grey = similarity kNN, red arrows = citations, optional dashed = shared co-authors); b topic-level network, core topic outlined; c top-10 PageRank; core / bridge statement above the figure; per-link reasons on click |
| Methods | data coverage, algorithms, limitations |
Graphics follow journal-figure conventions adapted from the nature-figure guidance in
[nature-skills](https://github.com/Yuan1z0825/nature-skills) (Apache-2.0; guidance only, no code copied):
- white background; Arial in figures, serif headings
- left and bottom axes only, no gridlines
- 0.6 px dark outlines on bars and nodes, frameless legends
- small bold panel letters
- a low-saturation blue / red / teal / gold / violet palette
The categorical palette passes colour-vision-deficiency checks (adjacent ΔE ≥ 9.5 under red–green simulation, ≥ 20 for normal vision; a separate set for dark mode). Re-validate if you change `--c1…--c8` at the top of `report_template.html`.
## Notes
- Keep `.ps1` files pure ASCII: Windows PowerShell 5.1 reads BOM-less scripts as ANSI, so non-ASCII text corrupts or breaks them.
- PowerShell variable names are case-insensitive (`$a` and `$A` are the same variable).
- Never `ConvertFrom-Json` raw OpenAlex works: abstract inverted indexes contain keys differing only by case, which PS 5.1 rejects. Works mode stores the raw text and the browser parses it.
- Scholar truncates long author lists ("..."). Papers not matched in OpenAlex only have a title (no abstract or affiliations) and are tagged "title only".
- Papers with more than 30 authors are excluded from the collaboration and institution statistics so that consortia do not swamp the network.
- Affiliations are checked against the raw byline text: OpenAlex sometimes matches one raw string ("Department of Health Outcomes …, College of Medicine, University of Florida") to unrelated institutions (Health Outcomes Solutions, Florida College, …). The report keeps only institutions whose names occur in the raw text (abbreviations such as "Univ." allowed); if none do, it uses institutions known from other bylines that occur in the text. Each raw string is matched on its own, footnote markers glued to words ("3University") are split off, and a match overlapping a longer one is dropped ("University of Florida College of Medicine" is the University of Florida, not "Florida College"). CJK raw text is left unchanged.
- Networks are laid out once and then pinned, so a dragged node stays where it is dropped (very large networks keep the live force layout).
- Co-authors are identified by their **byline names**, not by OpenAlex author records: OpenAlex often splits one person over several
records and sometimes files a person under someone else's record (byline "Zhangze Chen" under "Zhuo Chen"). Identical byline names
are one person; a shared record only joins compatible names ("J. Zhu" ~ "Jia Zhu"); Scholar initials ("Q Song") join the single
full name they fit. Names are shown as printed in the bylines (or as on the Scholar profile's co-author list).
Files in this skill
- README_EN.md
- SKILL.md
- scripts/build_report.ps1
- scripts/fetch_openalex.ps1
- scripts/fetch_scholar.ps1
- scripts/scholar_extract.js
- scripts/serve.ps1
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.