AgentSkillsCN

data-scraping-pipeline

TradingView数据抓取自动化管道指南。 适用场景:(1) 当用户咨询如何运行爬虫时;(2) 当需要理解数据管道的架构时;(3) 当需要设置或调试数据库上传时;(4) 当需要扩展抓取自动化功能时。 触发条件:TradingView爬虫、数据抓取、股价数据、CSV下载、数据库上传、SSH隧道、自动化管道、Playwright。

SKILL.md
--- frontmatter
name: data-scraping-pipeline
description: |
  TradingView 데이터 스크래핑 자동화 파이프라인 가이드.
  사용 시점: (1) 스크래퍼 실행 방법 문의 시, (2) 데이터 파이프라인 아키텍처 이해 필요 시,
  (3) DB 업로드 설정/디버깅 시, (4) 스크래핑 자동화 확장 작업 시.
  Triggers: TradingView scraper, data scraping, 주가 데이터, CSV 다운로드, DB 업로드,
  SSH tunnel, 자동화 파이프라인, Playwright.

Data Scraping Pipeline

TradingView에서 주가 데이터를 자동으로 수집하여 MySQL 데이터베이스에 업로드하는 파이프라인.

아키텍처 개요

code
[TradingView] ──Playwright──▶ [CSV 다운로드] ──db_service──▶ [MySQL DB]
                                   │                            │
                                   ▼                            ▼
                            downloads/                    etf2_db (원격)
                            - NVDA_D.csv                  - NVDA_D 테이블
                            - AAPL_1h.csv                 - AAPL_1h 테이블

핵심 파일 구조

code
data-scraping/
├── tradingview_playwright_scraper_upload.py  # 메인 스크래퍼 (최종 버전)
├── db_service.py                              # DB 연결 및 업로드 서비스
├── cookies.json                               # TradingView 로그인 쿠키
├── pyproject.toml                             # Poetry 의존성
├── poetry.lock                                # 의존성 잠금 파일
├── downloads/                                 # CSV 다운로드 폴더
└── tradingview_data/                          # 데이터 저장 폴더

실행 가이드

1. 환경 설정

bash
cd /Users/jeong-uchang/etf-trading-project/data-scraping

# 의존성 설치
poetry install
playwright install chromium

# 환경변수 설정 (.env 파일)
TRADINGVIEW_USERNAME=your_username
TRADINGVIEW_PASSWORD=your_password
UPLOAD_TO_DB=true
USE_EXISTING_TUNNEL=true
HEADLESS=true                     # 기본값: true (쿠키 없으면 자동으로 false 전환)

2. SSH 터널 (DB 업로드 시 필수)

bash
# 터널 시작 (한 번만 실행)
ssh -f -N -L 3306:127.0.0.1:5100 ahnbi2@ahnbi2.suwon.ac.kr

# 터널 확인
pgrep -f "ssh.*3306"

3. 스크래퍼 실행

bash
# 기본 실행 (HEADLESS=true 권장)
HEADLESS=true poetry run python tradingview_playwright_scraper_upload.py

# Linux 서버 환경 (디스플레이 없는 환경)
xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24' poetry run python tradingview_playwright_scraper_upload.py

Headless 모드 관리

기본 설정: HEADLESS=true

상황HEADLESS 값설명
일반 실행 (cron 자동화)true브라우저 창 없이 백그라운드 실행
로그인 필요 (쿠키 없음/만료)falseCAPTCHA 수동 해결을 위해 브라우저 표시
디버깅/UI 확인false브라우저 동작 시각적 확인

자동 전환 로직 (코드에 내장됨):

  1. HEADLESS=true 설정 시, 쿠키가 없거나 만료되면 자동으로 false로 전환
  2. 로그인 성공 후 쿠키가 저장되면 다음 실행부터 true 모드 사용 가능
  3. 쿠키가 유효하면 자동으로 true 모드로 실행

Linux 서버 필수 설정:

bash
# xvfb 설치 (Ubuntu/Debian)
sudo apt-get install xvfb

