궁극적인 Reddit 스크래퍼 구축: 풀-피처드, API-프리 데이터 수집 스위트
Source: Dev.to
TL;DR
API 키가 전혀 필요 없는 완전한 Reddit 스크래퍼 스위트를 만들었습니다. Streamlit 대시보드, Grafana·Metabase와 같은 도구와 연동할 수 있는 REST API, 포스트‑프로세싱을 위한 플러그인 시스템, 예약 스크래핑, 알림 등 다양한 기능을 포함하고 있습니다. 가장 좋은 점은—전부 오픈 소스라는 점입니다.
🔗 GitHub:
The Problem
Reddit 데이터를 분석, 연구, 혹은 개인 프로젝트에 활용하려고 시도해 본 적이 있다면 다음과 같은 문제에 직면했을 가능성이 높습니다.
- Reddit API는 매우 제한적인 레이트‑리밋을 가지고 있음(특히 2023년 API 변경 이후)
- API 키는 승인 절차가 필요하고 점점 더 제한되고 있음
- 기존 스크래퍼들은 보통 단일 목적—게시물 또는 댓글만 스크래핑함
- 스크래핑 후 데이터를 시각화하거나 분석할 쉬운 방법이 없음
- 수동으로 스크래핑을 실행하는 것은 번거롭고 자동화가 필요함
The Solution: Universal Reddit Scraper Suite
수 주에 걸친 개발 끝에 다음과 같은 완전한 기능을 갖춘 스크래퍼를 만들었습니다.
| Feature | What It Does |
|---|---|
| 📊 Full Scraping | 게시물, 댓글, 이미지, 비디오, 갤러리—모두 포함 |
| 🚫 No API Keys | Reddit의 공개 JSON 엔드포인트와 미러를 사용 |
| 📈 Web Dashboard | 분석을 위한 아름다운 7‑탭 Streamlit UI |
| 🚀 REST API | Metabase, Grafana, DuckDB 등과 연결 |
| 🔌 Plugin System | 확장 가능한 포스트‑프로세싱(감성 분석, 중복 제거, 키워드 추출) |
| 📅 Scheduled Scraping | Cron‑스타일 자동화 |
| 📧 Notifications | 스크래핑 완료 시 Discord·Telegram 알림 |
| 🐳 Docker Ready | 한 줄 명령으로 어디서든 배포 가능 |
Architecture Deep Dive
How It Works Without API Keys
공식(그리고 제한된) Reddit API 대신, 스크래퍼는 다음을 활용합니다.
- Public JSON endpoints – 모든 Reddit 페이지는
.json접미사를 붙이면 구조화된 데이터를 반환합니다. - Multiple mirror fallbacks – 하나의 소스가 레이트‑리밋에 걸리면 스크래퍼가 자동으로 다른 미러로 전환합니다.
MIRRORS = [
"https://old.reddit.com/",
"https://redlib.catsarch.com/",
"https://redlib.vsls.cz/",
"https://r.nf/",
"https://libreddit.northboot.xyz/",
"https://redlib.tux.pizza/",
]
소스가 실패하면 다음 미러가 자동으로 시도됩니다—수동 개입이 필요 없습니다.
The Core Scraping Engine
스크래퍼는 세 가지 모드로 동작합니다.
Full Mode – Complete package
python main.py --mode full --limit 100
게시물을 스크랩하고 모든 미디어(이미지, 비디오, 갤러리)를 다운로드하며, 전체 스레드 구조를 가진 댓글을 가져옵니다.
History Mode – Fast metadata‑only
python main.py --mode history --limit 500
미디어를 다운로드하지 않고 게시물 메타데이터만 수집해 데이터셋을 구축합니다.
Monitor Mode – Live watching
python main.py --mode monitor
5분마다 새로운 게시물을 지속적으로 확인합니다. 최신 뉴스나 트렌드 토론을 추적하기에 적합합니다.
The Dashboard Experience
7‑탭 Streamlit 대시보드는 데이터 탐색을 직관적으로 만들어 줍니다.
Overview Tab
- 총 게시물 및 댓글 수
- 전체 게시물의 누적 점수
- 미디어 게시물 비율
- 시간별 게시물 차트
- 점수 기준 상위 10개 게시물
Analytics Tab
- Sentiment Analysis – 전체 데이터셋에 대한 VADER 기반 감성 점수
- Keyword Cloud – 가장 많이 사용된 용어
- Best Posting Times – 최적의 참여 시간을 데이터 기반으로 제시
Search Tab
필터와 함께 전체 텍스트 검색 제공:
- 최소 점수
- 게시물 유형(텍스트, 이미지, 비디오, 갤러리, 링크)
- 작성자
- 사용자 정의 정렬
Comments Analysis
- 최고 점수 댓글 보기
- 가장 활발한 댓글 작성자 파악
- 시간에 따른 댓글 패턴 추적
Scraper Controls
대시보드에서 직접 새로운 스크래핑을 시작할 수 있습니다. 설정 가능한 옵션:
- 대상 subreddit/사용자
- 게시물 제한 수
- 모드(full/history)
- 미디어 및 댓글 토글
Job History
각 스크래핑 작업에 대한 가시성 제공:
- 상태(실행 중, 완료, 실패)
- 소요 시간 메트릭
- 게시물/댓글/미디어 수
- 오류 로그
Integrations
다음 서비스와 연결하기 위한 사전 구성된 안내:
- Metabase
- Grafana
- DreamFactory
- DuckDB
The Plugin Architecture
간단하면서도 강력한 확장 가능한 포스트‑프로세싱 시스템입니다.
class Plugin:
"""Base class for all plugins."""
name = "base"
description = "Base plugin"
enabled = True
def process_posts(self, posts):
return posts
def process_comments(self, comments):
return comments
Built‑in Plugins
Sentiment Tagger
게시물·댓글에 VADER 감성 점수와 라벨을 추가합니다.
class SentimentTagger(Plugin):
name = "sentiment_tagger"
description = "Adds sentiment scores and labels to posts"
def process_posts(self, posts):
for post in posts:
text = f"{post.get('title', '')} {post.get('selftext', '')}"
score, label = analyze_sentiment(text)
post['sentiment_score'] = score
post['sentiment_label'] = label
return posts
Deduplicator
여러 스크래핑 세션에서 중복으로 나타날 수 있는 게시물을 제거합니다.
Keyword Extractor
스크랩된 콘텐츠에서 가장 중요한 용어를 추출해 트렌드 분석에 활용합니다.
Creating Your Own Plugin
plugins/ 디렉터리에 새로운 파이썬 파일을 추가합니다.
from plugins import Plugin
class MyCustomPlugin(Plugin):
name = "my_plugin"
description = "Does something cool"
enabled = True
def process_posts(self, posts):
# Your logic here
return posts
스크래핑 시 플러그인을 활성화합니다.
python main.py --mode full --plugins sentiment_tagger,deduplicator
REST API for External Integrations
API 서버 실행:
python main.py --api
- API 기본 URL:
- Documentation:
Key Endpoints
| Endpoint | Description |
|---|---|
GET /posts | 필터(서브레딧, 제한, 오프셋)와 함께 게시물 목록 |
GET /comments | 댓글 목록 |
GET /subreddits | 스크랩된 모든 서브레딧 |
GET /jobs | 작업 이력 |
GET /query?sql=... | 파워 유저를 위한 원시 SQL 쿼리 |
GET /grafana/query | Grafana 호환 시계열 데이터 |
Real‑World Integration: Grafana Dashboard
- Grafana에 JSON API 또는 Infinity 플러그인을 설치합니다.
- datasource를 위 URL에 연결합니다.
/grafana/query엔드포인트를 시계열 패널에 사용합니다. 예시:
SELECT date(created_utc) AS time, COUNT(*) AS posts
FROM posts
GROUP BY date(created_utc);
이제 Reddit 활동을 실시간으로 추적하는 대시보드가 완성됩니다.
Scheduled Scraping & Notifications
Automation Made Easy
Cron‑스타일 스케줄링으로 정기 스크래핑을 설정합니다.
# 매 60분마다 스크랩
python main.py --schedule delhi --every 60
맞춤 옵션:
python main.py --schedule delhi --every 30 --mode full --limit 50
Get Notified
스크래핑이 완료되면 Discord 또는 Telegram 알림을 보낼 수 있도록 설정합니다.
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
export TELEGRAM_BOT_TOKEN="123456:ABC..."
export TELEGRAM_CHAT_ID="987654321"
스크래퍼가 선택한 플랫폼에 요약 알림을 전송합니다.
Dry Run Mode: Test Before You Commit
데이터를 실제로 저장하지 않고 스크래핑을 시뮬레이션합니다.
python main.py --mode full --limit 50 --dry-run
샘플 출력:
🧪 DRY RUN MODE - No data will be saved
🧪 DRY RUN COMPLETE!
📊 Would scrape: 100 posts
💬 Would fetch: 250 comments