162 lines
6.4 KiB
Python
162 lines
6.4 KiB
Python
"""
|
|
cli.py — 시스템 전체 CLI 통합 진입점
|
|
|
|
크롤러, 라인업 관리, 게임 기록 입력 등 모든 기능을
|
|
서브 커맨드(subcommand) 형태로 실행할 수 있습니다.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from playwright.sync_api import sync_playwright
|
|
|
|
from commands.base import add_common_arguments, load_report
|
|
from commands.record import run as run_record
|
|
|
|
DEFAULT_BASE_URL = "http://58.229.253.168:8089"
|
|
|
|
|
|
def _parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description="Baseball Automation CLI")
|
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
|
|
# 1. record 커맨드 (기존 record_game_playwright.py)
|
|
parser_record = subparsers.add_parser("record", help="크롤링된 리포트를 바탕으로 게임 기록을 자동 입력합니다.")
|
|
add_common_arguments(parser_record)
|
|
parser_record.add_argument("--review-only", action="store_true", help="경기기록 대신 합의판정만 일괄 등록")
|
|
|
|
# 2. crawl 커맨드 (네이버 API 크롤링)
|
|
parser_crawl = subparsers.add_parser("crawl", help="네이버 야구 API에서 데이터를 크롤링하여 JSON 리포트로 저장합니다.")
|
|
parser_crawl.add_argument("--game-id", required=True, help="크롤링할 네이버 게임 ID (예: 20260501NCLG02026)")
|
|
parser_crawl.add_argument("--output-dir", default="output", help="리포트를 저장할 디렉토리 (기본값: output)")
|
|
parser_crawl.add_argument("--start-inning", help="시작 이닝 필터 (예: '2', '3초')")
|
|
parser_crawl.add_argument("--end-inning", help="종료 이닝 필터 (예: '5', '7말')")
|
|
parser_crawl.add_argument("--lineup-only", action="store_true", help="라인업 정보만 저장")
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def interactive_mode() -> int:
|
|
print("=== Baseball Automation CLI ===")
|
|
print("1. 네이버 데이터 크롤링 (crawl)")
|
|
print("2. 관리자 사이트 라인업 입력 (lineup)")
|
|
print("3. 관리자 사이트 기록 자동 입력 (record)")
|
|
print("4. 크롤링 + 라인업 + 기록 한 번에 실행 (crawl -> lineup -> record)")
|
|
|
|
choice = input("\n실행할 작업을 선택하세요 (1/2/3/4) [4]: ").strip() or "4"
|
|
if choice not in {"1", "2", "3", "4"}:
|
|
print("잘못된 입력입니다.")
|
|
return 1
|
|
|
|
game_id = input("경기 ID를 입력하세요 (예: 20260501NCLG02026): ").strip()
|
|
if not game_id:
|
|
print("경기 ID가 필요합니다.")
|
|
return 1
|
|
|
|
base_url = DEFAULT_BASE_URL
|
|
user_data_dir = None
|
|
manager_game_no = ""
|
|
|
|
if choice in {"2", "3", "4"}:
|
|
base_url_input = input("기록 사이트 기본 URL을 입력하세요 (엔터 시 site.txt 자동 참조): ").strip()
|
|
if base_url_input:
|
|
base_url = base_url_input
|
|
else:
|
|
try:
|
|
site_txt_path = Path("site.txt")
|
|
if site_txt_path.exists():
|
|
lines = site_txt_path.read_text(encoding="utf-8").splitlines()
|
|
if lines and lines[0].startswith("http"):
|
|
from urllib.parse import urlparse
|
|
parsed = urlparse(lines[0])
|
|
base_url = f"{parsed.scheme}://{parsed.netloc}"
|
|
print(f"👉 [자동 설정] 기록 사이트 URL: {base_url}")
|
|
except Exception as e:
|
|
print(f"site.txt 파일을 읽는 중 오류가 발생했습니다: {e}")
|
|
return 1
|
|
|
|
user_data_dir = input("크롬 프로필 경로를 입력하세요 (엔터 시 임시 세션): ").strip()
|
|
manager_game_no = input("관리자 사이트 게임번호를 입력하세요 (예: 11211, 모르면 엔터): ").strip()
|
|
|
|
args = argparse.Namespace(
|
|
game_id=game_id,
|
|
base_url=base_url,
|
|
report_path=None,
|
|
manager_game_no=manager_game_no or None,
|
|
user_data_dir=user_data_dir or None,
|
|
channel="chrome",
|
|
headless=False,
|
|
close=False,
|
|
write_events=True,
|
|
job_id=None,
|
|
lineup_only=False,
|
|
review_only=False,
|
|
start_inning=None,
|
|
end_inning=None,
|
|
output_dir="output",
|
|
save=True, # for lineup
|
|
)
|
|
|
|
if choice in {"1", "4"}:
|
|
from crawler.report_builder import build_report, filter_report, save_report
|
|
print(f"\n[{args.game_id}] 데이터 크롤링 시작...")
|
|
report = build_report(args.game_id)
|
|
filtered = filter_report(report)
|
|
out_path = save_report(filtered, Path(args.output_dir))
|
|
print(f"✅ 크롤링 및 리포트 저장 완료: {out_path}")
|
|
|
|
if choice in {"2", "3", "4"}:
|
|
report_path = Path(args.output_dir) / f"{args.game_id}_report.json"
|
|
report = load_report(report_path)
|
|
|
|
with sync_playwright() as playwright:
|
|
if choice in {"2", "4"}:
|
|
from commands.lineup import run as run_lineup
|
|
run_lineup(playwright, args, report)
|
|
|
|
if choice in {"3", "4"}:
|
|
from commands.record import run as run_record
|
|
print(f"\n[{args.game_id}] 관리자 사이트 기록 자동 입력 시작...")
|
|
run_record(playwright, args, report)
|
|
|
|
return 0
|
|
|
|
|
|
def main() -> int:
|
|
if len(sys.argv) == 1:
|
|
return interactive_mode()
|
|
|
|
args = _parse_args()
|
|
|
|
if args.game_id:
|
|
args.game_id = "".join(args.game_id.split())
|
|
|
|
if args.command == "record":
|
|
report_path = Path(args.report_path) if args.report_path else Path("output") / f"{args.game_id}_report.json"
|
|
report = load_report(report_path)
|
|
with sync_playwright() as playwright:
|
|
run_record(playwright, args, report)
|
|
return 0
|
|
|
|
if args.command == "crawl":
|
|
from crawler.report_builder import build_report, filter_report, save_report
|
|
print(f"[{args.game_id}] 데이터 크롤링 시작...")
|
|
report = build_report(args.game_id, start_inning=args.start_inning, end_inning=args.end_inning)
|
|
filtered = filter_report(
|
|
report,
|
|
lineup_only=getattr(args, "lineup_only", False),
|
|
start_inning=args.start_inning,
|
|
end_inning=args.end_inning
|
|
)
|
|
out_path = save_report(filtered, Path(args.output_dir))
|
|
print(f"✅ 크롤링 및 리포트 저장 완료: {out_path}")
|
|
return 0
|
|
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|