# xvfb-run으로 실행 (디스플레이 없는 서버에서 필수)
xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24' \
  HEADLESS=true poetry run python tradingview_playwright_scraper_upload.py

로그인 워크플로우:

bash
# Step 1: 로그인이 필요하면 HEADLESS=false로 실행 (CAPTCHA 수동 해결)
HEADLESS=false poetry run python tradingview_playwright_scraper_upload.py

# Step 2: 로그인 성공 후 cookies.json 생성됨

# Step 3: 이후부터는 HEADLESS=true로 자동화 실행
HEADLESS=true poetry run python tradingview_playwright_scraper_upload.py
# 또는 Linux 서버:
xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24' \
  HEADLESS=true poetry run python tradingview_playwright_scraper_upload.py

주요 설정

TIME_PERIODS (시간대 설정)

python
TIME_PERIODS = [
    {"name": "12달", "button_text": "1Y", "interval": "1 날"},   # Daily 데이터
    {"name": "1달", "button_text": "1M", "interval": "30 분"},   # 30분 데이터
    {"name": "1주", "button_text": "5D", "interval": "5 분"},    # 5분 데이터
    {"name": "1일", "button_text": "1D", "interval": "1 분"},    # 1분 데이터
]

STOCK_LIST (종목 리스트)

python
STOCK_LIST = [
    "NVDA", "AAPL", "MSFT", "GOOGL", "AMZN", "META", "TSLA", ...
]

데이터 플로우

  1. 로그인: cookies.json 사용 (없으면 자동 로그인)
  2. 심볼 검색: #header-toolbar-symbol-search 클릭 → 종목 입력
  3. 시간대 변경: 버튼 클릭 (1Y, 1M, 5D, 1D)
  4. CSV 다운로드: 차트 데이터 다운로드 메뉴
  5. DB 업로드: db_service.upload_csv() 호출

DB 테이블 구조

sql
CREATE TABLE `{symbol}_{timeframe}` (
    `time` DATETIME NOT NULL PRIMARY KEY,
    `symbol` VARCHAR(32) NOT NULL,
    `timeframe` VARCHAR(16) NOT NULL,
    `open` DOUBLE,
    `high` DOUBLE,
    `low` DOUBLE,
    `close` DOUBLE,
    `volume` BIGINT,
    `rsi` DOUBLE,
    `macd` DOUBLE
)

트러블슈팅

로그인 실패

  • cookies.json 삭제 후 재실행
  • CAPTCHA 발생 시 수동 해결 필요 (HEADLESS=false로 실행)

DB 연결 실패

  • SSH 터널 확인: pgrep -f "ssh.*3306"
  • 터널 재시작: ssh -f -N -L 3306:127.0.0.1:5100 ahnbi2@ahnbi2.suwon.ac.kr

요소 찾기 실패

  • TradingView UI 변경 가능성
  • HEADLESS=false로 실행하여 UI 확인

Linux 디스플레이 에러

증상: Cannot open display 또는 no display environment variable 에러

해결:

bash
# xvfb 설치
sudo apt-get install xvfb

# xvfb-run으로 실행
xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24' \
  poetry run python tradingview_playwright_scraper_upload.py

xvfb-run 옵션 설명:

  • --auto-servernum: 사용 가능한 서버 번호 자동 선택
  • --server-args='-screen 0 1280x960x24': 가상 화면 해상도 설정 (1280x960, 24bit 색상)

자동화 파이프라인

구현된 자동화 스크립트

code
scripts/
├── scrape-daily.sh       # 일일 데이터 수집 자동화
├── validate_data.py      # 데이터 품질 검증
└── setup-cron.sh         # cron 작업 설정

scrape-daily.sh - 일일 스크래핑 자동화

미국 정규장 마감 후 자동으로 TradingView 데이터를 수집하는 완전 자동화 스크립트.

위치: /home/ahnbi2/etf-trading-project/scripts/scrape-daily.sh

