- 전체
- Python 일반
- Python 수학
- Python 그래픽
- Python 자료구조
- Python 인공지능
- Python 인터넷
- Python SAGE
- wxPython
- TkInter
- iPython
- wxPython
- pyQT
- Jython
- django
- flask
- blender python scripting
- python for minecraft
- Python 데이터 분석
- Python RPA
- cython
- PyCharm
- pySide
- kivy (python)
Python 인터넷 PS4 프로 자동 구입 매크로 만들기 -5-
2020.11.21 23:56
PS4 프로 자동 구입 매크로 만들기 -5-

과도한 매크로 사용은 서버에 큰 부담이 될 수 있으므로 반복적인 작업을 자동화 하거나 테스트 용도로 한정해서 사용하시기 바랍니다. 매크로 사용 시 발생하는 모든 문제에 대한 책임은 전적으로 매크로 사용자 본인에게 있습니다.
마지막으로 주문서 작성을 해 보겠습니다. 이번엔 입력할 게 꽤 많아 보이지만 잘 분석해 보면 지금 껏 해 왔던 내용의 반복에 지나지 않습니다. 또 이후 과정이나 다른 쇼핑몰을 살펴봐도 결국 지금까지 해왔던 내용을 조금만 응용해 보면 다 할 수 있고, 쇼핑몰들 구성이 거의 비슷하기 때문에 어렵지 않습니다. 심지어는 여러 웹사이트를 같은 데서 만든 흔적도 보이는데 소스가 비슷하거나 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)
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.

