# scraper2-hj3415 README

`scraper2-hj3415`는 네이버 WiseReport 기반 NFS 데이터 수집과 OpenDART 공시 조회를 제공하는 Python CLI 패키지입니다.
라이브러리로 임포트해서도 사용할 수 있고, `scraper2` 명령으로 단독 실행도 가능합니다.

`pyproject.toml` 기준 정보:
- 패키지명: `scraper2-hj3415`
- 버전: `2.9.0`
- Python: `>=3.11`
- 빌드 백엔드: `flit_core`
- CLI 엔트리포인트: `scraper2 = scraper2_hj3415.cli.app:app`

## 1. 프로젝트 기능 설명

이 프로젝트는 크게 두 가지 기능을 제공합니다.

- NFS 수집: 종목코드와 endpoint(`c101`, `c103`, `c104`, `c106`, `c108`) 기준으로 재무/지표 데이터를 수집합니다.
- DART 수집: OpenDART 공시 목록을 조회하고 KRX300 기준 필터링 결과를 제공합니다.

기본 사용 형태는 CLI이며, 내부 유즈케이스를 직접 임포트해 다른 프로젝트에서 재사용할 수도 있습니다.

## 2. 프로젝트 구조 설명

아래 구조를 먼저 보면 어디서 무엇을 다루는지 빠르게 파악할 수 있습니다.

```text
scraper2-hj3415/
├─ pyproject.toml
├─ src/scraper2_hj3415/
│  ├─ cli/
│  │  ├─ app.py                  # scraper2 루트
│  │  ├─ nfs.py                  # scraper2 nfs one/all
│  │  ├─ dart.py                 # scraper2 dart reports/today
│  │  └─ common.py               # CLI 옵션/헬퍼
│  ├─ app/
│  │  ├─ settings.py             # .env 및 OS 환경변수 로딩
│  │  ├─ composition.py          # 앱 전체 의존성 조립
│  │  ├─ nfs/                    # NFS 도메인/파서/유즈케이스/어댑터
│  │  └─ dart/                   # DART 도메인/유즈케이스/어댑터
│  └─ .env
├─ tests/
└─ dist/
```

CLI 트리:

```text
scraper2
├── nfs
│   ├── one
│   └── all
├── dart
│   ├── reports
│   └── today
└── mi
```

## 3. CLI 사용법 (예시 포함)

설치:

```bash
cd packages/scraper2-hj3415
python -m pip install -e .
python -m pip install playwright
python -m playwright install chromium
```

도움말:

```bash
scraper2 --help
scraper2 nfs --help
scraper2 dart --help
```

NFS 단건 수집:

```bash
scraper2 nfs one 005930 c101
scraper2 nfs one 005930 c103 --asof 2026-01-09T05:00:00Z
scraper2 nfs one 005930 all --no-show
```

NFS 대량 수집:

```bash
scraper2 nfs all c101
scraper2 nfs all all --universe krx300 --limit 20
scraper2 nfs all c108 --chunk-size 3 --asof 2026-01-09T05:00:00Z
```

DART 조회:

```bash
scraper2 dart reports --sdate 20260301 --edate 20260320
scraper2 dart reports --sdate 20260320 --edate 20260320 --no-show
scraper2 dart today
```

## 4. 다른 프로젝트에서 임포트 사용 예시

CLI 없이 코드에서 직접 유즈케이스를 조립해 사용할 수 있습니다.

```python
import asyncio
from datetime import datetime, UTC

from scraper2_hj3415.app.nfs.composition import build_nfs_usecases


async def main() -> None:
    # memory sink를 쓰면 외부 DB 저장 없이 결과 envelope만 받을 수 있습니다.
    ucs = build_nfs_usecases(
        sink="memory",
        headless=True,
        timeout_ms=20000,
        max_concurrency=2,
        db=None,
    )
    try:
        env = await ucs.ingest.c101.execute(
            "005930",
            sleep_sec=1.0,
            asof=datetime.now(UTC),
        )
        print(env["topic"], env["key"])
    finally:
        await ucs.resources.aclose()


asyncio.run(main())
```

## 5. 환경변수 설정 예시

기본적으로 `src/scraper2_hj3415/.env`와 OS 환경변수를 함께 읽습니다.

```env
# app
APP_NAME=scraper2
APP_ENV=prod
LOG_LEVEL=INFO

# db
MONGO_URI=mongodb://localhost:27017
MONGO_DB_NAME=hj3415
MONGO_CONNECT_TIMEOUT_MS=5000
MONGO_SERVER_SELECTION_TIMEOUT_MS=5000
SNAPSHOT_TTL_DAYS=730

# nfs
NFS_SINK=mongo
SCRAPER_HEADLESS=true
SCRAPER_TIMEOUT_MS=20000
SCRAPER_MAX_CONCURRENCY=2
SCRAPER_SLEEP_SEC_DEFAULT=2.0

# dart
DART_API_KEY=your_api_key
```

운영 시 핵심:
- `NFS_SINK=mongo` 사용 시 MongoDB 접근이 필요합니다.
- `dart` 명령 사용 시 `DART_API_KEY`가 필요합니다.

## 6. Docker 사용 예시 (Dockerfile + docker-compose.yml)

아래는 `Dockerfile`로 `scraper2` 이미지를 만들고, `docker-compose.yml`에서 MongoDB와 함께 실행하는 예시입니다.

Dockerfile 예시 (`packages/scraper2-hj3415/Dockerfile`):

```dockerfile
FROM mcr.microsoft.com/playwright/python:v1.55.0-jammy

WORKDIR /app
COPY . /app

RUN python -m pip install --upgrade pip && \
    python -m pip install .

ENTRYPOINT ["scraper2"]
```

docker-compose.yml 예시 (모노레포 루트 기준):

```yaml
version: "3.9"

services:
  mongo:
    image: mongo:7
    container_name: scraper2-mongo
    ports:
      - "27017:27017"
    volumes:
      - mongo_data:/data/db

  scraper2:
    build:
      context: ./packages/scraper2-hj3415
      dockerfile: Dockerfile
    container_name: scraper2-cli
    environment:
      APP_NAME: scraper2
      APP_ENV: prod
      LOG_LEVEL: INFO
      MONGO_URI: mongodb://mongo:27017
      MONGO_DB_NAME: hj3415
      NFS_SINK: mongo
      SCRAPER_HEADLESS: "true"
      SCRAPER_TIMEOUT_MS: "20000"
      SCRAPER_MAX_CONCURRENCY: "2"
      SCRAPER_SLEEP_SEC_DEFAULT: "2.0"
      DART_API_KEY: ${DART_API_KEY:-}
    depends_on:
      - mongo
    command: ["--help"]

volumes:
  mongo_data:
```

실행:

```bash
docker compose up --build
```

단발성 명령 실행:

```bash
docker compose run --rm scraper2 nfs one 005930 c101 --no-show
docker compose run --rm scraper2 dart today --no-show
```

운영 팁:
- compose 네트워크에서는 `MONGO_URI=mongodb://mongo:27017`처럼 서비스명(`mongo`)으로 접속합니다.
- `DART_API_KEY`는 `.env` 파일 또는 CI/CD secret으로 주입하는 방식이 안전합니다.
