gencode
3067 0
PS4 프로 자동 구입 매크로 만들기 -5-
2017-01-16 20:14:52 - genonfire
2017-12-08 20:14:52
과도한 매크로 사용은 서버에 큰 부담이 될 수 있으므로 반복적인 작업을 자동화 하거나 테스트 용도로 한정해서 사용하시기 바랍니다. 매크로 사용 시 발생하는 모든 문제에 대한 책임은 전적으로 매크로 사용자 본인에게 있습니다.


마지막으로 주문서 작성을 해 보겠습니다. 이번엔 입력할 게 꽤 많아 보이지만 잘 분석해 보면 지금 껏 해 왔던 내용의 반복에 지나지 않습니다. 또 이후 과정이나 다른 쇼핑몰을 살펴봐도 결국 지금까지 해왔던 내용을 조금만 응용해 보면 다 할 수 있고, 쇼핑몰들 구성이 거의 비슷하기 때문에 어렵지 않습니다. 심지어는 여러 웹사이트를 같은 데서 만든 흔적도 보이는데 소스가 비슷하거나 XPATH로 찾아야 할 태그 이름마저 서로 동일한 곳도 있습니다.


배송정보입력


가장 처음 우리를 겁먹게 만드는 건 배송정보입력으로 이름, 연락처, 주소, 주문메세지까지 입력할 칸이 너무 많습니다만, 시나리오 짤 때도 경험했다시피 “위 정보와 같음”, “자택”에 체크하면 회원정보가 알아서 입력됩니다. 따라서 딱 두 줄만 짜면 되겠네요.

이를 위해 미리 회원 정보에 전화번호/주소 등을 정확히 입력해 둘 필요가 있습니다. 다른 시나리오에서 응용할 때도 미리 할 수 있는 건 해 놓으면 불 필요한 코드를 많이 줄일 수 있습니다. 특히 ActiveX 설치 팝업이 뜨면 망하는 경우도 있으니 미리 다 설치 해 두세요.

“위 정보와 같음” 그리고 “자택”을 각각 인스펙터로 살펴보겠습니다.



딱 봐도 간단히 될 거 같네요.


    samecheck = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='checkbox'][@name='same']"))).click()

    homeradio = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='radio'][@name='place'][@value='H']"))).click()


팝업 닫기




이 번엔 팝업을 닫아 보도록 하겠습니다. 이 팝업은 굳이 닫지 않아도 주문하는데 아무 지장이 없지만, 이런 경우가 왕왕 있기도 하고 간혹 필수로 처리해야 되는 경우도 있기 때문에 윈도우 다루는 법을 익혀 둘 필요가 있습니다.


def closePopups(driver, default_window):
    handles = list(driver.window_handles)
    if (len(handles) > 1):
        for handle in handles:
            if (handle != default_handle):
                driver.switch_to_window(handle)
                driver.close()
                handles.remove(handle)
                driver.switch_to_window(default_handle)


새로운 함수를 만들었습니다. 이 closePopups() 함수는 현재 webdriver가 갖고 있는 윈도우를 확인한 후 여러 개일 경우 기본 윈도우를 제외한 나머지를 다 닫는 역할을 합니다. 이 함수를 order() 함수에서 불러주면 될 거 같습니다. default_window라고 새로운 변수가 생겼는데 이건 기본 윈도우인지를 확인하기 위해 추가한 겁니다. 아래 처럼 팝업이 뜨기 전에 현재 윈도우 핸들 값을 갖고 있다가 나중에 비교하는데 사용하면 됩니다.


    default_handle = driver.current_window_handle
    order(driver, default_handle)


추가로 이 시나리오에선 사용하지 않지만, 가끔 자바 스크립트로 된 팝업을 띄우는 곳도 있습니다.




이런 류의 팝업을 없애려면 아래처럼 하면 되고, 확인이 아닌 취소 버튼을 누르려면 alert.accept() 대신 alert.dismiss() 로 넣어주면 됩니다.


    WebDriverWait(driver, 5).until(EC.alert_is_present())
    alert = driver.switch_to_alert()
    alert.accept()


적립금 사용


이번엔 인터넷 쇼핑에서 가장 중요한 적립금을 써 보도록 하겠습니다. 우선 적립금을 쓰기 위한 로직을 정리해 보면 오른쪽의 사용가능 적립금이 얼마인지를 확인한 다음 100원 이상이면 100원 단위로 잘라서 왼쪽의 사용할 적립금 부분에 입력하는 방식이네요.



역시 인스펙터로 두 적립금 박스를 살펴 보겠습니다.




하나씩 살펴보니 역시 어렵지 않게 처리할 수 있을 것 같습니다. 늘 하던대로 XPATH로 찾고 value 값을 get_attribute()로 가져온 후 그 중 얼마를 써야하는지 계산하고 왼쪽 박스에 send_keys()로 보내면 딱 되겠네요. 하면 이렇게 됩니다.


    point = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='text'][@name='okreserve']")))
    mypoint = int(point.get_attribute("value"))
    print "point: %d" % mypoint
    if (mypoint >= 100):
        pointinput = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='text'][@name='usereserve']")))
        usepoint = mypoint / 100 * 100
        pointinput.send_keys(usepoint)
        print "use point: %d" % usepoint


다시 스크립트를 실행해 보면 포인트 계산도 잘 되고 파워쉘에 로그도 잘 찍히고 있네요.




마무리


이상으로 python + selenium 을 이용한 매크로 작성법 포스팅을 마칩니다. 지금까지 나왔던 내용을 잘 응용하고, 구글링을 동반하면 새로운 시나리오에 대해서도 별 무리없이 작성이 가능할 겁니다. 다시 한 번 강조하지만 매크로 사용에 각별히 주의하시고 되팔렘 물건은 사지도 팔지도 맙시다. 끝으로 지금까지 작성한 전체 소스입니다.


https://github.com/genonfire/macpro


#-*- 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"
ITEMURL = PS4PRO

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 closePopups(driver, default_window):
    handles = list(driver.window_handles)
    if (len(handles) > 1):
        for handle in handles:
            if (handle != default_handle):
                driver.switch_to_window(handle)
                driver.close()
                handles.remove(handle)
                driver.switch_to_window(default_handle)

def order(driver, default_handle):
    samecheck = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='checkbox'][@name='same']"))).click()

    homeradio = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='radio'][@name='place'][@value='H']"))).click()

    closePopups(driver, default_handle)

    point = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='text'][@name='okreserve']")))
    mypoint = int(point.get_attribute("value"))
    print "point: %d" % mypoint
    if (mypoint >= 100):
        pointinput = WebDriverWait(driver, WAITTIME).until(EC.presence_of_element_located((By.XPATH, "//input[@type='text'][@name='usereserve']")))
        usepoint = mypoint / 100 * 100
        pointinput.send_keys(usepoint)
        print "use point: %d" % usepoint

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)

    default_handle = driver.current_window_handle
    order(driver, default_handle)
이 글이 마음에 드셨다면.. 1
gencode 의 다른 포스트
tbs 김어준의 뉴스공장 팟캐스트 RSS 생성기
favicon 만들기
네이버 사전에 네이버 번역 API 연동하기 (파파고)
> PS4 프로 자동 구입 매크로 만들기 -5-
PS4 프로 자동 구입 매크로 만들기 -4-
PS4 프로 자동 구입 매크로 만들기 -3-
PS4 프로 자동 구입 매크로 만들기 -2-
댓글 [ 0 ]