똥손이라 슬픈 사람의 티켓팅 매크로 제작기

부리또의 댄스·2025년 4월 13일
1
post-thumbnail

시작하기 전..
매크로를 이용해 예매한 티켓을 정가가 아닌 값에 재판매하면 불법이지만
스스로 제작한 매크로를 사용하는 것 자체는 불법이 아니라는 글을 봤기에 이 글을 작성합니다..
(아니라면 알려주세요!! 내리겠습니다!!)

최근에 저에게는 두 번의 티켓팅이 있었습니다

제가 정말 사랑하는 성진 쿤의 리사이틀 티켓팅이 무려 하루에 2시간 간격으로 두 번이나 있었습니다

그리고 아니나 다를까...

실 패 했 어

그래서 저는 결심합니다...
매번 남의 손 빌리기도 그렇고 내 손으로 좀 잡아보자....
근데 어케하지...
..!! 매크로!!

그렇다 나는 그래도 몇 년동안 컴퓨터를 배운 사람이었던 것이다..

저는 사실 고딩 때도 매크로를 사용해본 적이 있습니다
그때는 이렇게 직접 만든 건 아니었고, 시중에 있는 단순한 클릭 매크로를 다운받아서 좌표를 지정해준 후에 단축키로 트리거를 해주는 그런 방식의 간단한 매크로였습니다

사실 "매크로" 단어만 듣고 보면 티켓팅 쪽에서 하도 안 좋은 사례가 많다보니 부정적으로 들리고는 하지만, 원래는 그냥 효율적인 도구입니다

티켓팅이나 게임뿐만 아니라 업무 자동화에도 많이 쓰이죠

하여튼 서론이었구요 본격적으로 들어가보겠습니다


저는 우선 파이썬을 이용했습니다.
이유는 pyautogui라는 좋은 라이브러리가 있기 때문입니다.

pyautogui란?

Python으로 마우스와 키보드를 자동으로 제어할 수 있게 해주는 라이브러리이다.
사람이 하는 컴퓨터 조작을 코드로 대신하게 해준다.

그리고 최종 코드부터 보자면 다음과 같습니다.

macro.py

### 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 키를 눌러주면 매크로가 바로 동작하는 것을 보실 수 있습니다.

하나하나씩 천천히 뜯어보도록 하겠습니다.

코드 설명

1.

### macro.py
from pynput import keyboard
import pyautogui
import numpy as np

우선 세 개의 라이브러리를 import 해줍니다.
pynput은 지정해준 단축키로 매크로 실행을 트리거하게 하기 위해서 사용하는 라이브러리입니다.

pyautogui는 위에서도 말했듯 Python으로 마우스와 키보드를 자동으로 제어할 수 있게 해주는 라이브러리입니다.

numpy는 RGB 배열을 빠르고 편리하게 사용하기 위한 라이브러리입니다.

2.

### 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은 차례대로, 시작점을 좌측 상단 모서리라고 할 때 (xx, yy, widthwidth, heightheight)를 의미합니다. 즉, 직사각형으로 좌석을 인식할 구역을 설정해주는 것입니다.
해당 값은 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) 좌석 클릭 후에는 미리 지정한 '좌석선택완료' 버튼을 클릭하여, 다음 페이지로 넘어가도록 한다.

3.

# ------------------- 단축키 리스너 -------------------

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 키로 지정해주었습니다.


끝입니다. 간단하죠?
코드는 자유롭게 사용하셔도 됩니다 ㅋ
악용은 하지 마시고
다들 여유로운 문화생활하시길

profile
환영합니다!

10개의 댓글

comment-user-thumbnail
2025년 4월 17일

성공을 기원합니다

답글 달기
comment-user-thumbnail
2025년 5월 28일

혹시.... 스포츠 티켓도 가능할까요...?

1개의 답글
comment-user-thumbnail
2025년 5월 30일

티켓링크도 사용 가능한가요?

1개의 답글
comment-user-thumbnail
2025년 6월 11일

그 심정 누구보다도 이해가 가고, 공감이 가네요. ㅠㅠ
정말 아무것도 모르는 사람인데, 위의 코드를 어디에 입력해야 하는건가요??
아니면 무엇을 배워야 할지 가이드라인이라도 좀 알려주실 수 있나요??
물에 빠진 사람 한 번 건져준다는 심정으로 한번만 도와주십시요.ㅠㅠ
딸이랑 야구장 가고 싶은데 뭐든 쉽지 않네요. ㅠㅠ

답글 달기
comment-user-thumbnail
2025년 6월 24일

티켓링크로 야구경기 예매할려고하는데 자동으로 예매창 들어가지나요??

답글 달기
comment-user-thumbnail
2025년 7월 11일

멜론티켓도 가능한가요?

답글 달기
comment-user-thumbnail
2025년 7월 18일

안녕하세요
혹시 티켓링크 스포츠에도 적용이 가능할까요..?

답글 달기
comment-user-thumbnail
2025년 8월 28일

혹시 no module named이라는 것은 어떻게 되는건가요?

답글 달기