예매하고자 하는 승차권을 정확하게 알고 있다면, 굳이 승차권 리스트를 조회할 필요가 없다.
그래도 최종적으로 UI도 입히고, 유저 편의성을 높이려면 조회 기능은 필요할 것 같아 구현해보려고 한다.
결론적으로 말하자면, SRT 승차권 리스트를 Json 형태로 받아오는 방법을 못찾았다...
HTML 코드를 받아서 파싱을 해야한다. 이것만은 하기 싫었는데...
승차권 조회를 여러번 해보면서 찾은 결과
- URL : https://etk.srail.kr/hpg/hra/01/selectScheduleList.do
- Method : POST
- Query : pageId=TK0101010000 (없어도 되는 것으로 추정됨)
Data Field
- dptRsStnCd : 출발역 코드 (e.g. 0551)
- arvRsStnCd : 도착역 코드
- stlbTrnClsfCd : [추정] 항상 '05' - ~~ Train Classification Code 같은데, 변하지 않음
- psgNum : 총 승객 인원
- seatAttCd : [추정] 좌석 속성, rqSeatAttCd1와 같은 값인 것으로 보임
- isRequest : [추정] 항상 'Y'
- dptRsStnCdNm : 출발역 이름
- arvRsStnCdNm : 도착역 이름
- dptDt : 출발 날짜 (e.g. 20240108)
- dptTm : 출발 시간 (e.g. 194500)
- chtnDvCd : 여정경로 (1 - 직통, 2 - 환승, 3 - 왕복)
- psgInfoPerPrnb1 : 어른 인원
- psgInfoPerPrnb5 : 어린이 인원
- psgInfoPerPrnb4 : 노인 인원
- psgInfoPerPrnb2 : 중증장애인 인원
- psgInfoPerPrnb3 : 경증장애인 인원
- locSeatAttCd1 : 좌석위치 (000 - default, 011 - 1인석, 012 - 창측좌석, 013 - 내측좌석)
- rqSeatAttCd1 : 좌석속성 (015 - 일반, 021 - 휠체어, 028 - 전동휠체어)
- trnGpCd : 차종구분 (109 - 전체, 300 - SRT, 900 - SRT+KTX)
- dlayTnumAplFlg : 지연열차포함 (Y - 포함, N - 미포함)
위 정보를 가지고 Post 요청을 보내는 코드를 짜보자.
def fetch_schedule(self, dptRsStnCd, arvRsStnCd, dptRsStnCdNm, arvRsStnCdNm, dptDt, dptTm, adult, child, senior,
svrDsb, mldDsb, chtnDvCd='1', locSeatAttCd1='000', rqSeatAttCd1='015', trnGpCd='300',
dlayTnumAplFlg='Y'):
schedule_url = "https://etk.srail.kr/hpg/hra/01/selectScheduleList.do"
body = {
"dptRsStnCd": dptRsStnCd, # 출발역 코드 (e.g. 0551)
"arvRsStnCd": arvRsStnCd, # 도착역 코드
"stlbTrnClsfCd": "05", # [추정] 항상 '05' - ~~ Train Classification Code 같은데, 변하지 않음
"psgNum": str(adult+child+senior+svrDsb+mldDsb), # 총 승객 인원
"seatAttCd": rqSeatAttCd1, # [추정] 좌석 속성, rqSeatAttCd1와 같은 값인 것으로 보임
"isRequest": "Y", # [추정] 항상 'Y'
"dptRsStnCdNm": dptRsStnCdNm, # 출발역 이름
"arvRsStnCdNm": arvRsStnCdNm, # 도착역 이름
"dptDt": dptDt, # 출발 날짜 (e.g. 20240108)
"dptTm": dptTm, # 출발 시간 (e.g. 194500)
"chtnDvCd": chtnDvCd, # 여정경로 (1 - 직통, 2 - 환승, 3 - 왕복)
"psgInfoPerPrnb1": str(adult), # 어른 인원
"psgInfoPerPrnb5": str(child), # 어린이 인원
"psgInfoPerPrnb4": str(senior), # 노인 인원
"psgInfoPerPrnb2": str(svrDsb), # 중증장애인 인원
"psgInfoPerPrnb3": str(mldDsb), # 경증장애인 인원
"locSeatAttCd1": locSeatAttCd1, # 좌석위치 (000 - default, 011 - 1인석, 012 - 창측좌석, 013 - 내측좌석)
"rqSeatAttCd1": rqSeatAttCd1, # 좌석속성 (015 - 일반, 021 - 휠체어, 028 - 전동휠체어)
"trnGpCd": trnGpCd, # 차종구분 (109 - 전체, 300 - SRT, 900 - SRT+KTX)
"dlayTnumAplFlg": dlayTnumAplFlg, # 지연열차포함 (Y - 포함, N - 미포함)
}
res = self.session.post(schedule_url, data=body)
print(res.text)
위 코드를 실행해보면, 시간표 정보가 포함된 HTML 코드가 잘 수신되는걸 확인할 수 있다.
변수를 조금씩 바꿔가며 테스트해보니, 기차역 이름은 중요하지 않은것 같다. 역 코드를 기준으로 조회하는 듯 싶다.
여기서 유의미한 시간표 정보를 뽑아보자.
크롬 개발자 도구로 소스를 만지다 보니, "trnNo" class 안에 해당 기차의 정보가 매우 예쁘게 정리되어 있는 것을 확인할 수 있다.
BeautifulSoup를 이용하여 기차 정보를 뽑아보자.
import requests
from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'html.parser')
trains = soup.find_all("td", {"class": "trnNo"})
result = []
for tr in trains:
schedule_info = dict()
schedule_info["trnOrdrNo"] = tr.find("input", {"name": re.compile(r'trnOrdrNo')})['value']
schedule_info["jrnySqno"] = tr.find("input", {"name": re.compile(r'jrnySqno')})['value']
schedule_info["runDt"] = tr.find("input", {"name": re.compile(r'runDt')})['value']
schedule_info["trnNo"] = tr.find("input", {"name": re.compile(r'trnNo')})['value']
schedule_info["trnGpCd"] = tr.find("input", {"name": re.compile(r'trnGpCd')})['value']
schedule_info["stlbTrnClsfCd"] = tr.find("input", {"name": re.compile(r'stlbTrnClsfCd')})['value']
schedule_info["dptDt"] = tr.find("input", {"name": re.compile(r'dptDt')})['value']
schedule_info["dptTm"] = tr.find("input", {"name": re.compile(r'dptTm')})['value']
schedule_info["dptRsStnCd"] = tr.find("input", {"name": re.compile(r'dptRsStnCd')})['value']
schedule_info["dptRsStnCdNm"] = tr.find("input", {"name": re.compile(r'dptRsStnCdNm')})['value']
schedule_info["dptStnConsOrdr"] = tr.find("input", {"name": re.compile(r'dptStnConsOrdr')})['value']
schedule_info["dptStnRunOrdr"] = tr.find("input", {"name": re.compile(r'dptStnRunOrdr')})['value']
schedule_info["arvRsStnCd"] = tr.find("input", {"name": re.compile(r'arvRsStnCd')})['value']
schedule_info["arvRsStnCdNm"] = tr.find("input", {"name": re.compile(r'arvRsStnCdNm')})['value']
schedule_info["arvStnConsOrdr"] = tr.find("input", {"name": re.compile(r'arvStnConsOrdr')})['value']
schedule_info["arvStnRunOrdr"] = tr.find("input", {"name": re.compile(r'arvStnRunOrdr')})['value']
schedule_info["seatAttCd"] = tr.find("input", {"name": re.compile(r'seatAttCd')})['value']
schedule_info["scarGridcnt"] = tr.find("input", {"name": re.compile(r'scarGridcnt')})['value']
schedule_info["scarNo"] = tr.find("input", {"name": re.compile(r'scarNo')})['value']
schedule_info["seatNo_1"] = tr.find("input", {"name": re.compile(r'seatNo_1')})['value']
schedule_info["seatNo_2"] = tr.find("input", {"name": re.compile(r'seatNo_2')})['value']
schedule_info["seatNo_3"] = tr.find("input", {"name": re.compile(r'seatNo_3')})['value']
schedule_info["seatNo_4"] = tr.find("input", {"name": re.compile(r'seatNo_4')})['value']
schedule_info["seatNo_5"] = tr.find("input", {"name": re.compile(r'seatNo_5')})['value']
schedule_info["seatNo_6"] = tr.find("input", {"name": re.compile(r'seatNo_6')})['value']
schedule_info["seatNo_7"] = tr.find("input", {"name": re.compile(r'seatNo_7')})['value']
schedule_info["seatNo_8"] = tr.find("input", {"name": re.compile(r'seatNo_8')})['value']
schedule_info["seatNo_9"] = tr.find("input", {"name": re.compile(r'seatNo_9')})['value']
schedule_info["trainDiscGenRt"] = tr.find("input", {"name": re.compile(r'trainDiscGenRt')})['value']
schedule_info["rcvdAmt"] = tr.find("input", {"name": re.compile(r'rcvdAmt')})['value']
schedule_info["rcvdFare"] = tr.find("input", {"name": re.compile(r'rcvdFare')})['value']
schedule_info["trnNstpLeadInfo"] = tr.find("input", {"name": re.compile(r'trnNstpLeadInfo')})['value']
result.append(schedule_info)
return result
각 필드 값의 의미를 몰라도 된다. 나중에 예매할 때 필요한 정보만 사용하면 되니까.
srt.fetch_schedule('0297', '0552', '오송', '동탄', '20240110', '193100', 1, 0, 0, 0, 0)
위 샘플코드를 돌려보면 결과가 아래처럼 잘 나온다
[{'trnOrdrNo': '0', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00384', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '193100', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000009', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000012', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '1', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00618', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '194000', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000005', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000008', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '2', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00362', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '204600', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000006', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000007', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '3', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00664', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '205500', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000007', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000009', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '4', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00620', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '213000', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000004', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000006', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '5', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00366', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '214000', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000004', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000006', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '6', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00666', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '221500', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000007', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000009', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '7', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00370', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '222400', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000006', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000008', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}, {'trnOrdrNo': '8', 'jrnySqno': '001', 'runDt': '20240110', 'trnNo': '00376', 'trnGpCd': '300', 'stlbTrnClsfCd': '17', 'dptDt': '20240110', 'dptTm': '233700', 'dptRsStnCd': '0297', 'dptRsStnCdNm': '오송', 'dptStnConsOrdr': '000006', 'dptStnRunOrdr': '000005', 'arvRsStnCd': '0552', 'arvRsStnCdNm': '동탄', 'arvStnConsOrdr': '000002', 'arvStnRunOrdr': '000006', 'seatAttCd': '015', 'scarGridcnt': '', 'scarNo': '', 'seatNo_1': '', 'seatNo_2': '', 'seatNo_3': '', 'seatNo_4': '', 'seatNo_5': '', 'seatNo_6': '', 'seatNo_7': '', 'seatNo_8': '', 'seatNo_9': '', 'trainDiscGenRt': '0.0', 'rcvdAmt': '10700', 'rcvdFare': '4800', 'trnNstpLeadInfo': ''}]
기차역 코드를 자동으로 가져오자
여기서 끝내려고 했으나... 아무래도 기차역 리스트와 코드를 자동으로 가져와야 할 것 같다.
유저 입장에서 기차역 코드를 알 필요가 전혀 없다. 사람은 기차역 이름을 보고 예매하지, 코드를 보지 않는다.
그리고 나중에 기차역이 새로 지어지거나 추가된다면... 유지보수하기가 상당히 귀찮을테니 자동으로 리스트를 가져와보자.
승차권 조회 페이지 코드를 살펴봤으나, 기차역 리스트와 역코드가 담긴 정보는 없었다.
출발역/도착역을 바꿀 수 있는 버튼이 수상스러우니 클릭해보자.
소스에서 기차역 이름과 코드를 확인할 수 있다.
가져오자.
def fetch_stations(self):
res = self.session.get("https://etk.srail.kr/hpg/hra/01/selectMapInfo.do")
soup = BeautifulSoup(res.text, 'html.parser')
stations = soup.find_all("a", {"class": re.compile(r'map')})
result = dict()
for station in stations:
station_split = station['onclick'].split("'")
result[station_split[3]] = station_split[1]
return result
역 정보는 class 선언할 때 불러줘도 될 것 같으니, 수정하면 완성된 코드는 아래와 같다!
import re
import requests
from bs4 import BeautifulSoup
class SRT:
def __init__(self, login_type, login_id, login_pwd):
# login_type - 1: 회원번호, 2: 이메일, 3: 휴대전화번호
# login_id - 회원번호/이메일/휴대전화번호
# login_pwd - 비밀번호
self.session = requests.Session()
self.session.get("https://etk.srail.kr/main.do")
self.login_type = login_type
self.login_id = login_id
self.login_pwd = login_pwd
self.stations = self.fetch_stations()
def login(self):
login_url = "https://etk.srail.kr/cmc/01/selectLoginInfo.do"
body = {
"rsvTpCd": "",
"goUrl": "",
"from": "",
"srchDvCd": self.login_type,
"srchDvNm": self.login_id,
"hmpgPwdCphd": self.login_pwd
}
res = self.session.post(login_url, data=body)
if "location.replace('/main.do')" in res.text:
return True
else:
return False
def is_logged_in(self):
res = self.session.get("https://etk.srail.kr/main.do")
if '로그아웃' in res.text:
return True
else:
return False
def fetch_schedule(self, dptRsStnCdNm, arvRsStnCdNm, dptDt, dptTm, adult, child, senior, svrDsb, mldDsb,
chtnDvCd='1', locSeatAttCd1='000', rqSeatAttCd1='015', trnGpCd='300', dlayTnumAplFlg='Y'):
schedule_url = "https://etk.srail.kr/hpg/hra/01/selectScheduleList.do"
body = {
"dptRsStnCd": self.stations[dptRsStnCdNm], # 출발역 코드 (e.g. 0551)
"arvRsStnCd": self.stations[arvRsStnCdNm], # 도착역 코드
"stlbTrnClsfCd": "05", # [추정] 항상 '05' - ~~ Train Classification Code 같은데, 변하지 않음
"psgNum": str(adult+child+senior+svrDsb+mldDsb), # 총 승객 인원
"seatAttCd": rqSeatAttCd1, # [추정] 좌석 속성, rqSeatAttCd1와 같은 값인 것으로 보임
"isRequest": "Y", # [추정] 항상 'Y'
"dptRsStnCdNm": dptRsStnCdNm, # 출발역 이름
"arvRsStnCdNm": arvRsStnCdNm, # 도착역 이름
"dptDt": dptDt, # 출발 날짜 (e.g. 20240108)
"dptTm": dptTm, # 출발 시간 (e.g. 194500)
"chtnDvCd": chtnDvCd, # 여정경로 (1 - 직통, 2 - 환승, 3 - 왕복)
"psgInfoPerPrnb1": str(adult), # 어른 인원
"psgInfoPerPrnb5": str(child), # 어린이 인원
"psgInfoPerPrnb4": str(senior), # 노인 인원
"psgInfoPerPrnb2": str(svrDsb), # 중증장애인 인원
"psgInfoPerPrnb3": str(mldDsb), # 경증장애인 인원
"locSeatAttCd1": locSeatAttCd1, # 좌석위치 (000 - default, 011 - 1인석, 012 - 창측좌석, 013 - 내측좌석)
"rqSeatAttCd1": rqSeatAttCd1, # 좌석속성 (015 - 일반, 021 - 휠체어, 028 - 전동휠체어)
"trnGpCd": trnGpCd, # 차종구분 (109 - 전체, 300 - SRT, 900 - SRT+KTX)
"dlayTnumAplFlg": dlayTnumAplFlg, # 지연열차포함 (Y - 포함, N - 미포함)
}
res = self.session.post(schedule_url, data=body)
soup = BeautifulSoup(res.text, 'html.parser')
trains = soup.find_all("td", {"class": "trnNo"})
result = []
for tr in trains:
schedule_info = dict()
schedule_info["trnOrdrNo"] = tr.find("input", {"name": re.compile(r'trnOrdrNo')})['value']
schedule_info["jrnySqno"] = tr.find("input", {"name": re.compile(r'jrnySqno')})['value']
schedule_info["runDt"] = tr.find("input", {"name": re.compile(r'runDt')})['value']
schedule_info["trnNo"] = tr.find("input", {"name": re.compile(r'trnNo')})['value']
schedule_info["trnGpCd"] = tr.find("input", {"name": re.compile(r'trnGpCd')})['value']
schedule_info["stlbTrnClsfCd"] = tr.find("input", {"name": re.compile(r'stlbTrnClsfCd')})['value']
schedule_info["dptDt"] = tr.find("input", {"name": re.compile(r'dptDt')})['value']
schedule_info["dptTm"] = tr.find("input", {"name": re.compile(r'dptTm')})['value']
schedule_info["dptRsStnCd"] = tr.find("input", {"name": re.compile(r'dptRsStnCd')})['value']
schedule_info["dptRsStnCdNm"] = tr.find("input", {"name": re.compile(r'dptRsStnCdNm')})['value']
schedule_info["dptStnConsOrdr"] = tr.find("input", {"name": re.compile(r'dptStnConsOrdr')})['value']
schedule_info["dptStnRunOrdr"] = tr.find("input", {"name": re.compile(r'dptStnRunOrdr')})['value']
schedule_info["arvRsStnCd"] = tr.find("input", {"name": re.compile(r'arvRsStnCd')})['value']
schedule_info["arvRsStnCdNm"] = tr.find("input", {"name": re.compile(r'arvRsStnCdNm')})['value']
schedule_info["arvStnConsOrdr"] = tr.find("input", {"name": re.compile(r'arvStnConsOrdr')})['value']
schedule_info["arvStnRunOrdr"] = tr.find("input", {"name": re.compile(r'arvStnRunOrdr')})['value']
schedule_info["seatAttCd"] = tr.find("input", {"name": re.compile(r'seatAttCd')})['value']
schedule_info["scarGridcnt"] = tr.find("input", {"name": re.compile(r'scarGridcnt')})['value']
schedule_info["scarNo"] = tr.find("input", {"name": re.compile(r'scarNo')})['value']
schedule_info["seatNo_1"] = tr.find("input", {"name": re.compile(r'seatNo_1')})['value']
schedule_info["seatNo_2"] = tr.find("input", {"name": re.compile(r'seatNo_2')})['value']
schedule_info["seatNo_3"] = tr.find("input", {"name": re.compile(r'seatNo_3')})['value']
schedule_info["seatNo_4"] = tr.find("input", {"name": re.compile(r'seatNo_4')})['value']
schedule_info["seatNo_5"] = tr.find("input", {"name": re.compile(r'seatNo_5')})['value']
schedule_info["seatNo_6"] = tr.find("input", {"name": re.compile(r'seatNo_6')})['value']
schedule_info["seatNo_7"] = tr.find("input", {"name": re.compile(r'seatNo_7')})['value']
schedule_info["seatNo_8"] = tr.find("input", {"name": re.compile(r'seatNo_8')})['value']
schedule_info["seatNo_9"] = tr.find("input", {"name": re.compile(r'seatNo_9')})['value']
schedule_info["trainDiscGenRt"] = tr.find("input", {"name": re.compile(r'trainDiscGenRt')})['value']
schedule_info["rcvdAmt"] = tr.find("input", {"name": re.compile(r'rcvdAmt')})['value']
schedule_info["rcvdFare"] = tr.find("input", {"name": re.compile(r'rcvdFare')})['value']
schedule_info["trnNstpLeadInfo"] = tr.find("input", {"name": re.compile(r'trnNstpLeadInfo')})['value']
result.append(schedule_info)
return result
def fetch_stations(self):
res = self.session.get("https://etk.srail.kr/hpg/hra/01/selectMapInfo.do")
soup = BeautifulSoup(res.text, 'html.parser')
stations = soup.find_all("a", {"class": re.compile(r'map')})
result = dict()
for station in stations:
station_split = station['onclick'].split("'")
result[station_split[3]] = station_split[1]
return result
if __name__ == "__main__":
srt = SRT('1', '', '')
srt.login()
srt.is_logged_in()
schedules = srt.fetch_schedule('오송', '동탄', '20240110', '193100', 1, 0, 0, 0, 0)
print(schedules)
'프로젝트 > SRT&KTX 매진표 예매' 카테고리의 다른 글
SRT&KTX 기차표 매크로 예매 - (6) 아이디/비밀번호 저장하기 (0) | 2024.01.12 |
---|---|
SRT&KTX 기차표 매크로 예매 - (5) UI 만들기 (PyQt5) (0) | 2024.01.12 |
SRT&KTX 기차표 매크로 예매 - (4) SRT 승차권 예매 (1) | 2024.01.09 |
SRT&KTX 기차표 매크로 예매 - (2) SRT 로그인 (1) | 2024.01.08 |
SRT&KTX 기차표 매크로 예매 - (1) 계획 및 목표 (1) | 2024.01.08 |