100 lines
2.7 KiB
Python
100 lines
2.7 KiB
Python
# ==========================================
|
|
# crawlers/base.py - 크롤러 공통 유틸리티
|
|
# ==========================================
|
|
|
|
import requests
|
|
|
|
def safe_float(value):
|
|
"""
|
|
안전한 float 변환
|
|
None, 빈 문자열, 콤마 포함 숫자 등을 처리
|
|
"""
|
|
if value is None:
|
|
return 0.0
|
|
try:
|
|
return float(str(value).replace(',', ''))
|
|
except (ValueError, TypeError):
|
|
return 0.0
|
|
|
|
def create_session():
|
|
"""기본 설정된 requests 세션 생성"""
|
|
session = requests.Session()
|
|
return session
|
|
|
|
def get_default_headers():
|
|
"""기본 HTTP 헤더 반환"""
|
|
return {
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36',
|
|
'Accept': 'application/json, text/plain, */*'
|
|
}
|
|
|
|
def determine_status(current_kw):
|
|
"""발전량 기반 상태 결정"""
|
|
if current_kw > 0:
|
|
return "🟢 정상"
|
|
else:
|
|
return "💤 대기"
|
|
|
|
def format_result(name, kw, today, plant_id, status=None):
|
|
"""결과 딕셔너리 포맷 통일"""
|
|
if status is None:
|
|
status = determine_status(kw)
|
|
|
|
return {
|
|
'name': name,
|
|
'kw': kw,
|
|
'today': today,
|
|
'id': plant_id,
|
|
'status': status
|
|
}
|
|
|
|
def validate_data_quality(data_list, value_key='generation_kwh'):
|
|
"""
|
|
데이터 품질 검증
|
|
|
|
Returns:
|
|
dict: {
|
|
'is_valid': bool,
|
|
'warnings': list,
|
|
'all_zero': bool,
|
|
'duplicate_ratio': float
|
|
}
|
|
"""
|
|
if not data_list or len(data_list) == 0:
|
|
return {
|
|
'is_valid': False,
|
|
'warnings': ['데이터 없음'],
|
|
'all_zero': True,
|
|
'duplicate_ratio': 0.0
|
|
}
|
|
|
|
warnings = []
|
|
values = [safe_float(item.get(value_key, 0)) for item in data_list]
|
|
|
|
# 모두 0인 경우 체크
|
|
all_zero = all(v == 0 for v in values)
|
|
if all_zero:
|
|
warnings.append('모든 값이 0 - 실제 데이터가 아닐 가능성')
|
|
|
|
# 연속 중복 체크
|
|
if len(values) > 1:
|
|
duplicates = 0
|
|
for i in range(len(values) - 1):
|
|
if values[i] == values[i+1]:
|
|
duplicates += 1
|
|
|
|
duplicate_ratio = duplicates / (len(values) - 1)
|
|
|
|
if duplicate_ratio > 0.8:
|
|
warnings.append(f'연속 중복 비율 {duplicate_ratio*100:.1f}% - 실제 데이터가 아닐 가능성')
|
|
else:
|
|
duplicate_ratio = 0.0
|
|
|
|
is_valid = not all_zero and duplicate_ratio < 0.8
|
|
|
|
return {
|
|
'is_valid': is_valid,
|
|
'warnings': warnings,
|
|
'all_zero': all_zero,
|
|
'duplicate_ratio': duplicate_ratio
|
|
} |