주요 기능:

  1. SSH 터널 자동 확인 및 시작
  2. Poetry 환경 자동 설정 및 검증
  3. Headless 모드로 브라우저 실행 (서버 환경)
  4. 상세 로그 기록 및 실행 시간 측정
  5. 성공/실패 상태 자동 리포트

실행 환경 변수:

bash
export HEADLESS=true              # Headless 모드 활성화
export PATH="/usr/local/bin:..."  # cron 환경용 PATH

Linux 서버 실행 (xvfb 필수):

bash
# 수동 실행
xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24' \
  HEADLESS=true poetry run python tradingview_playwright_scraper_upload.py

# cron에서 실행 시 스크립트 내부에 xvfb-run 포함

로그 출력:

code
logs/scraper-YYYYMMDD.log

예시:
========================================
📊 일일 스크래핑 시작: Thu Jan 30 22:00:01 UTC 2026
========================================
✅ SSH 터널 이미 실행 중
🚀 스크래퍼 실행 중...
Headless 모드: true
...
✅ 스크래핑 성공 (소요시간: 342초)
완료 시간: Thu Jan 30 22:05:43 UTC 2026

수동 실행:

bash
./scripts/scrape-daily.sh

# 로그 실시간 확인
tail -f logs/scraper-$(date +%Y%m%d).log

validate_data.py - 데이터 품질 검증

MySQL 데이터베이스의 모든 종목 테이블을 자동으로 검증하는 Python 스크립트.

위치: /home/ahnbi2/etf-trading-project/scripts/validate_data.py

검증 항목:

검증 항목설명임계값
테이블 존재종목별 테이블 생성 여부-
최신 데이터오늘/어제 데이터 존재 여부1일 이내
NULL 값 비율open, high, low, close, volume5% 이하
중복 타임스탬프동일 시간 중복 데이터0건
가격 이상치0 이하 가격, 50% 이상 급변0건

실행:

bash
cd /home/ahnbi2/etf-trading-project/data-scraping
poetry run python ../scripts/validate_data.py

결과 형식:

json
{
  "timestamp": "2026-01-30T15:30:00",
  "summary": {
    "total_tables": 60,
    "passed": 58,
    "failed": 2,
    "errors": 0,
    "pass_rate": 0.967,
    "fail_rate": 0.033,
    "error_rate": 0.0
  },
  "failed_tables": ["NVDA_1h", "AAPL_D"],
  "tables": {
    "NVDA_D": {
      "exists": true,
      "row_count": 252,
      "status": "PASSED",
      "checks": {
        "recent_data": {
          "passed": true,
          "latest_date": "2026-01-29",
          "days_old": 1
        },
        "null_values": {
          "passed": true,
          "null_counts": { ... }
        },
        "duplicates": {
          "passed": true,
          "duplicate_count": 0
        },
        "price_anomalies": {
          "passed": true,
          "invalid_prices": 0,
          "extreme_changes": 0
        }
      }
    }
  }
}

검증 결과 저장:

  • 위치: logs/validation_YYYYMMDD_HHMMSS.json
  • Exit Code: 0 (성공), 1 (실패/에러)

결과 조회:

bash
# 최근 검증 결과 요약
ls -lt logs/validation_*.json | head -1 | xargs cat | jq '.summary'

# 실패한 테이블 목록
ls -lt logs/validation_*.json | head -1 | xargs cat | jq '.failed_tables'

Cron 설정

자동 설정 (권장):

bash
./scripts/setup-cron.sh

수동 설정:

bash
crontab -e

# 매일 오전 7시 (한국시간) = 22:00 UTC (미국 정규장 마감 후)
# 월~금요일에만 실행
0 22 * * 1-5 /home/ahnbi2/etf-trading-project/scripts/scrape-daily.sh

Cron 작업 확인:

bash
# 현재 설정된 cron 목록
crontab -l

# cron 실행 로그 (시스템 로그)
grep CRON /var/log/syslog | tail -20

통합 파이프라인 워크플로우

