패스트 캠퍼스 AI LAB 3기 과정 2주차에 하는 SRT 자동 예매 예제 입니다.
실제는 Slack에 보내는 법을 배우는데 솔찍히 slack보다는 카톡 으로 알려줘야 하지 않겠나 싶어 따로 PyKakao를 공부했습니다.
뭐 메세지 보내는 API야 대충 블로그들 보고 따라하니 너무 좋더라구요.
아무튼 하는 방법 하나씩 정리해 보겠습니다!!
1. KAKAO DEVELOPER 설정
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
카카오 디벨로퍼에 들어가서 설정 붙어 해야해요!!
들어가면 아래 같은 화면이 나올거에요.
# 1. 내 애플리케이션 클릭!!
# 2. 애플리케이션 추가
# 3 정보(앱이름, 사업자명, 카테고리) 설정
# 4. 카카오 로그인 활성화 설정 ON
# 5. Redirect URI 에 localhost 추가!!!
같은 카카오 로그인 페이지에서 아래로 스크롤 하면 있습니다!!
# 6. 동의 항목 설정
카카오 로그인 밑에 있는 동의 항목으로 이동후 다음과 같이 설정해주세요!
# 7 API KEY 가져오기
이러면 설정 끝입니다!!! 다음은 코드로 가겠습니다!!!
2. 코드 구현
https://github.com/tjsgh531/SRT_crawling/tree/main
GitHub - tjsgh531/SRT_crawling: -selenium
-selenium. Contribute to tjsgh531/SRT_crawling development by creating an account on GitHub.
github.com
완성본은 깃허브를 통해 받아 볼 수 있습니다!!
2-1 코드 Flow
SRT 페이지에 들어가서 예매를 광클 해주는 것은 Selenium 이란 라이브러리로 구현 하고
카카오톡으로 메세지 전송해 주는 것은 Pykakao 라이브러리로 구현합니다.
- # 1. 카카오 로그인 (PyKakao)
- # 2. 카카오로 너한테 메세지 보내도 되는지 auth 관련 code 받기 (PyKakao)
- # 3. SRT에 들어가요! (selenium)
- # 4. SRT 로그인을 합니다. (selenium)
- # 5. 예매 페이지로 갑니다 (selenium)
- # 6. 원하는 출발지/도착지/시간 을 입력 시킵니다. (selenium)
- # 7. 매진이 없어질때 까지 광클 합니다! (selenium)
- # 8. 예약을 성공적으로 누르면 카카오톡에 메세지를 보냅니다 (PyKakao)
2-2 코드
참고로 저는 jupyter notebook에서 실행 했습니다.
colab은 selenium 사용하기 위해서 귀찮은 설정을 많이 해줘야 해서 추천 안합니다. 저도 평소는 colab 파입니다.
selenium에서 요소를 찾을 때, wait.unitl(EC.presence_of_element_located()) 함수를 사용했습니다.
find_element() 아시는 분은 사용해도 상관 없습니다!!!
둘의 차이는 그저 명시적 기다림 유무라 제가 사용한 것이 안전하지만 아래로 적어도 왠만해서 오류 안나요.
# 0. 설치 및 환경 설정
- 라이브러리(selenium, webdriver-manager, pykakao) 설치
# selenium 설치
!pip install selenium
# webdriver manager 설치
!pip install WebDriver-Manager
# pykakao 설치
!pip install PyKakao
- 필요 모듈 import
# selenium & webdriver-manager 관련
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
# pykakao 관련
from PyKakao import Message
- 브라우저 띄우기
ChromeDriverManager().install()
# 크롬으로 창 띄우기
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)
# 1. 카카오 로그인
- auth url 로 들어가자!
api_key = '복사해 둔 Kakao API KEY'
API = Message(service_key = api_key)
auth_url = API.get_url_for_generating_code()
browser.get(auth_url)
- kakao 로그인
import getpass
kakao_id = input("카카오 아이디 입력 : ")
kakao_pw = getpass.getpass("카카오 pw입력: ")
kakao_id_input = wait.until(EC.presence_of_element_located((By.ID, 'loginId--1')))
kakao_pw_input = wait.until(EC.presence_of_element_located((By.ID, 'password--2')))
kakao_submit_btn = browser.find_element(By.CLASS_NAME, 'btn_g')
kakao_id_input.clear()
kakao_pw_input.clear()
kakao_id_input.send_keys(kakao_id)
kakao_pw_input.send_keys(kakao_pw)
kakao_submit_btn.click()
print("카카오 앱에서 확인을 눌러주세요!")
# 2. 카카오로 너한테 메세지 보내도 되는지 auth 관련 code 받기
- 로그인 성공시 code 받는 url 들어갈 수 있다.
kakao_agree_btn = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'btn_agree')))
kakao_agree_btn.click()
- code는 url 주소에서 'code=~' 라고 표시 되어 있음. 그래서 그 뒤 string을 가져오는 작업(이때 404 NOT FOUND 같은 창이 뜨는데 신경 안써도 됩니다!!! 우리에게 필요한건 오직 url 주소!!!)
import re
code_url = browser.current_url
print(f"현재 url : {code_url}")
code = re.search(r"code=(.+)", str(code_url))
code = code.group(1)
print(f"code : {code}")
# 3 SRT에 들어가요!
url = 'https://etk.srail.kr/cmc/01/selectLoginForm.do?pageId=TK0701000000' # SRT 로그인 페이지 URL
browser.get(url)
# 4. SRT 로그인 합시다!
email = input("ID(이메일)를 입력해 주세요 : ")
pw = getpass.getpass("PW를 입력해 주세요 : ")
email_login_btn = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="srchDvCd2"]')))
email_login_btn.click()
id_input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="srchDvNm02"]')))
pw_input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="hmpgPwdCphd02"]')))
submit_btn = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="login-form"]/fieldset/div[1]/div[1]/div[3]/div/div[2]/input')))
id_input.clear()
pw_input.clear()
id_input.send_keys(email)
pw_input.send_keys(pw)
submit_btn.click()
# 5. 예매 페이지 갑시다!
booking_url = 'https://etk.srail.kr/hpg/hra/01/selectScheduleList.do?pageId=TK0101010000'
browser.get(booking_url)
# 6. 원하는 출발지/도착지/출발시간 입력받습니다!
- 출발지 / 도착지 입력 받아 브라우저 입력 하는 부분에 전달
departure = input("어디서 출발하나요? : ")
destination = input("어디로 갈까요? : ")
departure_input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="dptRsStnCdNm"]')))
destination_input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="arvRsStnCdNm"]')))
departure_input.clear()
destination_input.clear()
departure_input.send_keys(departure)
destination_input.send_keys(destination, Keys.ENTER)
- 시간 입력 받은 후 해당 정보로 검색
time_input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="dptTm"]')))
times = time_input.find_elements(By.TAG_NAME, 'option')
search_btn = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="search_top_tag"]/input')))
for time in times:
print(f"{time.text}시", end=" / ")
wanted_time = int(input("가 있습니다. 몇 시로 예매 할까요? : "))
for time in times:
if wanted_time == int(time.text):
time.click()
break
search_btn.click()
# 7. 매진 아닐때 까지 광클!!
import time
while True:
special_seat = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="result-form"]/fieldset/div[6]/table/tbody/tr[1]/td[6]')))
economy_seat = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="result-form"]/fieldset/div[6]/table/tbody/tr[1]/td[7]')))
is_special_seat = False
is_economy_seat = False
if '예약 하기' in special_seat.text:
is_special_seat = True
if '예약 하기' in economy_seat.text:
is_economy_seat = True
if is_special_seat:
print("특실 자리를 예매할 수 있어요!!")
special_seat_btn = special_seat.find_element(By.TAG_NAME, 'a')
special_seat_btn.click()
break
if is_economy_seat:
print("일반실 자리를 예매할 수 있어요!!")
economy_seat_btn = economy_seat.find_element(By.TAG_NAME, 'a')
economy_seat_btn.click()
break
print("예약 할 수 있는 표가 없어요.. 광클 합니다")
browser.refresh()
time.sleep(3)
search_btn = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'btn_large ')))
search_btn.click()
# 8. 자리가 있으면 카톡으로 메세지를 보내자!!
import requests
url = 'https://kauth.kakao.com/oauth/token'
redirect_uri = 'https://localhost:5000'
data = {
'grant_type' : 'authorization_code',
'client_id' : api_key,
'redirect_uri' : redirect_uri,
'code' : code,
}
response = requests.post(url, data=data)
tokens = response.json()
import json
booking_url = browser.current_url
url="https://kapi.kakao.com/v2/api/talk/memo/default/send"
# kapi.kakao.com/v2/api/talk/memo/default/send
headers={
"Authorization" : "Bearer " + tokens["access_token"]
}
data={
"template_object": json.dumps({
"object_type":"text",
"text":f"예약에 성공했습니다! 10분 내로 결제하러 가세요!! {booking_url}",
"link":{
"web_url":"www.naver.com"
}
})
}
response = requests.post(url, headers=headers, data=data)
response.status_code
print(response.status_code)
if response.json().get('result_code') == 0:
print('메시지를 성공적으로 보냈습니다.')
else:
print('메시지를 성공적으로 보내지 못했습니다. 오류메시지 : ' + str(response.json()))
'EDA > selenium' 카테고리의 다른 글
selenium 라이브러리 함수 정리 (0) | 2024.04.04 |
---|---|
selenium으로 크롤링 하기(실습 예제) (0) | 2024.04.04 |