Call the Python script (scripts/openalex_search.py) through OpenAlex open API to perform fully automated retrieval,
no institutional account required, no API key required, no browser required.
Dependency installation
pip install openpyxl
The OpenAlex API requires no registration, with a maximum of 10 requests per second; the script has built-in rate limiting.
Step 0: Parse input and formulate a search strategy
0.1 Keyword group design principles
Extract 2-3 core concept groupsfrom the research topic, expand synonyms within each group (separated by+ ), and take the AND intersection between groups.
Key note: The words used for filtering groups should be sufficientlyspecific, avoid using extremely broad words such as "meaning" and "identity" (which appear in all social science literature). Prefer compound phrases:
| Avoid (too broad) | Use instead (more specific) |
|---|---|
meaning |
meaning of work + work meaning + meaningful work |
identity |
occupational identity + worker identity + professional identity |
control |
labor control + algorithmic control + managerial control |
change |
livelihood change + occupational transition + career change |
Topic example: "Livelihood changes and meaning construction of ride-hailing drivers"
组1(研究对象,主检索):gig economy + platform labor + ride-hailing + Uber driver + DiDi
组2(核心议题,后置过滤):meaning of work + work meaning + occupational identity + livelihood
0.2 Broader-concept fallback
If a group of words is too precise (emerging concepts, specific groups), proactively add broader concepts:
| Precise word | Broader-concept fallback |
|---|---|
ride-hailing driver |
+ gig worker + platform worker + precarious worker |
meaning-making |
+ identity work + self-concept + sensemaking |
algorithmic management |
+ digital labor + platform capitalism |
0.3 Confirm strategy with the user
Before execution, list the search plan and wait for user confirmation:
【主体联合检索】
组1(主检索):gig economy + platform labor + ride-hailing + Uber driver
组2(后置过滤):meaning of work + work meaning + occupational identity + livelihood
【独立补充检索】(主检索完成后必做)
补充A(研究对象背景):precarious work + informal economy × labor market + working conditions
补充B(核心理论):identity work + sensemaking + meaning-making × labor + work + occupation
WoS 布尔检索式(同步生成,供有机构权限用户使用)
Step 0.5: Generate WoS / Scopus Boolean search strings
Before executing the script, generate standard Boolean search strings based on the keyword groups and output them to the user for backup:
Web of Science(SSCI):
TS = ("gig economy" OR "platform labor" OR "ride-hailing" OR "Uber driver")
AND TS = ("meaning of work" OR "occupational identity" OR "livelihood" OR "worker identity")
AND WC = (Sociology OR "Industrial Relations" OR "Labor Relations")
Scopus:
TITLE-ABS-KEY("gig economy" OR "platform labor" OR "ride-hailing")
AND TITLE-ABS-KEY("meaning of work" OR "occupational identity" OR "livelihood")
AND SUBJAREA(SOCI OR PSYC OR ECON OR BUSI)
Step 1: Execute the combined main search
python3 /Users/songyiping/.claude/skills/foreign-literature-search/scripts/openalex_search.py \
--keywords "gig economy + platform labor + ride-hailing + Uber driver" \
--keywords "meaning of work + work meaning + occupational identity + livelihood" \
--max-results 100 \
--topic "快车司机生计变迁与意义建构" \
--category "直接相关(平台劳动×意义建构)" \
--color "D9E1F2" \
--output-dir ~/Downloads
How the script works:
- Use the group with the fewest words (most specific) as themain search, call the OpenAlex API for each synonym, and merge the results (OR logic)
- Performpost-hoc text filteringon each paper's title+abstract: ensure it contains at least one word from each of the other groups
- If fewer than 20 papers remain after filtering, automatically relax to "match any one additional group"
- Sort in descending order by citation count and output the top N papers
Parameter description:
| Parameter | Description |
|---|---|
--keywords |
Keyword groups, each --keywords is one group, within a group + separates synonyms |
--max-results |
Maximum number of papers returned (default 100) |
--year-from / --year-to |
Year range (e.g., --year-from 2010) |
--no-soc-filter |
Disable social science concept filtering (enabled by default) |
--min-quartile |
Minimum journal quartile requirement, e.g., --min-quartile Q2 keep only Q1/Q2 journals |
--no-journal-stats |
Skip journal quartile query (faster, not recommended) |
--category |
Literature category label (used for final Excel classification) |
--color |
Excel row color, blue=D9E1F2, green=E2EFDA, yellow=FFF2CC, orange=FCE4D6 |
--output-file |
Specify output path |
--topic |
Search topic (used for file name) |
Excel Output Column Description:
| Column Name | Description |
|---|---|
| JCR Quartile | Q1-Q4, based on the curated built-in journal list (nosymbol) or estimated from the 2yr impact factor (withsymbol) |
| CAS Quartile | Zone 1-Zone 4, same source as above |
| 2yr Impact Factor | Average citation rate over the recent 2 years returned by the OpenAlex source API (≈ 2yr IF) |
| Citations | Total number of citations of the paper |
Quartile Data Description: The built-in table covers about 50 core social science journals (including ASQ, ASR, AJS, Human Relations, etc.). Journals not covered are assigned quartiles by estimating from the OpenAlex impact factor (marked with
*). The official JCR/CAS quartiles are based on the latest year; please verify them yourself.
Step 2: Independent Supplementary Search (Required)
After the main search is completed, conduct independent searches for each core concept to obtain indirectly related literature:
Supplementary Search A: Background Literature on the Research Subject
python3 /Users/songyiping/.claude/skills/foreign-literature-search/scripts/openalex_search.py \
--keywords "precarious work + informal work + gig worker + platform worker" \
--keywords "labor market + working conditions + employment + job quality" \
--max-results 60 \
--topic "快车司机生计变迁与意义建构" \
--category "间接相关-劳动条件背景" \
--color "E2EFDA" \
--output-file ~/Downloads/外文补充A_劳动背景.xlsx
Supplementary Search B: Core Theoretical Literature
python3 /Users/songyiping/.claude/skills/foreign-literature-search/scripts/openalex_search.py \
--keywords "identity work + sensemaking + meaning-making + self-concept" \
--keywords "labor + work + occupation + employment" \
--max-results 60 \
--topic "快车司机生计变迁与意义建构" \
--category "间接相关-意义/身份认同理论" \
--color "FFF2CC" \
--output-file ~/Downloads/外文补充B_意义理论.xlsx
If supplementary search results are fewer than 20, adjustment is not mandatory, but if the result is 0, replace the terms and retry.
Step 3: Aggregate and Merge — Output a Unified Classified Excel
After all searches are completed, merge all Excel files and remove duplicates to generate a unified classified Excel:
import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment
from pathlib import Path
files = {
"直接相关(平台劳动×意义建构)": ("D9E1F2", "~/Downloads/外文文献检索_快车司机生计变迁_YYYYMMDD.xlsx"),
"间接相关-劳动条件背景": ("E2EFDA", "~/Downloads/外文补充A_劳动背景.xlsx"),
"间接相关-意义/身份认同理论": ("FFF2CC", "~/Downloads/外文补充B_意义理论.xlsx"),
}
all_rows = []
seen_titles = set()
orig_headers = None # 从第一个文件读取真实表头,不硬编码
for category, (color, filepath) in files.items():
wb = openpyxl.load_workbook(Path(filepath).expanduser())
ws = wb.active
rows = list(ws.iter_rows(values_only=True))
if orig_headers is None:
orig_headers = list(rows[0]) # 实际表头:序号(0), 文献类别(1), 标题(2), ...
for row in rows[1:]:
title = str(row[2] or "").strip() # 标题固定在索引2
if title and title not in seen_titles:
seen_titles.add(title)
# 用正确的 category 覆盖原行的文献类别(索引1),保留其余列原样
all_rows.append((color, category) + tuple(row[2:]))
wb.close()
wb_out = openpyxl.Workbook()
ws_out = wb_out.active
ws_out.title = "外文文献汇总"
# 直接使用从文件读取的真实表头,避免硬编码导致列名错位或重复
ws_out.append(orig_headers)
for cell in ws_out[1]:
cell.font = Font(bold=True, color="FFFFFF", size=11)
cell.fill = PatternFill(fill_type="solid", fgColor="1F4E79")
cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
for seq, row_data in enumerate(all_rows, 1):
color, category = row_data[0], row_data[1]
ws_out.append((seq, category) + row_data[2:]) # 用新序号替换原序号
fill = PatternFill(fill_type="solid", fgColor=color)
for cell in ws_out[ws_out.max_row]:
cell.fill = fill
cell.alignment = Alignment(vertical="top", wrap_text=True)
# 列宽按实际列数动态设置(原始文件有14列)
col_widths = [5, 28, 45, 22, 22, 8, 8, 10, 6, 8, 36, 36, 30, 60]
for i, w in enumerate(col_widths[:len(orig_headers)], 1):
ws_out.column_dimensions[openpyxl.utils.get_column_letter(i)].width = w
for row in ws_out.iter_rows(min_row=2):
ws_out.row_dimensions[row[0].row].height = 65
ws_out.freeze_panes = "A2"
ws_out.auto_filter.ref = ws_out.dimensions
ws2 = wb_out.create_sheet("分类统计")
ws2.append(["文献类别", "颜色", "篇数"])
color_desc = {"D9E1F2": "蓝-直接相关", "E2EFDA": "绿-背景文献", "FFF2CC": "黄-理论文献", "FCE4D6": "橙-扩展视角"}
for cat, (color, _) in files.items():
cnt = sum(1 for r in all_rows if r[1] == cat)
ws2.append([cat, color_desc.get(color, color), cnt])
ws2.append(["合计(去重后)", "", len(all_rows)])
for cell in ws2[1]: cell.font = Font(bold=True)
output_path = "~/Downloads/外文文献汇总_快车司机生计变迁_YYYYMMDD.xlsx"
wb_out.save(Path(output_path).expanduser())
print(f"[✓] 已保存: {output_path}(共 {len(all_rows)} 篇)")
Step 4: Report the Results
After the searches are completed, report to the user:
- Number of records in each search round (including API total reference)
- Total number of records after deduplication, distribution by category
- Summary file path (open the file)
- Remind the user to supplement the search with institutional databases in WoS/Scopus
open ~/Downloads/外文文献汇总_*.xlsx
Color Conventions
| Category | Color | hex |
|---|---|---|
| Directly Related | Blue | D9E1F2 |
| Indirectly Related-Background | Green | E2EFDA |
| Indirectly Related-Theory | Yellow | FFF2CC |
| Indirectly Related-Extension | Orange | FCE4D6 |
Frequently Asked Questions
| Phenomenon | Cause and Handling |
|---|---|
| There are irrelevant papers in the results | The filter group used terms that are too broad (such as "meaning") → switch to compound phrases such as "meaning of work" |
| Results < 20 papers | The main search terms are too precise → add broader concepts (such as adding "gig worker + platform worker") |
| SSL/connection error | Network fluctuation; the script automatically retries 3 times; if it continues to fail, wait a while and retry |
| Abstract is empty | Some papers in OpenAlex have no abstract data (this is normal) |
| Top journal marked with ⭐ | The journal name matches the built-in top journal list such as ASQ, Human Relations, Organization Studies, etc. |