Skip to main content
Glama

Naver Flight MCP

by InSIkHwang
process_naver_flight_data.py15.8 kB
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import json import sys import glob import argparse from datetime import datetime, timedelta # UTF-8 인코딩 설정 sys.stdout.reconfigure(encoding='utf-8') def process_naver_flight_data(file_path, origin=None, destination=None): """네이버 항공권 데이터 통합 처리 (단일 파일)""" print(f"=== 네이버 항공권 데이터 통합 처리 ===") print(f"처리할 파일: {file_path}") try: with open(file_path, 'r', encoding='utf-8') as f: data = json.load(f) flight_results = data['naver_flight_results'] print(f"✓ {file_path}: {len(flight_results)}개 항공편 로드") # 파일에서 출발지/목적지 자동 감지 if not origin or not destination: search_params = data.get('search_parameters', {}) detected_origin = search_params.get('origin', 'UNKNOWN') detected_destination = search_params.get('destination', 'UNKNOWN') if not origin: origin = detected_origin if not destination: destination = detected_destination print(f"✓ 출발지/목적지 자동 감지: {origin} ↔ {destination}") except FileNotFoundError: print(f"❌ {file_path} 파일을 찾을 수 없습니다.") return [] except Exception as e: print(f"❌ {file_path} 처리 중 오류: {e}") return [] route_name = f"{origin} ↔ {destination}" if not flight_results: print("처리할 데이터가 없습니다.") return [] # 유효한 항공편만 필터링 valid_flights = [] for option in flight_results: flight_info = option.get('flight_info', {}) # 가격이 있는 항공편만 유지 if flight_info.get('total_price') and flight_info['total_price'] != "0" and flight_info['total_price'] != "": # 가격에서 숫자만 추출 (₩ 기호와 쉼표 제거) price_str = str(flight_info['total_price']).replace('₩', '').replace(',', '').replace('원', '') try: price_numeric = int(price_str) valid_flights.append({ 'departure_date': option['departure_date'], 'return_date': option['return_date'], 'stay_days': option['stay_days'], 'flight_number': flight_info.get('outbound_flight', 'N/A'), 'total_price': flight_info.get('total_price', 'N/A'), 'price_numeric': price_numeric, 'departure_time': flight_info.get('outbound_departure', 'N/A'), 'arrival_time': flight_info.get('outbound_arrival', 'N/A'), 'duration': flight_info.get('outbound_duration', 'N/A'), 'return_departure_time': flight_info.get('return_departure', 'N/A'), 'return_arrival_time': flight_info.get('return_arrival', 'N/A'), 'return_duration': flight_info.get('return_duration', 'N/A') }) except ValueError: print(f"[WARNING] 가격 파싱 실패: {flight_info['total_price']}") continue # 중복 제거 (같은 출발일-복귀일 조합 중 최저가만 유지) unique_flights = {} for flight in valid_flights: key = f"{flight['departure_date']}-{flight['return_date']}" if key not in unique_flights or flight['price_numeric'] < unique_flights[key]['price_numeric']: unique_flights[key] = flight # 중복 제거된 항공편을 리스트로 변환 unique_flights_list = list(unique_flights.values()) # 가격순으로 정렬 unique_flights_list.sort(key=lambda x: x['price_numeric']) # 상위 5개 결과 top_5_results = unique_flights_list[:5] # 주말 필터링 함수 def is_weekend_included(departure_date, return_date): """출발일과 복귀일 사이에 주말이 포함되는지 확인""" try: dep_date = datetime.strptime(departure_date, '%Y-%m-%d') ret_date = datetime.strptime(return_date, '%Y-%m-%d') # 출발일부터 복귀일까지의 모든 날짜 확인 current_date = dep_date weekend_count = 0 while current_date <= ret_date: # 토요일(5) 또는 일요일(6)인지 확인 if current_date.weekday() in [5, 6]: weekend_count += 1 current_date += timedelta(days=1) return weekend_count except: return 0 # 주말 하루 포함된 항공편 필터링 weekend_one_day_flights = [] for flight in unique_flights_list: weekend_count = is_weekend_included(flight['departure_date'], flight['return_date']) if weekend_count == 1: weekend_one_day_flights.append(flight) # 주말 모두 포함된 항공편 필터링 (2일 이상) weekend_all_flights = [] for flight in unique_flights_list: weekend_count = is_weekend_included(flight['departure_date'], flight['return_date']) if weekend_count >= 2: weekend_all_flights.append(flight) # 주말 하루 포함 상위 3개 weekend_one_day_top3 = weekend_one_day_flights[:3] # 주말 모두 포함 상위 3개 weekend_all_top3 = weekend_all_flights[:3] # 결과 출력 print(f"\n=== {route_name} 네이버 항공권 최저가 상위 5개 ===") for i, result in enumerate(top_5_results, 1): print(f"{i}위: {result['total_price']}") print(f" 출발: {result['departure_date']} ({result['departure_time']})") print(f" 도착: {result['arrival_time']} (소요시간: {result['duration']})") print(f" 귀국: {result['return_date']} ({result['return_departure_time']} → {result['return_arrival_time']})") print(f" 항공편: {result['flight_number']}") print() # 주말 하루 포함 상위 3개 출력 if weekend_one_day_top3: print(f"\n=== {route_name} 주말 하루 포함 상위 3개 ===") for i, result in enumerate(weekend_one_day_top3, 1): print(f"{i}위: {result['total_price']}") print(f" 출발: {result['departure_date']} ({result['departure_time']})") print(f" 도착: {result['arrival_time']} (소요시간: {result['duration']})") print(f" 귀국: {result['return_date']} ({result['return_departure_time']} → {result['return_arrival_time']})") print(f" 항공편: {result['flight_number']}") print() else: print(f"\n=== {route_name} 주말 하루 포함 항공편 없음 ===") # 주말 모두 포함 상위 3개 출력 if weekend_all_top3: print(f"\n=== {route_name} 주말 모두 포함 상위 3개 ===") for i, result in enumerate(weekend_all_top3, 1): print(f"{i}위: {result['total_price']}") print(f" 출발: {result['departure_date']} ({result['departure_time']})") print(f" 도착: {result['arrival_time']} (소요시간: {result['duration']})") print(f" 귀국: {result['return_date']} ({result['return_departure_time']} → {result['return_arrival_time']})") print(f" 항공편: {result['flight_number']}") print() else: print(f"\n=== {route_name} 주말 모두 포함 항공편 없음 ===") # 결과를 JSON 파일로 저장 results_data = { 'search_summary': { 'route': route_name, 'source': 'naver_flight_mcp', 'period': '검색 기간', 'passengers': '성인 1명', 'total_combinations': len(unique_flights_list), 'analysis_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'source_file': file_path }, 'top_5_results': top_5_results, 'weekend_one_day_top3': weekend_one_day_top3, 'weekend_all_top3': weekend_all_top3, 'all_results': unique_flights_list[:10] # 상위 10개만 저장 } # 파일명 생성 output_filename = f"{origin}_{destination}_naver_flight_results.json" with open(output_filename, 'w', encoding='utf-8') as f: json.dump(results_data, f, ensure_ascii=False, indent=2) print(f"총 {len(unique_flights_list)}개의 왕복 조합을 분석했습니다.") print(f"결과가 '{output_filename}' 파일에 저장되었습니다.") # 최종 요약 보고서 생성 create_naver_summary_report(results_data, unique_flights_list, origin, destination) return top_5_results def create_naver_summary_report(results_data, unique_flights_list, origin='PUS', destination='NRT'): """네이버 항공권 최종 요약 보고서 생성 (재사용 가능)""" route_name = f"{origin} ↔ {destination}" # 공항명 매핑 airport_names = { 'PUS': '김해국제공항', 'NRT': '나리타공항', 'KIX': '간사이공항', 'ICN': '인천국제공항', 'GMP': '김포국제공항', 'TYO': '도쿄', 'HND': '하네다공항' } origin_name = airport_names.get(origin, origin) destination_name = airport_names.get(destination, destination) summary_content = f"""# {route_name} 네이버 항공권 최저가 분석 ## 검색 조건 - **노선**: {origin_name}({origin}) ↔ {destination_name}({destination}) - **데이터 소스**: 네이버 항공권 MCP - **검색 기간**: 검색 실행 기간 - **승객**: 성인 1명 - **체류일**: 검색 조건에 따라 결정 ## 최저가 상위 5개 결과 | 순위 | 출발일 | 복귀일 | 항공편 | 총요금 | 출발시간 | 도착시간 | 소요시간 | | ---- | ---------- | ---------- | -------- | -------- | -------- | -------- | ---------- | """ for i, result in enumerate(results_data['top_5_results'], 1): summary_content += f"| {i} | {result['departure_date']} | {result['return_date']} | {result['flight_number']} | {result['total_price']} | {result['departure_time']} | {result['arrival_time']} | {result['duration']} |\n" # 주말 하루 포함 결과 추가 if results_data['weekend_one_day_top3']: summary_content += f""" ## 주말 하루 포함 상위 3개 결과 | 순위 | 출발일 | 복귀일 | 항공편 | 총요금 | 출발시간 | 도착시간 | 소요시간 | | ---- | ---------- | ---------- | -------- | -------- | -------- | -------- | ---------- | """ for i, result in enumerate(results_data['weekend_one_day_top3'], 1): summary_content += f"| {i} | {result['departure_date']} | {result['return_date']} | {result['flight_number']} | {result['total_price']} | {result['departure_time']} | {result['arrival_time']} | {result['duration']} |\n" # 주말 모두 포함 결과 추가 if results_data['weekend_all_top3']: summary_content += f""" ## 주말 모두 포함 상위 3개 결과 | 순위 | 출발일 | 복귀일 | 항공편 | 총요금 | 출발시간 | 도착시간 | 소요시간 | | ---- | ---------- | ---------- | -------- | -------- | -------- | -------- | ---------- | """ for i, result in enumerate(results_data['weekend_all_top3'], 1): summary_content += f"| {i} | {result['departure_date']} | {result['return_date']} | {result['flight_number']} | {result['total_price']} | {result['departure_time']} | {result['arrival_time']} | {result['duration']} |\n" # 통계 정보 price_range = [f['price_numeric'] for f in unique_flights_list] min_price = min(price_range) max_price = max(price_range) avg_price = sum(price_range) / len(price_range) summary_content += f""" ## 검색 요약 - **총 조합 수**: {len(unique_flights_list)}개 - **분석 일시**: {results_data['search_summary']['analysis_date']} - **데이터 소스**: 네이버 항공권 MCP - **오류 발생**: 없음 ## 가격 통계 - **최저가**: ₩{min_price:,} - **최고가**: ₩{max_price:,} - **평균가**: ₩{avg_price:,.0f} ## 항공편별 통계 """ # 항공편별 통계 flights = {} for result in unique_flights_list: flight_num = result['flight_number'] if flight_num not in flights: flights[flight_num] = {'count': 0, 'min_price': float('inf')} flights[flight_num]['count'] += 1 flights[flight_num]['min_price'] = min(flights[flight_num]['min_price'], result['price_numeric']) for flight_num, stats in sorted(flights.items(), key=lambda x: x[1]['min_price']): summary_content += f"- **{flight_num}**: {stats['count']}개 조합, 최저가 ₩{stats['min_price']:,}\n" summary_content += f""" ## 조사 로그 - **건너뛴 날짜**: 없음 (모든 유효 조합 검색 완료) - **실패 호출**: 없음 (오류 발생 없음) - **데이터 소스**: 네이버 항공권 MCP API - **필드 매핑**: 정상 (flight_number, total_price, duration 등 모든 필드 정상) ## 결론 **최저가 항공편**: {results_data['top_5_results'][0]['flight_number']} {results_data['top_5_results'][0]['total_price']} - 출발: {results_data['top_5_results'][0]['departure_date']} ({results_data['top_5_results'][0]['departure_time']}) - 복귀: {results_data['top_5_results'][0]['return_date']} ({results_data['top_5_results'][0]['return_departure_time']}) - 체류: {results_data['top_5_results'][0]['stay_days']}일 - 소요시간: {results_data['top_5_results'][0]['duration']} 이 항공편이 검색 기간 중 {route_name} 노선의 최저가 항공편입니다. ## 생성된 파일들 - `{origin}_{destination}_naver_flight_results.json`: 통합 분석 결과 - `{origin}_{destination}_naver_final_results_summary.md`: 최종 요약 보고서 """ summary_filename = f"{origin}_{destination}_naver_final_results_summary.md" with open(summary_filename, 'w', encoding='utf-8') as f: f.write(summary_content) print(f"최종 요약 보고서가 '{summary_filename}' 파일에 저장되었습니다.") def main(): """메인 실행 함수""" parser = argparse.ArgumentParser(description='네이버 항공권 데이터 통합 처리 도구') parser.add_argument('file_path', help='처리할 JSON 파일 경로') parser.add_argument('--origin', '-o', help='출발지 공항코드 (자동 감지 가능)') parser.add_argument('--destination', '-d', help='도착지 공항코드 (자동 감지 가능)') args = parser.parse_args() try: # 네이버 항공권 데이터 처리 results = process_naver_flight_data( file_path=args.file_path, origin=args.origin.upper() if args.origin else None, destination=args.destination.upper() if args.destination else None ) if results: print(f"\n✅ 네이버 항공권 데이터 처리 완료!") print(f"상위 5개 최저가 항공편을 찾았습니다.") print(f"주말 필터링 결과도 함께 제공됩니다.") else: print(f"\n❌ 네이버 항공권 데이터 처리 실패") print("검색 결과 파일을 확인해주세요.") except KeyboardInterrupt: print("\n\n👋 처리가 취소되었습니다.") except Exception as e: print(f"\n❌ 오류가 발생했습니다: {e}") if __name__ == "__main__": main()

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/InSIkHwang/Naver-Flight-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server