과도한 매크로 사용은 서버에 큰 부담이 될 수 있으므로 반복적인 작업을 자동화 하거나 테스트 용도로 한정해서 사용하시기 바랍니다. 매크로 사용 시 발생하는 모든 문제에 대한 책임은 전적으로 매크로 사용자 본인에게 있습니다.
본래 시나리오는 품절인지 계속 확인하다가 재고가 있으면 구매하기 버튼을 누르는 건데, 이게 현실에선 테스트가 힘들겠죠? 따라서 임의로 테스트 환경을 만들어야 합니다. 때문에 일단 구매가 가능한 물품 페이지로 가서 품절일 때와의 차이를 확인해 보겠습니다. ITEMURL을 기능 구현이 완료될 때 까지 잠시 봐꿔 두도록 하겠습니다.
HOMEPAGE = "http://gamewoori.com/shop/member.html?type=login" PS4PRO = "http://gamewoori.com/shop/shopdetail.html?branduid=885806&xcode=009&mcode=001&scode=&type=X&search=&sort=regdate" PS4SLIM = "http://gamewoori.com/shop/shopdetail.html?branduid=885764&xcode=009&mcode=001&scode=&type=X&search=&sort=regdate" ITEMURL = PS4SLIM
이미지 상에 체크한대로 빨간 상자의 총 상품 금액(품절이면 0원, 재고 있으면 실제 금액)이나 파란 상자의 구매하기 버튼 등을 비교할 수 있을 것 같네요. 이미지 찾는 건 많이 해 봤으니 새로운 시도를 위해 이번엔 빨간 상자의 총 상품 금액을 비교하는 방법으로 checkStock() 함수를 만들도록 하겠습니다.
우선 기존 소스에서 checkStock()을 부르는 부분을 살펴보면 checkStock() 함수가 True일 경우 계속 반복하도록 되어 있습니다. 따라서 checkStock() 함수는 재고가 없으면 return True, 재고가 있으면 return False를 해줘야 겠네요.
i = 1 while(checkStock(driver, i)): i += 1 time.sleep(SLEEPSEC) if (i > LOOP and LOOP != -1): break driver.get(ITEMURL)
이제 품절인 아이템, 재고가 있는 아이템의 금액(0원/378,000원)에 대해 각각 요소 검사를 실행해 봅니다.
둘 다 똑같은 <strong id=”MK_p_total” class=”MK_total”></strong> 인데 가운데 금액만 차이가 나네요. 따라서 XPATH로 id가 ‘MK_p_total’인 strong 태그를 찾은 후 그 안에 있는 금액 부분을 확인해서 0이면 return True, 아니면 return False를 하면 될 것 같습니다.
def checkStock(driver, i): mktotal = driver.find_element_by_xpath("//strong[@id='MK_p_total']") totalPrice = mktotal.get_attribute("innerHTML") if (totalPrice == "0"): print('[%d]%s' % (i, 'out of stock')) return True else: print "Go! Checkout~" return False
<strong></storong> 사이의 금액 부분을 가져오기 위해 .get_attribute(“innerHTML”)을 썼습니다. 이제 스크립트를 실행 후 파워쉘에 출력되는 로그를 살펴봅시다. 품절일 경우 out of stock 이 반복해서 찍혀야 하고, 재고가 있으면 Go! Checkout~ 이 찍혀야 합니다.
원하던 대로 출력이 되는 것 같습니다. 품절인 상태에서 계속 out of stock 로그를 찍으면서 반복하다 서버상 재고가 있음으로 바뀌면 Go! Checkout~을 찍는지를 확인해보고 싶지만 이건 테스트가 힘드니 될거라고 믿고 넘어가겠습니다. 또 현재는 재고확인을 딱 3번만 하는데 주석에 적혀 있듯 3을 -1로 바꾸면 재고가 있을 때 까지 무한 루프를 돌게 됩니다.
LOOP = -1
이제 재고가 있을 때 바로구매하기 버튼을 누르는 checkout() 함수를 만들어 보겠습니다. 지난 번 로그인할 때도 그랬듯이 동작이 한 개니까 한 줄이면 될 것 같네요.
하이라이트된 img를 XPATH로 찾을 수도 있지만, 이번에도 <a href=”JavaScript:send_multi(”, ‘baro’, ”);”>가 보이네요. 역시 바로구매하기 버튼을 누르면 이 JavaScript가 실행되는 구조이므로 이 스크립트를 실행하도록 하겠습니다.
def checkout(driver): driver.execute_script("JavaScript:send_multi('', 'baro', '')");
이제 다시 스크립트를 실행해 보면 바로구매하기 버튼이 눌린 것 처럼 주문서작성 화면으로 넘어가네요. 여기까지의 전체 소스입니다. 다음 포스팅에선 주문서작성을 마무리하도록 하겠습니다.
#-*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time import sys reload(sys) sys.setdefaultencoding('utf-8') HOMEPAGE = "http://gamewoori.com/shop/member.html?type=login" PS4PRO = "http://gamewoori.com/shop/shopdetail.html?branduid=885806&xcode=009&mcode=001&scode=&type=X&search=&sort=regdate" PS4SLIM = "http://gamewoori.com/shop/shopdetail.html?branduid=885764&xcode=009&mcode=001&scode=&type=X&search=&sort=regdate" ITEMURL = PS4SLIM USERID = "" PASSWORD = "" WAITTIME = 1000 SLEEPSEC = 5 LOOP = 3 # -1 for infinite def login(driver): WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//td/input[@name='id']"))).send_keys(USERID) driver.find_element_by_xpath("//td/input[@name='passwd']").send_keys(PASSWORD) driver.execute_script("JavaScript:check()") WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, "//a[@href='/html/mainm.html?type=logout ']"))) def checkStock(driver, i): mktotal = driver.find_element_by_xpath("//strong[@id='MK_p_total']") totalPrice = mktotal.get_attribute("innerHTML") if (totalPrice == "0"): print('[%d]%s' % (i, 'out of stock')) return True else: print "Go! Checkout~" return False def checkout(driver): driver.execute_script("JavaScript:send_multi('', 'baro', '');") def order(driver): print '주문서 작성 함수' if __name__ == "__main__": driver = webdriver.Firefox() driver.wait = WebDriverWait(driver, 2) driver.get(HOMEPAGE) login(driver) driver.get(ITEMURL) i = 1 while(checkStock(driver, i)): i += 1 time.sleep(SLEEPSEC) if (i > LOOP and LOOP != -1): break driver.get(ITEMURL) checkout(driver) order(driver)
궁금한게 있는데요. 지금 같은 사이트로 따라서 만들어보는중에 보니 품절 상품도 가격이 그대로 올라와 있더라구요.
이런 경우 sold out 이미지로 if문을 만들어야 할 것 같은데 어떻게 진행해야할지 감이 안잡히네요...
혹시 조언을 좀 주실 수 있을까요?
시작한지가 얼마 안되서 잘 모르는게 많습니다 ㅜ
def checkStock(driver, i):
soldout = driver.find_element_by_xpath("//div[@class='prd-btns']")
checksoldout = soldout.get_attribute("innerHTML")
if (checksoldout == "상품이 품절되었습니다."):
print('[%d]%s' % (i, 'out of stock'))
return True
else:
print "Go! Checkout~"
return False
이부분을
if ("상품이 품절되었습니다." in resStr):
이걸로 바꿔보세요