본문 바로가기

python/인터파크티켓

인터파크티켓 매크로 만들기 1



인터파크 티켓 사이트 변경이 있어서 이 글 따라서 만들면 돌아가지 않습니다 .

 

어차피 만들어 나가는 과정을 다 적어놔서 알아서 해결한 분들고 계실거라 생각이 들지만....
수정해서 새로 글작성 하겠습니다


python sellenium을 이용해 인터파크 티켓을 자동으로 예매하는 프로그램을 만들었습니다.

 

사용하던 매크로 프로그램이 있는데 안된다 하며 만들 줄 아냐해서 만들기 시작.

 

현재 미니맵이 없는 공연은 자동 예매가 되는 거 까진 확인 했는데..... 실전에서 빠르게 예매를 할 수 있는지는 알 수가 없....

 

이 글은 python, sellenium의 사용법에 대한 설명은 빼고 적었습니다.


 

sellenium은 직접 브라우저를 실행시켜서 자동으로 동작을 하는데, 여기에선 크롬 드라이버를 사용했습니다.

크롬 말고 파이어폭스도 사용 가능합니다.

 

1.

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome('./chromedriver.exe')
# 사이즈조절
driver.set_window_size(1400, 1000)  # (가로, 세로)
driver.get('https://ticket.interpark.com/Gate/TPLogin.asp') # 페이지 이동

크롬 드라이버를 이용해 인터파크 티켓 로그인 페이지에 접속합니다.

 

2.

driver.switch_to.frame(driver.find_element(By.XPATH, "//div[@class='leftLoginBox']/iframe[@title='login']"))
userId = driver.find_element(By.ID, 'userId')
userId.send_keys('ID') # 로그인 할 계정 id
userPwd = driver.find_element(By.ID, 'userPwd')
userPwd.send_keys('PASSWORD') # 로그인 할 계정의 패스워드
userPwd.send_keys(Keys.ENTER)

 

페이지에 iframe이 있고 내가 찾고 싶은 게 iframe 안에 있다면 switch_to.frame() 메서드를 사용해서 iframe을 선택해줍니다.

아래 인터파크 티켓 사이트 로그인 페이지인데, F12를 눌러 개발자 도구를 켜면 볼 수 있습니다.

선택하고 싶은 iframe이 id, name가 없어서 상위 태그와 title속성을 이용해서 찾아줬습니다.

(iframe은 로그인뿐 아니라 티켓을 예매할 때도 많이 보인다. )

 

[iframe 로그인폼.]

 

find_element() 메서드를 사용해 아이디와, 비밀번호를 입력해준 후 비밀번호 입력 후 엔터키를 입력해 줘서 로그인해줍니다.

아래 캡처 사진을 보면 아이디, 비밀번호 입력해주는 input 태그에 id와 name 속성이 있습니다.

이중 id속성을 이용해서 태그를 찾아줄 수 있습니다.

 

[아이디, 비밀번호]

 

3.

driver.get('http://ticket.interpark.com/Ticket/Goods/GoodsInfo.asp?GoodsCode=' + 'goodsCode')

goodsCode는 내가 예매하고 싶은 공연을 찾아서 상세페이지에 들어가면, 링크 주소에서 확인할 수 있습니다.

