## 왜 논문 PDF 크롤링이 필요한가
학술 연구, AI 모델 학습, 문헌 분석 등 다양한 목적으로 대량의 논문 데이터가 필요한 경우가 있습니다. 특히 자연어 처리(NLP)나 과학 문헌 분석 프로젝트에서는 수십만 건의 논문을 체계적으로 수집하고 관리하는 것이 핵심 과제입니다.
이 글에서는 arXiv, PubMed, bioRxiv 등 주요 논문 저장소에서 **98만 건의 메타데이터**와 **23만 건의 PDF 파일**(총 1TB)을 수집한 경험을 바탕으로 실무 노하우를 공유합니다.
## 주요 논문 데이터 소스별 특징
### 1. arXiv (23만 건 수집)
- **특징**: 물리학, 수학, 컴퓨터 과학 분야 프리프린트 저장소
- **장점**: 대부분의 논문이 PDF로 공개되어 있고, API와 bulk access 제공
- **주요 카테고리**: cs.CL(자연어처리) 3.8만 건, cs.CV(컴퓨터 비전) 3.6만 건, cs.LG(머신러닝) 2.9만 건
- **용량**: 688GB (평균 3-4MB/파일)
### 2. PubMed (67만 건 메타데이터)
- **특징**: 생명과학 및 의학 분야 최대 데이터베이스
- **주의점**: 모든 논문이 오픈액세스는 아니므로 PMC(PubMed Central)에서 무료 제공 여부 확인 필요
- **수집률**: 전체 67만 건 중 28만 건에서 PDF URL 확보 (42%)
### 3. bioRxiv/medRxiv (7만 건)
- **특징**: 생물학/의학 분야 프리프린트
- **장점**: 거의 모든 논문이 PDF 제공, 수집률 99%
- **용량**: 319GB
## 크롤링 시스템 아키텍처
### 1단계: 메타데이터 수집
```python
# arXiv API 활용 예시
import urllib.request
import xml.etree.ElementTree as ET
def fetch_arxiv_metadata(category, start_date):
base_url = 'http://export.arxiv.org/api/query?'
query = f'search_query=cat:{category}&start=0&max_results=1000'
response = urllib.request.urlopen(base_url + query)
data = response.read()
root = ET.fromstring(data)
papers = []
for entry in root.findall('{http://www.w3.org/2005/Atom}entry'):
paper = {
'id': entry.find('{http://www.w3.org/2005/Atom}id').text,
'title': entry.find('{http://www.w3.org/2005/Atom}title').text,
'pdf_url': entry.find('{http://www.w3.org/2005/Atom}link[@title="pdf"]').get('href')
}
papers.append(paper)
return papers
```
### 2단계: PDF 다운로드 전략
**핵심 고려사항:**
1. **Rate Limiting**: 각 소스마다 요청 제한이 다름
- arXiv: 초당 1-3 요청 권장
- PubMed: API 키 없이는 초당 3 요청 제한
2. **재시도 로직**: 네트워크 오류, 일시적 장애 대응
```python
import time
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
def download_pdf_with_retry(url, save_path):
session = requests.Session()
retry = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
try:
response = session.get(url, timeout=30, stream=True)
with open(save_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return True
except Exception as e:
print(f"Download failed: {e}")
return False
finally:
time.sleep(1) # Rate limiting
```
3. **저장 구조**: 카테고리별 디렉토리 분류
```
/papers/
├── arxiv/
│ ├── cs.CL/
│ ├── cs.CV/
│ └── cs.LG/
├── biorxiv/
└── medrxiv/
```
## 데이터베이스 설계
```sql
CREATE TABLE papers (
id SERIAL PRIMARY KEY,
source VARCHAR(50), -- 'arxiv', 'pubmed', 'biorxiv'
paper_id VARCHAR(100) UNIQUE,
title TEXT,
authors TEXT[],
abstract TEXT,
categories VARCHAR(50)[],
pdf_url TEXT,
pdf_path TEXT, -- 로컬 저장 경로
download_status VARCHAR(20), -- 'pending', 'completed', 'failed'
created_at TIMESTAMP DEFAULT NOW(),
downloaded_at TIMESTAMP
);
CREATE INDEX idx_source ON papers(source);
CREATE INDEX idx_categories ON papers USING GIN(categories);
CREATE INDEX idx_download_status ON papers(download_status);
```
## 모니터링 및 진행상황 추적
**일일 리포트 자동 생성:**
```python
from datetime import datetime, timedelta
def generate_daily_report(db_conn):
today = datetime.now().date()
yesterday = today - timedelta(days=1)
query = f"""
SELECT
source,
COUNT(*) as total,
SUM(CASE WHEN pdf_url IS NOT NULL THEN 1 ELSE 0 END) as has_pdf_url,
SUM(CASE WHEN download_status = 'completed' THEN 1 ELSE 0 END) as downloaded,
SUM(CASE WHEN downloaded_at::date = '{today}' THEN 1 ELSE 0 END) as today_downloads
FROM papers
GROUP BY source
"""
# 결과를 마크다운 표로 변환
# ...
```
## 실전 팁
### 1. 텍스트 추출 자동화
PDF 다운로드와 동시에 텍스트 추출까지 수행하면 효율적입니다.
```python
import PyPDF2
def extract_text_from_pdf(pdf_path):
try:
with open(pdf_path, 'rb') as f:
reader = PyPDF2.PdfReader(f)
text = ''
for page in reader.pages:
text += page.extract_text()
return text
except:
return None
```
### 2. 중복 방지
- 논문 ID를 UNIQUE 제약조건으로 설정
- 다운로드 전 파일 존재 여부 체크
### 3. 디스크 용량 관리
- 1TB 규모의 데이터는 압축 고려 (gzip으로 30-40% 절감 가능)
- 오래된/사용 빈도 낮은 파일은 cold storage로 이동
## 법적/윤리적 고려사항
⚠️ **반드시 확인해야 할 사항:**
1. **라이선스**: arXiv는 대부분 재배포 가능하지만, PubMed는 저널별로 다름
2. **robots.txt**: 크롤링 금지 여부 확인
3. **API 이용약관**: bulk download 정책 준수
4. **개인정보**: 저자 이메일 등 민감정보 수집 주의
## 결론
대규모 논문 크롤링 프로젝트의 핵심은:
✅ **단계별 접근**: 메타데이터 → PDF URL → 다운로드 → 텍스트 추출
✅ **안정성**: 재시도 로직, 에러 핸들링, 진행상황 추적
✅ **확장성**: 카테고리별 분산 처리, 병렬 다운로드
✅ **준수**: 각 플랫폼의 API 정책 및 라이선스 존중
23만 건 규모는 단일 서버에서도 충분히 처리 가능하지만, 100만 건 이상으로 확장할 경우 분산 큐(Celery, RabbitMQ) 도입을 고려해보세요.
### 다음 단계
- **전문 검색 엔진 구축**: Elasticsearch로 논문 검색 시스템 만들기
- **임베딩 벡터화**: 논문 내용을 벡터로 변환해 유사도 검색 구현
- **자동 분류**: 머신러닝으로 논문 카테고리 자동 태깅
ai-automation
대규모 학술 논문 PDF 크롤링 시스템 구축기: 100만 건 데이터 수집 노하우
arXiv, PubMed 등 주요 논문 저장소에서 23만 건의 PDF를 자동 수집한 경험 공유
SpacePlanning · SpacePlanning AI Team2026년 4월 8일조회 304