KTX 기차표를 조회해보자.
POST 요청의 Payload를 보면 데이터가 엄...청나게 많다.
불필요한 데이터가 많을 것 같으니, 천천히 분석해보자. 결과는 다음과 같다.
승차권 조회를 여러번 해보면서 찾은 결과
- URL : https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do
- Method : POST
Data Field
- selGoTrain : 기차 종류 (05 - 전체, 00 - KTX, 09 - ITX-청춘, 18 - ITX-마음, 02 - 무궁화, 03 - 통근열차)
- txtPsgFlg_1 : 성인 수
- txtPsgFlg_2 : 어린이 수(만6~12세)
- txtPsgFlg_8 : 아기 수(만6세 미만)
- txtPsgFlg_3 : 노인 수
- txtPsgFlg_4 : 중증장애인 수
- txtPsgFlg_5 : 경증장애인 수
- txtSeatAttCd_3 : 좌석위치 (000 - 기본, 011 - 1인석, 012 - 창측좌석, 013 - 내측좌석)
- txtSeatAttCd_2 : 좌석방향 (000 - 기본, 009 - 순방향석, 010 - 역방향석)
- txtSeatAttCd_4 : 좌석속성 (015 - 일반, 019 - 유아동반/편한대화, 031 - 노트북, 021 - 수동휠체어, 028 - 전동휠체어, XXX - 수유실 인접, 018 - 2층석, 032 - 자전거거치대)
- selGoTrainRa : [추정] selGoTrain과 동일
- radJobId : 여정 경로(1 - 직통, 2 - 환승, 3 - 왕복)
- adjcCheckYn : 인접역 포함 여부 ("Y", "N")
- txtGoStart : 출발역 텍스트 (e.g. 서울)
- txtGoEnd : 도착역 텍스트 (e.g. 청량리)
- txtGoHour : 출발 시간 (e.g. 180000 - HHMMSS)
- txtGoPage : 조회 페이지 - 항상 1
- txtGoAbrdDt : 출발일(e.g. 20240120)
- checkStnNm : 항상 "Y"
- hidRsvTpCd : 예약구분 (03 - 일반예약, 09 - 단체예약)
- 나머지 - 안보내도 됨
데이터 포맷을 맞춰서 post 요청을 보내면 아래와 같은 java script 포맷의 데이터를 얻을 수 있다.
각 파라미터의 의미를 이해하려면 train_info 함수를 들어댜봐야한다.
이 정보를 가지고 스케쥴을 정리해서 반환하게끔 해서 마무리하면 메서드는 아래와 같이 완성된다
def fetch_schedule(self, txtGoStart, txtGoEnd, txtGoAbrdDt, txtGoHour, adult, child, baby, senior, svrDsb, mldDsb,
radJobId='1', txtSeatAttCd_3='000', txtSeatAttCd_2 = '000', txtSeatAttCd_4='015', selGoTrain='00', dlayTnumAplFlg='Y'):
schedule_url = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"
body = {
"selGoTrain": selGoTrain, # 기차 종류 (05-전체, 00-KTX, 09-ITX-청춘, 18-ITX-마음, 02-무궁화, 03-통근열차)
"txtPsgFlg_1": adult, # 성인 수
"txtPsgFlg_2": child, # 어린이 수(만6~12세)
"txtPsgFlg_8": baby, # 아기 수(만6세 미만)
"txtPsgFlg_3": senior, # 노인 수
"txtPsgFlg_4": svrDsb, # 중증장애인 수
"txtPsgFlg_5": mldDsb, # 경증장애인 수
"txtSeatAttCd_3": txtSeatAttCd_3, # 좌석위치 (000 - 기본, 011 - 1인석, 012 - 창측좌석, 013 - 내측좌석)
"txtSeatAttCd_2": txtSeatAttCd_2, # 좌석방향 (000 - 기본, 009 - 순방향석, 010 - 역방향석)
"txtSeatAttCd_4": txtSeatAttCd_4, # 좌석속성 (015 - 일반, 019 - 유아동반/편한대화, 031 - 노트북, 021 - 수동휠체어,
# 028 - 전동휠체어, XXX - 수유실 인접, 018 - 2층석, 032 - 자전거거치대)
"selGoTrainRa": selGoTrain, # [추정] selGoTrain과 동일
"radJobId": radJobId, # 여정 경로(1 - 직통, 2 - 환승, 3 - 왕복)
"adjcCheckYn": "N", # 인접역 포함 여부 ("Y", "N")
"txtGoStart": txtGoStart, # 출발역 텍스트 (e.g. 서울)
"txtGoEnd": txtGoEnd, # 도착역 텍스트 (e.g. 청량리)
"txtGoHour": txtGoHour, # 출발 시간 (e.g. 180000 - HHMMSS)
"txtGoPage": "1", # 조회 페이지 - 항상 1
"txtGoAbrdDt": txtGoAbrdDt, # 출발일(e.g. 20240120)
"checkStnNm": "Y", # 항상 "Y"
"hidRsvTpCd": "03", # 예약구분 (03 - 일반예약, 09 - 단체예약)
}
try:
res = self.session.post(schedule_url, data=body, headers=self.get_req_headers())
except Exception as e:
self.error_callback('KTX 열차 조회 실패', f"HTTP 요청에 실패했습니다 - \n{e}")
return []
try:
soup = BeautifulSoup(res.text, 'html.parser')
trains = soup.find_all("script", string=re.compile('new train_info'))
except Exception as e:
self.error_callback('KTX 열차 조회 실패', f"HTML 파싱에 실패했습니다 - \n{e}")
return []
result = []
try:
for tr in trains:
tr = tr.text.replace('\t', '').replace(' ', '').replace("\r\n", "").replace("\"", "")
tr = tr[tr.find('(')+1:]
tr = tr[:tr.rfind(')')]
tr = tr.split(',')
schedule_info = dict()
schedule_info["txtGoAbrdDt"] = tr[0]
schedule_info["txtGoStartCode"] = tr[1]
schedule_info["txtGoEndCode"] = tr[2]
schedule_info["selGoTrain"] = tr[3]
schedule_info["selGoRoom"] = tr[4]
schedule_info["txtGoHour"] = tr[5]
schedule_info["txtGoTrnNo"] = tr[6]
schedule_info["useSeatFlg"] = tr[7]
schedule_info["useServiceFlg"] = tr[8]
schedule_info["selGoSeat"] = tr[9]
schedule_info["selGoSeat1"] = tr[10]
schedule_info["selGoSeat2"] = tr[11]
schedule_info["txtPsgCnt1"] = tr[12]
schedule_info["txtPsgCnt2"] = tr[13]
schedule_info["selGoService"] = tr[14]
schedule_info["h_trn_seq"] = tr[15]
schedule_info["h_chg_trn_dv_cd"] = tr[16]
schedule_info["h_chg_trn_seq"] = tr[17]
schedule_info["h_dpt_rs_stn_cd"] = tr[18]
schedule_info["h_dpt_rs_stn_cd_nm"] = tr[19]
schedule_info["h_arv_rs_stn_cd"] = tr[20]
schedule_info["h_arv_rs_stn_cd_nm"] = tr[21]
schedule_info["h_trn_no"] = tr[22]
schedule_info["h_yms_apl_flg"] = tr[23]
schedule_info["h_trn_clsf_cd"] = tr[24]
schedule_info["h_trn_gp_cd"] = tr[25]
schedule_info["h_seat_att_cd"] = tr[26]
schedule_info["h_run_dt"] = tr[27]
schedule_info["h_dpt_dt"] = tr[28]
schedule_info["h_dpt_tm"] = tr[29]
schedule_info["h_arv_dt"] = tr[30]
schedule_info["h_arv_tm"] = tr[31]
schedule_info["h_dlay_hr"] = tr[32]
schedule_info["h_rsv_wait_ps_cnt"] = tr[33]
schedule_info["h_dtour_flg"] = tr[34]
schedule_info["h_car_tp_cd"] = tr[35]
schedule_info["h_trn_cps_cd1"] = tr[36]
schedule_info["h_trn_cps_cd2"] = tr[37]
schedule_info["h_trn_cps_cd3"] = tr[38]
schedule_info["h_trn_cps_cd4"] = tr[39]
schedule_info["h_trn_cps_cd5"] = tr[40]
schedule_info["h_no_ticket_dpt_rs_stn_cd"] = tr[41]
schedule_info["h_no_ticket_arv_rs_stn_cd"] = tr[42]
schedule_info["h_nonstop_msg"] = tr[43]
schedule_info["h_dpt_stn_cons_ordr"] = tr[44]
schedule_info["h_arv_stn_cons_ordr"] = tr[45]
schedule_info["h_dpt_stn_run_ordr"] = tr[46]
schedule_info["h_arv_stn_run_ordr"] = tr[47]
schedule_info["h_stnd_rest_seat_cnt"] = tr[48]
schedule_info["h_free_rest_seat_cnt"] = tr[49]
result.append(schedule_info)
except Exception as e:
self.error_callback('KTX 열차 조회 실패', f"열차 시간표 파싱에 실패했습니다 - \n{e}")
풀 코드는 깃허브로..!
'프로젝트 > SRT&KTX 매진표 예매' 카테고리의 다른 글
SRT&KTX 기차표 매크로 예매 - (12) 예매시 텔레그램 알림 보내기(python-telegram-bot) (0) | 2024.01.17 |
---|---|
SRT&KTX 기차표 매크로 예매 - (11) KTX 승차권 예매 (1) | 2024.01.16 |
SRT&KTX 기차표 매크로 예매 - (9) KTX 역 리스트 조회 (0) | 2024.01.15 |
SRT&KTX 기차표 매크로 예매 - (8) KTX 로그인 (0) | 2024.01.15 |
SRT&KTX 기차표 매크로 예매 - (7) 실행파일 만들기 (PyInstaller) (0) | 2024.01.12 |