solorpower_crawler/verify_data.py

250 lines
8.5 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
데이터 검증 스크립트
각 발전소별로 특정 날짜/월/연도의 실제 데이터를 조회하여 검증
"""
from datetime import datetime
from crawlers import nrems, hyundai, kremc, sun_wms, cmsolar
from config import SYSTEM_CONSTANTS
def format_hourly_data(data, date_str, plant_name):
"""시간별 데이터 포맷팅"""
print(f"\n{'='*80}")
print(f"[{plant_name}] 시간별 데이터: {date_str}")
print(f"{'='*80}")
if not data:
print(" ❌ 데이터 없음")
return
# 시간별로 그룹화
hourly_dict = {}
for record in data:
timestamp = record.get('timestamp', '')
if timestamp.startswith(date_str):
hour = timestamp.split(' ')[1][:2] if ' ' in timestamp else '00'
kwh = record.get('generation_kwh', 0)
if hour not in hourly_dict:
hourly_dict[hour] = 0
hourly_dict[hour] += kwh
if not hourly_dict:
print(" ❌ 해당 날짜 데이터 없음")
return
print(f"{len(hourly_dict)}시간 데이터")
print(f"\n {'시간':<8} {'발전량(kWh)':<15}")
print(f" {'-'*25}")
total = 0
for hour in sorted(hourly_dict.keys()):
kwh = hourly_dict[hour]
total += kwh
print(f" {hour}:00 {kwh:>10.2f}")
print(f" {'-'*25}")
print(f" {'합계':<8} {total:>10.2f}")
def format_daily_data(data, year_month, plant_name):
"""일별 데이터 포맷팅"""
print(f"\n{'='*80}")
print(f"[{plant_name}] 일별 데이터: {year_month}")
print(f"{'='*80}")
if not data:
print(" ❌ 데이터 없음")
return
# 해당 월의 데이터만 필터링
monthly_data = [d for d in data if d.get('date', '').startswith(year_month)]
if not monthly_data:
print(" ❌ 해당 월 데이터 없음")
return
print(f"{len(monthly_data)}일 데이터")
print(f"\n {'날짜':<15} {'발전량(kWh)':<15}")
print(f" {'-'*30}")
total = 0
for record in sorted(monthly_data, key=lambda x: x.get('date', '')):
date = record.get('date', '')
kwh = record.get('generation_kwh', 0)
total += kwh
print(f" {date:<15} {kwh:>10.2f}")
print(f" {'-'*30}")
print(f" {'합계':<15} {total:>10.2f}")
def format_monthly_data(data, year, plant_name):
"""월별 데이터 포맷팅"""
print(f"\n{'='*80}")
print(f"[{plant_name}] 월별 데이터: {year}")
print(f"{'='*80}")
if not data:
print(" ❌ 데이터 없음")
return
# 해당 연도의 데이터만 필터링
yearly_data = [d for d in data if d.get('month', '').startswith(year)]
if not yearly_data:
print(" ❌ 해당 연도 데이터 없음")
return
print(f"{len(yearly_data)}개월 데이터")
print(f"\n {'':<10} {'발전량(kWh)':<15}")
print(f" {'-'*25}")
total = 0
for record in sorted(yearly_data, key=lambda x: x.get('month', '')):
month = record.get('month', '')
kwh = record.get('generation_kwh', 0)
total += kwh
print(f" {month:<10} {kwh:>10.2f}")
print(f" {'-'*25}")
print(f" {'합계':<10} {total:>10.2f}")
if len(yearly_data) > 0:
print(f" {'평균':<10} {total/len(yearly_data):>10.2f}")
def verify_plant(plant_config, crawler_module):
"""개별 발전소 데이터 검증"""
plant_name = plant_config['name']
print(f"\n{'#'*80}")
print(f"# {plant_name}")
print(f"{'#'*80}")
try:
# 1. 시간별 데이터: 2025-05-10, 2024-10-20
print(f"\n[1/6] 시간별 데이터 수집 중...")
hourly_2025 = crawler_module.fetch_history_hourly(plant_config, '2025-05-10', '2025-05-10')
format_hourly_data(hourly_2025, '2025-05-10', plant_name)
hourly_2024 = crawler_module.fetch_history_hourly(plant_config, '2024-10-20', '2024-10-20')
format_hourly_data(hourly_2024, '2024-10-20', plant_name)
# 2. 일별 데이터: 2025-05, 2024-07
print(f"\n[2/6] 일별 데이터 수집 중...")
daily_2025 = crawler_module.fetch_history_daily(plant_config, '2025-05-01', '2025-05-31')
format_daily_data(daily_2025, '2025-05', plant_name)
daily_2024 = crawler_module.fetch_history_daily(plant_config, '2024-07-01', '2024-07-31')
format_daily_data(daily_2024, '2024-07', plant_name)
# 3. 월별 데이터: 2024년, 2025년
print(f"\n[3/6] 월별 데이터 수집 중...")
monthly_2025 = crawler_module.fetch_history_monthly(plant_config, '2025-01', '2025-12')
format_monthly_data(monthly_2025, '2025', plant_name)
monthly_2024 = crawler_module.fetch_history_monthly(plant_config, '2024-01', '2024-12')
format_monthly_data(monthly_2024, '2024', plant_name)
print(f"\n>>> {plant_name} 검증 완료")
except Exception as e:
print(f"\n ❌ 오류 발생: {str(e)}")
import traceback
traceback.print_exc()
def main():
"""메인 함수"""
print("\n" + "="*80)
print(">>> 발전소 데이터 검증 스크립트 <<<")
print("="*80)
print(f"검증 일시: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("\n[검증 대상]")
print(" - 시간별: 2025-05-10, 2024-10-20")
print(" - 일별: 2025년 5월, 2024년 7월")
print(" - 월별: 2025년, 2024년")
# 테스트 대상 발전소 설정
test_plants = [
# NREMS 1,2호기 (분리)
({'id': 'nrems-01', 'name': '1호기', 'type': 'nrems',
'auth': {'pscode': 'duce2023072288'},
'options': {'is_split': True, 'unit_id': 1},
'system': SYSTEM_CONSTANTS['nrems']}, nrems),
({'id': 'nrems-02', 'name': '2호기', 'type': 'nrems',
'auth': {'pscode': 'duce2023072288'},
'options': {'is_split': True, 'unit_id': 2},
'system': SYSTEM_CONSTANTS['nrems']}, nrems),
# NREMS 3호기
({'id': 'nrems-03', 'name': '3호기', 'type': 'nrems',
'auth': {'pscode': 'dc2023121086'},
'options': {},
'system': SYSTEM_CONSTANTS['nrems']}, nrems),
# NREMS 4호기
({'id': 'nrems-04', 'name': '4호기', 'type': 'nrems',
'auth': {'pscode': 'duce2023072269'},
'options': {},
'system': SYSTEM_CONSTANTS['nrems']}, nrems),
# NREMS 9호기
({'id': 'nrems-09', 'name': '9호기', 'type': 'nrems',
'auth': {'pscode': 'a2020061008'},
'options': {},
'system': SYSTEM_CONSTANTS['nrems']}, nrems),
# KREMC 5호기
({'id': 'kremc-05', 'name': '5호기', 'type': 'kremc',
'auth': {'user_id': '서대문도서관', 'password': 'sunhope5!'},
'options': {'cid': '10013000376', 'cityProvCode': '11', 'rgnCode': '11410',
'dongCode': '1141011700', 'enso_type_code': '15001'},
'system': SYSTEM_CONSTANTS['kremc']}, kremc),
# Sun-WMS 6호기
({'id': 'sunwms-06', 'name': '6호기', 'type': 'sun_wms',
'auth': {'payload_id': 'kc0fXUW0LUm2wZa+2NQI0Q==', 'payload_pw': 'PGXjU6ib2mKYwtrh2i3fIQ=='},
'options': {},
'system': SYSTEM_CONSTANTS['sun_wms']}, sun_wms),
# Hyundai 8호기
({'id': 'hyundai-08', 'name': '8호기', 'type': 'hyundai',
'auth': {'user_id': 'epecoop', 'password': 'sunhope0419', 'site_id': 'M0494'},
'options': {},
'system': SYSTEM_CONSTANTS['hyundai']}, hyundai),
# CMSolar 10호기
({'id': 'cmsolar-10', 'name': '10호기', 'type': 'cmsolar',
'auth': {'login_id': 'smart3131', 'password': 'ehdrb!123', 'site_no': '834'},
'options': {},
'system': SYSTEM_CONSTANTS['cmsolar']}, cmsolar),
]
# 각 발전소 검증
for plant_config, crawler_module in test_plants:
try:
verify_plant(plant_config, crawler_module)
except KeyboardInterrupt:
print("\n\n⚠️ 사용자 중단")
break
except Exception as e:
print(f"\n{plant_config['name']} 검증 실패: {str(e)}")
import traceback
traceback.print_exc()
continue
print("\n" + "="*80)
print(">>> 데이터 검증 완료 <<<")
print("="*80)
if __name__ == '__main__':
main()