pharmacy-pos-qr-system/backend/pubmed_search.py
시골약사 97cf89a9c2 feat: PubMed 기반 GraphRAG 연구 스크립트 추가
근거 기반 약물 추천을 위한 PubMed 논문 검색 및 분석 스크립트:

1. pubmed_search.py
   - PubMed 논문 검색 기본 템플릿
   - Biopython Entrez API 활용
   - 3가지 주제 검색 예시 포함

2. fetch_paper_abstract.py
   - PMID로 논문 초록 가져오기
   - 특정 논문 상세 정보 조회

3. analyze_statin_myopathy.py
   - Statin 근육병증과 CoQ10 보충 연구 분석
   - CK(Creatine Kinase) 측정의 의미 설명

4. ashwagandha_sleep_research.py
   - Ashwagandha의 수면 개선 효과 연구
   - 작용 메커니즘 분석 (코르티솔, GABA)
   - 다른 수면 보조제와 비교

5. naproxen_advantages_research.py
   - Naproxen의 심혈관 안전성 연구
   - NSAID 간 비교 분석
   - 약동학 및 업셀링 시나리오

6. pycnogenol_multi_indication_research.py
   - 피크노제놀의 7가지 적응증 연구
   - 발기부전, 당뇨망막병증, 정맥기능부전 등
   - 우선순위 점수화

7. pycnogenol_womens_health_research.py
   - 피크노제놀의 여성 건강 효능
   - 갱년기, 생리통, 피부 미용

8. sqlite_graph_example.py
   - SQLite 그래프 쿼리 예제
   - Cypher 스타일 추론 시연
   - GraphRAG 개념 실습

각 스크립트는 Windows 한글 인코딩 처리 포함.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-24 21:04:33 +09:00

166 lines
5.2 KiB
Python

"""
PubMed 논문 검색 테스트
Biopython Entrez를 사용한 의학 논문 검색
"""
import sys
import os
# UTF-8 인코딩 강제 (Windows 한글 깨짐 방지)
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
from Bio import Entrez
from dotenv import load_dotenv
# .env 파일 로드
load_dotenv()
# NCBI Entrez 설정
Entrez.email = os.getenv('PUBMED_EMAIL', 'test@example.com')
api_key = os.getenv('PUBMED_API_KEY')
if api_key:
Entrez.api_key = api_key
print(f"[INFO] PubMed API Key 사용 중 (최대 10 req/sec)")
else:
print(f"[INFO] API Key 없음 (최대 3 req/sec 제한)")
def search_pubmed(query, max_results=5):
"""PubMed에서 논문 검색"""
try:
print(f"\n검색어: '{query}'")
print("-" * 80)
# 1. 검색 (PMID 목록 가져오기)
handle = Entrez.esearch(
db="pubmed",
term=query,
retmax=max_results,
sort="relevance"
)
record = Entrez.read(handle)
handle.close()
pmids = record["IdList"]
total_count = int(record["Count"])
if not pmids:
print(f"[WARNING] 검색 결과 없음")
return []
print(f"[OK] 총 {total_count}건 검색됨, 상위 {len(pmids)}건 조회 중...\n")
# 2. 논문 상세 정보 가져오기
handle = Entrez.efetch(
db="pubmed",
id=pmids,
rettype="medline",
retmode="xml"
)
papers = Entrez.read(handle)
handle.close()
results = []
for idx, paper in enumerate(papers['PubmedArticle'], 1):
try:
article = paper['MedlineCitation']['Article']
# PMID
pmid = str(paper['MedlineCitation']['PMID'])
# 제목
title = article.get('ArticleTitle', '(제목 없음)')
# 초록 (여러 섹션이 있을 수 있음)
abstract_parts = article.get('Abstract', {}).get('AbstractText', [])
if abstract_parts:
if isinstance(abstract_parts, list):
abstract = ' '.join([str(part) for part in abstract_parts])
else:
abstract = str(abstract_parts)
else:
abstract = "(초록 없음)"
# 저널
journal = article.get('Journal', {}).get('Title', '(저널 없음)')
# 출판 연도
pub_date = article.get('Journal', {}).get('JournalIssue', {}).get('PubDate', {})
year = pub_date.get('Year', '(연도 없음)')
# 저자 (첫 번째 저자만)
authors = article.get('AuthorList', [])
if authors:
first_author = authors[0]
last_name = first_author.get('LastName', '')
initials = first_author.get('Initials', '')
author_str = f"{last_name} {initials}" if last_name else "(저자 없음)"
else:
author_str = "(저자 없음)"
result = {
'pmid': pmid,
'title': title,
'abstract': abstract[:500] + '...' if len(abstract) > 500 else abstract,
'journal': journal,
'year': year,
'author': author_str
}
results.append(result)
# 출력
print(f"[{idx}] PMID: {pmid}")
print(f"제목: {title}")
print(f"저자: {author_str}")
print(f"저널: {journal} ({year})")
print(f"초록: {result['abstract']}")
print(f"링크: https://pubmed.ncbi.nlm.nih.gov/{pmid}/")
print("-" * 80)
except Exception as e:
print(f"[ERROR] 논문 파싱 실패: {e}")
continue
return results
except Exception as e:
print(f"[ERROR] PubMed 검색 실패: {e}")
return []
def main():
"""메인 실행"""
print("=" * 80)
print("PubMed 논문 검색 테스트")
print("=" * 80)
# 테스트 1: Statin과 CoQ10 관계
print("\n[TEST 1] Statin과 CoQ10 근육 부작용 관계")
results1 = search_pubmed("statin AND coq10 AND muscle", max_results=3)
# 테스트 2: CoQ10 일반
print("\n[TEST 2] CoQ10 보충제 효능")
results2 = search_pubmed("coenzyme q10 supplementation benefits", max_results=3)
# 테스트 3: 약물 상호작용
print("\n[TEST 3] Atorvastatin 부작용")
results3 = search_pubmed("atorvastatin adverse effects", max_results=3)
print("\n" + "=" * 80)
print("검색 완료")
print("=" * 80)
print(f"{len(results1) + len(results2) + len(results3)}개 논문 조회됨")
print("\n[TIP] GraphRAG에 활용 방법:")
print(" 1. 검색된 PMID를 지식 그래프에 저장")
print(" 2. AI 추천 시 관련 논문 인용")
print(" 3. 예시: 'Statin 복용자에게 CoQ10 추천 (근거: PMID:12345678, 신뢰도: 85%)'")
if __name__ == '__main__':
main()