아래 링크에 끝부분의 숫자입니다. (# 제외)

 

 

 

4.

# 예매하기 버튼 클릭
driver.find_element(By.XPATH, "//div[@class='tk_dt_btn_TArea']/a").click()

# 예매하기 눌러서 새창이 뜨면 포커스를 새창으로 변경
driver.switch_to.window(driver.window_handles[1])
driver.get_window_position(driver.window_handles[1])

# 예매안내가 팝업이 뜨면 닫기. ( ticketingInfo_check : True, False )
ticketingInfo_check = self.check_exists_by_element(By.XPATH, "//div[@class='layerWrap']/div[@class='titleArea']/a[@class='closeBtn']")
if ticketingInfo_check:
    driver.find_element(By.XPATH, "//div[@class='layerWrap']/div[@class='titleArea']/a[@class='closeBtn']").click()

개발자 도구를 실행시켜 예매하기 버튼의 위치를 찾아 click() 메서드를 이용해서 예매하기를 클릭해줍니다.

여기서 class속성이 tk_dt_btn_TArea의 자식 중 a태그가 한 개라서 find_element() 메서드 사용이 가능합니다.

태그가 복수로 나온다면 find_elements()를 사용해야 합니다. (나중에 sellenium 메서드 사용법을 정리 필요)

 

 

예매안내 팝업이 뜨는지 체크하는 메서드는 웹페이지 안에 내가 원하는 태그가 있는지를 체크해주는 식으로 만들어 줍니다.  

변수로 넣어준 태그가 없다면 에러가 발생하는데, 에러가 발생하지 않으면 내가 찾는 태그가 있다를 의미합니다.

from selenium.common.exceptions import NoSuchElementException

# 태그가 없으면 에러발생
def check_exists_by_element(by, name):
    try:
        driver.find_element(by, name)
    except NoSuchElementException:
        return False
    return True

 

 

5. 

# 날짜 아이프레임
driver.switch_to.frame(driver.find_element(By.XPATH, "//div[@class='contL']/iframe[@id='ifrmBookStep']"))

# 월 체크
calHead = driver.find_elements(By.XPATH, "//div[@class='calHead']/div[@class='month']/span")
year_month = calHead[1].find_elements(By.XPATH, "//em")
year = year_month[0].text  # 년
month = year_month[1].text  # 월

yearC = wantYear - int(year)	# wantYear : 예매 원하는 년
monthC = wantMonth - int(month)	# wantMonth : 예매 원하는 월

s = yearC * 12 + monthC
i = 0
# 월 이동
if s > 0:
    while i < s:
        calHead[2].click()
        i = i + 1
        calHead = driver.find_elements(By.XPATH, "//div[@class='calHead']/div[@class='month']/span")
elif s < 0:
    while i < s:
        calHead[0].click()
        i = i - 1
        calHead = driver.find_elements(By.XPATH, "//div[@class='calHead']/div[@class='month']/span")

# 선택 가능한 날짜 모두 불러오기
CellPlayDate = driver.find_elements(By.NAME, "CellPlayDate")

# 일 선택
for cell in CellPlayDate:
    if cell.text == wantDate:	# wantDate : 예매 원하는 일
        cell.click()
        break

내가 예매하고 싶은 날짜를 선택하기 위해서 현재 화면의 달력과 비교를 해서 이동 후 선택할 수 있게 합니다.

선택 가능한 날짜에 name 속성이 CellPlayDate로 고정되어 있습니다. 이걸 이용해서 날짜들을 불러와 줍니다.

불러온 날짜들의 숫자를 비교해 선택을 click() 메서드를 이용해 클릭을 해줍니다.

 

아래 사진 순서대로 iframe, 월 이동, 일 태그 확인할 수 있습니다.

 

[iframe]
[월 선택]
[일 선택]

 

 

6.

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 시간 클릭 전 활성화 대기
# 태그가 만들어 질 때 까지 30초간 기다림
# 30초전 태그가 활성화 되면 바로 실행
time_li = WebDriverWait(driver, 30).until(
                EC.presence_of_all_elements_located((By.ID, "CellPlaySeq"))
            )

# hour : 예매하고 싶은 회차 시
# min_ : 예매하고 싶은 회차 분
hm = hour + "시 " +  min_ + "분"

for li in time_li:
    if li.text == hm:
        li.click()
        break

# iframe의 부모 프레임으로 돌아가기
driver.switch_to.default_content()

# 다음버튼 클릭
next = WebDriverWait(driver, 30).until(
                EC.presence_of_all_elements_located((By.XPATH, "//div[@class='contR']/div[@class='buy_info']/p[@id='LargeNextBtn']/a/img"))
            )
next[0].click()

5. 에서 날짜 선택을 하면 바로 오른쪽에 회차가 활성화가 됩니다.

1개 회차만 있다면 자동으로 선택이 되지만, 2개 이상일 경우 직접 선택을 해줘야 합니다.

여기에선 원하는 시, 분을 이용해 선택 하지만 순서를 이용해 선택할 수도 있습니다.

회차 선택이 끝나고 다음 버튼을 눌러줘야 하는데 다음 버튼은 iframe안에 있는 게 아니라서 부모 프레임으로 이동 후 클릭해줘야 합니다.

 

7.

# 자동예매 방지 문자열입력이 떠있는지 확인
driver.switch_to.frame(driver.find_element(By.XPATH, "//div[@id='divBookSeat']/iframe[@id='ifrmSeat']"))
capchaLayer_check = self.check_exists_by_element(By.XPATH, "//div[@id='divRecaptcha']")

# 자동예매 방지 문자열 입력창이 있다면 5초 대기
if capchaLayer_check:
    time.sleep(5)

공연에 따라 자동 예매 방지 문자열 입력을 하라고 팝업창이 나올 수가 있습니다.

이건....  자동으로 입력이 불가능해서 사용자가 입력할 시간을 기다려 준 후 움직이게 해 줍니다.

대기시간을 5초는 입력하는 시간보다 많이 길 수 있어서 원하는 대로 줄여도 무방합니다.

 

8.

# 좌석 선택 iframe
driver.switch_to.frame(driver.find_element(By.XPATH, "//div[@class='seatL']/iframe[@id='ifrmSeatDetail']"))

# 활성화 되어 있는 좌석의 class 속성 stySeat
seat_check = driver.find_element(By.CSS_SELECTOR, "img.stySeat")
seat_title = seat_check.get_attribute('title')
b = seat_title.split('-')

# 좌석 선택하는 태그의 title 속성의 포멧  
# [VIP석] 1층-A구역18열-11
# [VIP석] 1층-B구역 11열-1
# [VIP석] 1층-D열-99
# [VIP석] 1층-11열-11
# [VIP석] 1층-A블럭8열-10

if '구역' in b[1]:
    if b[1][b[1].find('역') + 1] == ' ':
        zone_seat_return = self.seat_title_checking1
    else:
        zone_seat_return = self.seat_title_checking2
 elif '블럭' in b[1]:
    zone_seat_return = self.seat_title_checking3
 else:
    c = re.compile('[0-9]')
    if c.match(b[1]):
        zone_seat_return = self.seat_title_checking4
    else:
        zone_seat_return = self.seat_title_checking5

# 좌석 선택
w_check = False
seat = 0
cnt = 0
while seat < 20:
    seat = seat + 1
    # zon_seat_return의 매개변수 설명
    # level : VIP, R, A  등 좌석의 등급
    # block : A, B, C 등 좌석의 구역을 설정
    # seat : 숫자 또는 영어. 열을 지정
    seat_string = zone_seat_return(level, block, seat)	
    imgs = driver.find_elements(By.CSS_SELECTOR, "img.stySeat" + seat_string)

    for i in imgs:
        i.click()
        cnt = cnt + 1
        if cnt == int(people_):
            w_check = True
            break

    if w_check:
        break
        
# 원래 팝업 프레임으로 돌아가기
driver.switch_to.default_content()
driver.switch_to.frame(driver.find_element(By.XPATH, "//div[@id='divBookSeat']/iframe[@id='ifrmSeat']"))
# 다음 버튼 클릭
driver.find_element(By.XPATH, "//div[@class='seatR']/div[@class='inner']/div[@class='btnWrap']/a/img").click()

좌석 선택을 할 때 내가 원하는 좌석을 지정해서 선택을 하고 싶어서 title속성에 좌석 좌표를 이용해서 원하는 좌석을 선택할 수 있게 해 줍니다.

5개의 포맷 외 다른 좌표도 있을 수 있습니다.

명확한 좌석을 선택하기보단 등급과 구역, 열 까지만 지정해서 좌석을 선택해 줍니다.

좌석 선택 시 미니맵이 없는 공연일 때만 동작합니다.

def seat_title_checking1(level, block, seat):
    return "[title*='" + level + "석'][title*='" + block + "구역 " + str(seat) + "열']"

def seat_title_checking2(level, block, seat):
    return "[title*='" + level + "석'][title*='" + block + "구역" + str(seat) + "열']"

def seat_title_checking3(level,  block, seat):
    return "[title*='" + level + "석'][title*='" + block + "블럭" + str(seat) + "열']"

def seat_title_checking4(level, block, seat):
    return "[title*='" + level + "석'][title*='-" + str(seat) + "열']"

def seat_title_checking5(level, block, seat):
    return "[title*='" + level + "석'][title*='-" + chr(64 + seat) + "열']"

 

8. 까지 모두 정상적으로 동작이 되면, 아래와 같은 화면으로 넘어가게 됩니다.

3단계부터일 땐 직접 선택해도 문제가 없을 거라 보여 개발하지 않았습니다.

이후 단계 모두 다 자동으로 하고 싶다면 F12로 개발자 도구를 켜 필요한 정보를 찾고 개발하는데 어려움은 없을 거라고 봅니다.

 

 

 

귀찮아서 대충 아무렇게나 만들어서 이상해 보이는 곳이 종종 보이지만 수정은 나중에.....

 

다음엔 화면을 구성해서 원하는 공연 정보를 입력해서 자동 예매하는 방법에 대해 알아보겠습니다.

'python > 인터파크티켓' 카테고리의 다른 글

인터파크티켓 매크로 만들기? 3  (81) 2022.01.11
인터파크티켓 매크로 만들기 2  (28) 2021.02.18