code
┌─────────────────────────────────────────┐
│  Cron Trigger (매일 22:00 UTC)          │
└───────────────┬─────────────────────────┘
                │
                ▼
┌─────────────────────────────────────────┐
│  scrape-daily.sh                        │
│  ├─ SSH 터널 확인/시작                   │
│  ├─ Poetry 환경 설정                     │
│  └─ Playwright 스크래퍼 실행 (Headless)  │
└───────────────┬─────────────────────────┘
                │
                ▼
┌─────────────────────────────────────────┐
│  TradingView 데이터 수집                 │
│  ├─ 30개 종목 × 2개 시간대              │
│  ├─ CSV 다운로드                        │
│  └─ MySQL 자동 업로드                   │
└───────────────┬─────────────────────────┘
                │
                ▼
┌─────────────────────────────────────────┐
│  로그 기록                              │
│  └─ logs/scraper-YYYYMMDD.log          │
└─────────────────────────────────────────┘

(선택) 수동 데이터 검증:
┌─────────────────────────────────────────┐
│  validate_data.py                       │
│  ├─ 60개 테이블 품질 검증               │
│  ├─ 5가지 검증 항목 자동 체크           │
│  └─ JSON 리포트 생성                    │
└─────────────────────────────────────────┘

모니터링 및 디버깅

로그 확인:

bash
# 오늘 스크래핑 로그 실시간 확인
tail -f logs/scraper-$(date +%Y%m%d).log

# 어제 로그 확인 (마지막 100줄)
tail -100 logs/scraper-$(date -d "yesterday" +%Y%m%d).log

# 최근 7일간 에러 검색
grep -i "error\|failed" logs/scraper-*.log | tail -50

DB 데이터 확인:

bash
# Python에서 직접 확인
python3 << 'EOF'
from db_service import DatabaseService
db = DatabaseService()
db.connect()

# 테이블 존재 확인
print("NVDA_D exists:", db.table_exists('NVDA_D'))

# 최근 데이터 확인
cursor = db.connection.cursor()
cursor.execute("SELECT * FROM NVDA_D ORDER BY time DESC LIMIT 5")
for row in cursor.fetchall():
    print(row)
EOF

SSH 터널 상태 확인:

bash
# 터널 프로세스 확인
pgrep -af "ssh.*3306:127.0.0.1:5100"

# 터널 재시작
pkill -f "ssh.*3306"
ssh -f -N -L 3306:127.0.0.1:5100 ahnbi2@ahnbi2.suwon.ac.kr

트러블슈팅

스크래핑 실패 시:

  1. SSH 터널 확인: pgrep -f "ssh.*3306"
  2. 로그 확인: tail -100 logs/scraper-$(date +%Y%m%d).log
  3. Headless 모드 해제 (Linux):
    bash
    xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24' \
      HEADLESS=false poetry run python tradingview_playwright_scraper_upload.py
    
  4. 수동 실행으로 디버깅:
    bash
    cd data-scraping && \
    xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24' \
      poetry run python tradingview_playwright_scraper_upload.py
    
  5. 쿠키 재로그인 필요 시: rm cookies.jsonHEADLESS=false로 실행

데이터 검증 실패 시:

  1. 검증 결과 확인: cat logs/validation_*.json | jq '.failed_tables'
  2. 실패 원인 분석: cat logs/validation_*.json | jq '.tables["NVDA_D"]'
  3. 테이블 직접 확인: SQL 쿼리로 데이터 조회

Cron 작업이 실행되지 않을 때:

  1. Cron 설정 확인: crontab -l
  2. PATH 환경 변수 확인: 스크립트 상단 PATH 설정 검증
  3. 시스템 로그 확인: grep CRON /var/log/syslog
  4. 스크립트 실행 권한: chmod +x scripts/scrape-daily.sh

관련 문서

  • DB 연결: .claude/skills/db-ssh-tunneling/skill.md
  • 프로젝트 개요: .claude/skills/ai-etf-project/skill.md