🧬 연구 허브

Skill

paper-source-collect 코드 참조

세 DB에서 논문을 대량 수집한다. DB마다 다른 한도·페이지네이션·응답형식을 다룬다.

언제 쓰나

검색식 하나로 여러 DB에서 논문 코퍼스를 만들 때. DB마다 제약이 달라서 한 방식으로 셋을 다 긁을 수 없다.

정본 코드

~/Documents/혜연/BTC_KOL_PoC/
  collect_pubmed.py    194줄  esearch → efetch 배치
  collect_openalex.py  198줄  OR 필터 배치 + 캐시
  collect_koreamed.py  426줄  API 없음 — 폼 재전송으로 긁는다
  topics/                     검색식 정의
  out/                        수집 결과 JSON

DB별 제약 — 여기가 전부다

DB인증한도페이지네이션응답
PubMed E-utilities키 선택무키 3 req/sretmax 최대 10000, efetch는 100건씩XML
OpenAlex키 없음mailto= 넣으면 10/s · 10만/일OR 필터 한 번에 50개JSON
KoreaMed없음명시 없음아래 함정 참조XML(요청해야)

PubMed — 2단계

esearch로 PMID 목록을 받고(retmax: 10000), efetch로 100건씩 상세를 받는다.

def efetch(pmids, batch=100, delay=1.0):
    ...
    time.sleep(delay)   # NCBI 부하 배려. 무키 제한은 3req/s 이지만 넉넉히 둔다

한도보다 여유 있게 잡는다. 3 req/s가 상한이라고 1초에 3번 때리면 간헐적으로 막힌다. 재시도는 time.sleep(3 * (i + 1))로 점점 늘린다.

OpenAlex — 키가 아예 없다

API 키는 존재하지 않는다. mailto= 만 붙이면 polite pool(초당 10건 / 일 10만건).

mailto는 인증이 아니라 예의다. 안 넣으면 공용 풀에서 훨씬 느리다.

BATCH = 50 — OpenAlex OR 필터 상한이다. 그 이상 넣으면 조용히 잘린다. select= 로 필요한 필드만 받는다(ids,doi,authorships,cited_by_count,publication_year). 전체를 받으면 응답이 수십 배 커진다.

결과는 openalex_cache.json에 쌓는다. 병합 단계를 여러 번 다시 돌리게 되므로 캐시가 없으면 매번 다시 긁는다.

KoreaMed — 공식 API가 없다

이 파일 426줄의 대부분이 여기서 나온 함정 대응이다.

s_display_type=xml     → PubMed 스타일 XML (저자별 소속 포함). 안 주면 HTML 파싱해야 한다
s_num_per_page         → 최대 500

가장 큰 함정 — 2페이지 이후:

2페이지 이후는 search_type=page_search + 결과페이지의 sub_search_frm 폼 전체 재전송이라야 나온다. sub_search 로 s_direct_page 만 바꾸면 조용히 1페이지가 다시 온다 (실측 중복 500/500).

에러가 아니라 같은 데이터가 성공처럼 돌아온다. 중복 제거를 안 하면 500건을 N번 받고도 모른다. 그래서 form_fields(body)로 결과 페이지의 input/select를 전부 긁어 되보낸다.

검색식이 길면 나눈다. QUERY_BUDGET = 900자 어림으로 최상위 OR 기준 분할(split_top_level_or), 실패하면 자동 이분할. 주석에 "정확할 필요 없다"고 적힌 이유다 — 실패가 분할을 유도한다.

공통 규칙

  • 검색식을 코드에 박지 마라. topics/ 에 두고 load_topic(topic_id) 로 읽는다. 검색식은 계속 바뀌고, 어떤 식으로 뽑았는지가 논문에 들어간다.
  • 재시도는 지수 백오프(3 * (i+1)). 4~5회.
  • 수집 결과는 원본 그대로 out/ 에 남긴다. 가공은 병합 단계에서.

연관 skill

paper-merge-provenance(다음 단계), biblio-normalize, lit-relevance-classify