시작하기 전..
매크로를 이용해 예매한 티켓을 정가가 아닌 값에 재판매하면 불법이지만
스스로 제작한 매크로를 사용하는 것 자체는 불법이 아니라는 글을 봤기에 이 글을 작성합니다..
(아니라면 알려주세요!! 내리겠습니다!!)
최근에 저에게는 두 번의 티켓팅이 있었습니다
제가 정말 사랑하는 성진 쿤의 리사이틀 티켓팅이 무려 하루에 2시간 간격으로 두 번이나 있었습니다
그리고 아니나 다를까...
그래서 저는 결심합니다...
매번 남의 손 빌리기도 그렇고 내 손으로 좀 잡아보자....
근데 어케하지...
..!! 매크로!!
그렇다 나는 그래도 몇 년동안 컴퓨터를 배운 사람이었던 것이다..
저는 사실 고딩 때도 매크로를 사용해본 적이 있습니다
그때는 이렇게 직접 만든 건 아니었고, 시중에 있는 단순한 클릭 매크로를 다운받아서 좌표를 지정해준 후에 단축키로 트리거를 해주는 그런 방식의 간단한 매크로였습니다
사실 "매크로" 단어만 듣고 보면 티켓팅 쪽에서 하도 안 좋은 사례가 많다보니 부정적으로 들리고는 하지만, 원래는 그냥 효율적인 도구입니다
티켓팅이나 게임뿐만 아니라 업무 자동화에도 많이 쓰이죠
하여튼 서론이었구요 본격적으로 들어가보겠습니다
저는 우선 파이썬을 이용했습니다.
이유는 pyautogui
라는 좋은 라이브러리가 있기 때문입니다.
pyautogui란?
Python으로 마우스와 키보드를 자동으로 제어할 수 있게 해주는 라이브러리이다.
사람이 하는 컴퓨터 조작을 코드로 대신하게 해준다.
그리고 최종 코드부터 보자면 다음과 같습니다.
### macro.py
from pynput import keyboard
import pyautogui
import time
import numpy as np
# ------------------- 설정 -------------------
region = (23, 157, 648, 611)
target_color = (79, 166, 52) # 초록
# target_color = (120, 105, 230) # 보라
tolerance = 5
confirm_button = (750, 655)
def color_match(c1, c2, tol):
return all(abs(a - b) <= tol for a, b in zip(c1, c2))
def run_macro():
screenshot = pyautogui.screenshot(region=region)
img = np.array(screenshot.convert("RGB"))
found = False
for y in range(img.shape[0]):
for x in range(img.shape[1]):
r, g, b = img[y, x]
if color_match((r, g, b), target_color, tolerance):
real_x = region[0] + x
real_y = region[1] + y
pyautogui.click(real_x, real_y)
print(f"좌석 클릭 완료: ({real_x}, {real_y}) / 색상: ({r}, {g}, {b})")
pyautogui.click(*confirm_button)
print("좌석 선택 완료 버튼 클릭")
found = True
break
if found:
break
if not found:
print("해당 색상을 찾지 못했습니다.")
# ------------------- 단축키 리스너 -------------------
def on_press(key):
try:
if key == keyboard.Key.alt:
print("option 눌림 → 매크로 실행")
run_macro()
except Exception as e:
print("오류 발생:", e)
print("⌨️ option 키를 누르면 매크로가 실행됩니다. 종료하려면 Ctrl+C.")
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
프로그램 실행 후 option 키를 눌러주면 매크로가 바로 동작하는 것을 보실 수 있습니다.
하나하나씩 천천히 뜯어보도록 하겠습니다.
### macro.py
from pynput import keyboard
import pyautogui
import numpy as np
우선 세 개의 라이브러리를 import 해줍니다.
pynput
은 지정해준 단축키로 매크로 실행을 트리거하게 하기 위해서 사용하는 라이브러리입니다.
pyautogui
는 위에서도 말했듯 Python으로 마우스와 키보드를 자동으로 제어할 수 있게 해주는 라이브러리입니다.
numpy
는 RGB 배열을 빠르고 편리하게 사용하기 위한 라이브러리입니다.
### macro.py
# ------------------- 설정 -------------------
region = (23, 157, 648, 611)
target_color = (83, 176, 249) # 초록
# target_color = (120, 105, 230) # 보라
# target_color = (83, 176, 249) # 하늘
# target_color = (235, 132, 87) # 주황
tolerance = 5
confirm_button = (750, 655)
좌석을 인식할 구역, 좌석 색(RGB), 좌석선택완료 버튼 좌표 등을 설정하는 부분입니다.
region
은 차례대로, 시작점을 좌측 상단 모서리라고 할 때 (, , , )를 의미합니다. 즉, 직사각형으로 좌석을 인식할 구역을 설정해주는 것입니다.
해당 값은 CordinationPicker.py
를 만들어 추출할 수 있습니다.
CordinationPicker.py
### CordinationPicker.py
from pynput import mouse
saved_points = []
def on_click(x, y, button, pressed):
if pressed:
saved_points.append((x, y))
print(f"클릭한 위치 저장: ({x}, {y})")
# 예: 2개 클릭하면 region 자동 출력
if len(saved_points) == 2:
x1, y1 = saved_points[0]
x2, y2 = saved_points[1]
region = (x1, y1, x2 - x1, y2 - y1)
print(f"\n 저장된 region: {region}")
# 마우스 클릭 리스너 실행
with mouse.Listener(on_click=on_click) as listener:
print("클릭하면 좌표가 저장됩니다. Ctrl+C로 종료")
listener.join()
위 코드를 실행하여 인식하려는 구역의 좌측상단 모서리와 우측하단 모서리를 클릭하면 위에서 필요한 네 개의 값을 얻을 수 있습니다.
다시 macro.py
파일로 돌아오겠습니다.
### macro.py
def color_match(c1, c2, tol):
return all(abs(a - b) <= tol for a, b in zip(c1, c2))
찾는 색상이 지정한 구역에 있는지 확인하는 color_match()
함수입니다.
c1
: 해당 픽셀의 RGB값c2
: 찾으려는 색의 RGB값tol
: RGB값의 오차 허용치픽셀마다 위 함수를 호출하여, 해당 픽셀의 RGB값이 찾으려는 색의 RGB값과 허용 범위 내에서 일치하면 true
를 반환합니다.
### macro.py
def run_macro():
screenshot = pyautogui.screenshot(region=region)
img = np.array(screenshot.convert("RGB"))
found = False
for y in range(img.shape[0]):
for x in range(img.shape[1]):
r, g, b = img[y, x]
if color_match((r, g, b), target_color, tolerance):
real_x = region[0] + x
real_y = region[1] + y
pyautogui.click(real_x, real_y)
print(f"좌석 클릭 완료: ({real_x}, {real_y}) / 색상: ({r}, {g}, {b})")
pyautogui.click(*confirm_button)
print("좌석 선택 완료 버튼 클릭")
found = True
break
if found:
break
if not found:
print("해당 색상을 찾지 못했습니다.")
실질적으로 해당하는 색의 좌석을 찾는 run_macro()
함수입니다.
run_macro() 작동 원리
1) 지정한 구역의 스크린샷을 찍는다.
2) 스크린샷을 RGB로 변환해서 Numpy 배열을 만든다.
3) 각 픽셀을 순회하면서, 일치여부를 판단하여 일치하면 해당 픽셀을 클릭한다.
4) 좌석 클릭 후에는 미리 지정한 '좌석선택완료' 버튼을 클릭하여, 다음 페이지로 넘어가도록 한다.
# ------------------- 단축키 리스너 -------------------
def on_press(key):
try:
if key == keyboard.Key.alt:
print("option 눌림 → 매크로 실행")
run_macro()
except Exception as e:
print("오류 발생:", e)
print("option 키를 누르면 매크로가 실행됩니다. 종료하려면 Ctrl+C.")
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
좌석이 뜨기 전에 보안문자를 입력하거나 하는 과정을 거쳐야 할 수 있으므로,
일단 파이썬 파일을 실행시키고 나서 단축키만 누르면 좌석 탐색 프로세스가 실행될 수 있도록 단축키 트리거를 설정해주었습니다.
어떤 단축키를 사용할 지는 if key == keyboard.Key.alt:
부분에서 오른쪽 부분을 바꿔줌으로서 원하는 키로 바꿀 수 있습니다. 저 같은 경우에는 option 키로 지정해주었습니다.
끝입니다. 간단하죠?
코드는 자유롭게 사용하셔도 됩니다 ㅋ
악용은 하지 마시고
다들 여유로운 문화생활하시길
성공을 기원합니다