구독 멤버쉽 쿠폰 코드가 매달 발행되고 매달 일일이 등록해줘야 하니 여간 귀찮은 일이 아니다.
그래서 파이썬 selenium + requests를 이용해 쿠폰을 긁어오고 자동으로 등록해주는 코드를 만들어야겠다는 생각이 들었다.
일단 나는 유플러스 유독에서 유튜브 프리미엄 + 리디 셀렉트 9,900원에 사용하고 있다. 일찍부터 시작해서 개이득
아무튼 작업 순서를 정리하자면
순서를 보면 간단하지만 손으로 하다보면 매달 쿠폰 놓치고 잊어먹는 일이 많았다.
(리디 셀렉트 굿. 하지만 종이책이 더 잘 읽힌다.)
일단 conda 가상환경을 만들고 진입 후 필요 모듈을 설치한다.
가상 환경 생성
conda create -n udok_venv python=3.8
가상 환경 진입
conda activate udok_venv
selenium, requests, pyperclip 설치
pip install selenium requests pyperclip
이제 설치가 완료되었다면 selenium의 webdriver를 열어 크롬 페이지를 열고 원하는 페이지 주소를 넣어준다면 화면이 열린다.
driver = webdriver.Chrome()
driver.get('https://www.lguplus.com/login/fallback')
이제 페이지가 열렸다면 내가 원하는 요소 element를 클릭을 해주어야 로그인 페이지로 넘어갈 수 있다.
driver의 find_element를 이용해 요소를 저장할 수 있다. 요소를 찾는데는 클래스, css 등 다양한 방법을 이용해서 찾을 수 있는데 더 편리하게 XPath로 찾을 것 이다.
XPath를 얻는 방법은 개발자 도구를 열어서 검사할 페이지 요소 선택클릭 후 복사 > XPath 복사하면 요소를 얻어 올 수 있다.

naver_login_box = driver.find_element(By.XPATH, '//*[@id="contentsSection"]/div/div/div/div/section/ul[1]/li[2]')
naver_login_box.click()
클릭 했다면 네이버 로그인 페이지가 열릴 것이다. 이제 아이디와 패스워드를 입력해야 하는데 일반적으로 selenium에서 send_keys 이용해 input 값을 입력할 수 있는데 이렇게 되면 네이버가 봇으로 탐지를 해 자동 로그인 방지 화면을 띄우게 된다.

이를 방지하기 위해서는 위에서 설치한 pyperclip 패키지를 이용해 클립보드, time.sleep() 을 이용해 방지할 수 있다.
naver_id_box = driver.find_element(By.XPATH, '//*[@id="id"]')
naver_pw_box = driver.find_element(By.XPATH, '//*[@id="pw"]')
naver_login_button = driver.find_element(By.XPATH, '//*[@id="log.login"]')
naver_id_box.click()
pyperclip.copy("") # 아이디 입력
naver_id_box.send_keys(Keys.CONTROL, 'v')
time.sleep(2)
naver_pw_box.click()
pyperclip.copy("") # 패스워드 입력
naver_pw_box.send_keys(Keys.CONTROL, 'v')
time.sleep(2)
naver_login_button.click()
중간에 time.sleep(2) 2초를 두어 자동 입력 방지를 막았다.
이제 로그인까지 완료했다. 웹 드라이버를 이용해서 페이지 진입해가면서 쿠폰 번호를 긁어올 수 있지만 진입 시간과 드라이버가 무겁기 때문에 requests를 이용해 쿠폰 번호를 요청하는 api를 사용하겠다.
유독에서 쿠폰 리스트를 받아오는 API를 분석해보니 GET 요청과 요청 헤더에 쿠키를 담아 보내는것을 확인했다. 그렇다면 로그인한 쿠키 세션들을 따로 저장해 requests > session > get 요청을 이용하면 되겠다.
(물론 requests의 get요청으로 수행해도 되지만 쿠키와 헤더를 업데이트해야 하기 때문에 Session을 사용해야 했었다.)
# driver cookie 딕셔너리화
_cookies = driver.get_cookies()
uplus_cookie_dict = {}
for cookie in _cookies:
uplus_cookie_dict[cookie['name']] = cookie['value']
# 쿠키 딕셔너리의 값들을 URL 인코딩
uplus_encoded_cookie_dict = {}
for key, value in uplus_cookie_dict.items():
if isinstance(value, str):
uplus_encoded_cookie_dict[key] = urllib.parse.quote(value)
else:
uplus_encoded_cookie_dict[key] = value
uplus_session = requests.Session()
uplus_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36'}
uplus_session.headers.update(uplus_headers)
uplus_session.cookies.update(uplus_encoded_cookie_dict)
res = uplus_session.get('https://www.lguplus.com/uhdc/fo/pogg/mypg/v1/coupon-list?cpnEposStusCd=UP&pcMblCd=P')
json_obj = json.loads(res.text)
위 과정을 거치고 나면 응답에서 쿠폰 리스트를 가져오면 끝이다.
자, 이제 절반 작업이 완료됐다. 이제 리디에 쿠폰만 등록하면 끝이다.
다시 driver에서 리디 셀렉트 페이지를 오픈하고 로그인을 하면 된다. 난 유독과 리디 셀렉트 모두 네이버 연동 로그인을 사용하기 때문에 로그인 과정은 위와 동일하게 처리를 하였다.
# 리디 셀렉트 로그인
driver.get('https://select.ridibooks.com/voucher')
ridi_login = driver.find_element(By.XPATH, '//*[@id="app"]/main/section/div/button')
ridi_login.click()
time.sleep(2)
try:
ridi_nvr_login1 = driver.find_element(By.XPATH, '//*[@id="__next"]/div/section/div/div/button[2]')
ridi_nvr_login1.click()
except Exception as e:
print("login1 element cannot find")
driver.quit()
try:
ridi_nvr_login2 = driver.find_element(By.XPATH, '//*[@id="__next"]/div/section/div/div[1]/button')
ridi_nvr_login2.click()
except Exception as e:
print("login2 element cannot find")
driver.quit()
그런데 문제가 있었다. 리디 셀렉트 로그인 페이지에서 네이버 로그인 이력이 있을 경우와 없을 경우 UI요소가 달라져 이를 구분했어야 했다. 따로 예외 처리가 필요했다.
이제 리디 셀렉트 로그인이 완료가 되었다면 쿠폰을 등록하는 API를 분석하면 끝!
마찬가지로 요청하려는 Session에 헤더와 쿠키를 동일하게 긁어오고 업데이트하면 된다.
등록하는 API는 Post요청에 json 데이터에
{
"voucher_code": req_coupon
}
를 담아서 보내면 된다.
이제 이 코드를 실행하면 리디 셀렉트에 매달 등록해서 전자책을 읽을 수 있다~