├── utils ├── __pycache__ │ ├── __init__.cpython-310.pyc │ ├── captcha.cpython-310.pyc │ ├── seat_filter.cpython-310.pyc │ └── auto_fill_info.cpython-310.pyc ├── __init__.py ├── seat_filter.py ├── auto_fill_info.py └── captcha.py ├── config.py ├── README.md └── main.py /utils/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crypt0nX/Interpark-Bot/HEAD/utils/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /utils/__pycache__/captcha.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crypt0nX/Interpark-Bot/HEAD/utils/__pycache__/captcha.cpython-310.pyc -------------------------------------------------------------------------------- /utils/__pycache__/seat_filter.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crypt0nX/Interpark-Bot/HEAD/utils/__pycache__/seat_filter.cpython-310.pyc -------------------------------------------------------------------------------- /utils/__pycache__/auto_fill_info.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crypt0nX/Interpark-Bot/HEAD/utils/__pycache__/auto_fill_info.cpython-310.pyc -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Author : 4 | # @Time : 2024/5/29 18:20 5 | # @File : __init__.py.py 6 | # @annotation : 7 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Author : 4 | # @Time : 2024/5/18 23:29 5 | # @File : config.py 6 | # @annotation : 7 | 8 | 9 | GOODS_ID = '24007162' 10 | TIME = '20240707' 11 | 12 | 13 | BizMemberCode = None 14 | 15 | INITIAL_URL = f'https://www.globalinterpark.com/en/product/{GOODS_ID}' 16 | 17 | 18 | def getInitialUrl(BizMemberCode): 19 | INITIAL_URL2 = ('https://gpoticket.globalinterpark.com/Global/Play/Booking/BookingSessionGate.asp?' 20 | f'v1={GOODS_ID}&' 21 | 'v2=G2001&' 22 | f'v3={TIME}&' 23 | f'v4=001&v5=N&v6=10965&v7={BizMemberCode}&v8=N') 24 | return INITIAL_URL2 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Interpark-Bot 2 | 3 | ## Description 4 | 5 | This is a simple example of a ticket-sniping program for Interpark Global, using DrissionPage. Please note that although it can successfully complete the task, it's likely not directly usable without some coding background, as the seating information for each venue is different and the process for each show may vary. This code is just an example. 6 | 7 | First, you need to open Chromium and enable the debug mode: ```chromium --remote-debugging-port=9222```, you can visit DrissionPage official site for more instruction 8 | 9 | Then, In config.py, you need to fill in two key variables based on the information of the different performances: GOODS_ID and TIME. Both variables can be found on the performance page. For example, using https://www.globalinterpark.com/en/product/24007162, GOODS_ID is the last set of numbers in the URL, 24007162, and TIME is the date of the performance, formatted as YYYYMMDD. 10 | 11 | Please note that you will still need to modify two functions in utils.seat_filter to filter specific venue seats. This will require you to study the code yourself. Good luck! 12 | 13 | For methods to bypass reCAPTCHA, thanks to https://github.com/sarperavci/GoogleRecaptchaBypass. 14 | ### 15 | 16 | This code is for learning purposes only. Please delete it within 24 hours after downloading. -------------------------------------------------------------------------------- /utils/seat_filter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Author : 4 | # @Time : 2024/5/29 18:21 5 | # @File : seatFilter.py 6 | # @annotation : 7 | import re 8 | 9 | def find_seat(html_text): 10 | seats = [] 11 | allseats = [] 12 | keys = ["me", "SeatGrade", "Floor", "RowNo", "SeatNo", "Block"] 13 | pattern = re.compile(r"alt=\"\" onclick=\"javascript: SelectSeat(.*)'") 14 | matches = pattern.findall(html_text) 15 | for match in matches: 16 | match = str(match).strip("(").replace("'", '').split(',') 17 | match = [i.strip().replace('열', '') for i in match] 18 | mapped_dict = dict(zip(keys, match)) 19 | try: 20 | if int(mapped_dict.get("RowNo")) == 7 and int(mapped_dict.get("SeatNo")) in [24, 25, 26, 27]: 21 | print("Remove: ", mapped_dict) 22 | continue 23 | except Exception as e: 24 | continue 25 | allseats.append(mapped_dict) 26 | if '1층' in mapped_dict.get('Floor'): 27 | seats.append(mapped_dict) 28 | if len(seats) > 0: 29 | return seats 30 | else: 31 | print(allseats) 32 | print("Couldn't find 1st floor seats") 33 | return allseats 34 | 35 | 36 | def filter_golden_seat(seats): 37 | golden_seats = [] 38 | for seat_dict in seats: 39 | try: 40 | if int(seat_dict.get('RowNo')) <= 9 and 2 <= int(seat_dict.get('SeatNo')) <= 24: 41 | golden_seats.append(seat_dict) 42 | except Exception as e: 43 | continue 44 | if len(golden_seats) > 0: 45 | return golden_seats 46 | else: 47 | print("Couldn't find golden seats") 48 | return seats -------------------------------------------------------------------------------- /utils/auto_fill_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Author : 4 | # @Time : 2024/5/29 18:22 5 | # @File : auto_fill_info.py 6 | # @annotation : 7 | import time 8 | 9 | 10 | def fillPersonalInfo(tab): 11 | tab.ele('xpath:/html/body/form/div/div[2]/div/div[1]/table/tbody/tr[2]/td/input').input('TBD') 12 | tab.ele('xpath://*[@id="BirYear"]').select.by_value("TBD") 13 | tab.ele('xpath://*[@id="BirMonth"]').select.by_value("TBD") 14 | tab.ele('xpath://*[@id="BirDay"]').select.by_value("TBD") 15 | tab.ele('xpath:/html/body/form/div/div[2]/div/div[1]/table/tbody/tr[8]/td/input').input("TBD") 16 | tab.ele('xpath:/html/body/form/div/div[2]/div/div[1]/table/tbody/tr[12]/td/select').select.by_value("TBD") 17 | tab.ele('xpath:/html/body/form/div/div[2]/div/div[1]/table/tbody/tr[10]/td/input').input("TBD") 18 | tab.ele('xpath:/html/body/form/div/div[2]/div/div[1]/table/tbody/tr[12]/td/input').input("TBD") 19 | 20 | 21 | def fillPaymentInfo(tab): 22 | tab.ele('xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/p/input').click() 23 | time.sleep(0.1) 24 | tab.ele('xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/p/select').select.by_value("TBD") 25 | tab.ele('xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/div/div/table/tbody/tr[2]/td/input[1]').input( 26 | "TBD") 27 | tab.ele('xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/div/div/table/tbody/tr[2]/td/input[2]').input( 28 | "TBD") 29 | tab.ele('xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/div/div/table/tbody/tr[2]/td/input[3]').input( 30 | "TBD") 31 | tab.ele('xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/div/div/table/tbody/tr[2]/td/input[4]').input( 32 | "TBD") 33 | tab.ele( 34 | 'xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/div/div/table/tbody/tr[3]/td/select[1]').select.by_value( 35 | "TBD") 36 | tab.ele( 37 | 'xpath:/html/body/div/form/div[2]/div/div[1]/ul/div/li[2]/div/div/table/tbody/tr[3]/td/select[2]').select.by_value( 38 | "TBD") 39 | -------------------------------------------------------------------------------- /utils/captcha.py: -------------------------------------------------------------------------------- 1 | import os, urllib, random, pydub, speech_recognition, time 2 | from DrissionPage.common import Keys 3 | from DrissionPage import ChromiumPage 4 | 5 | 6 | class RecaptchaSolver: 7 | def __init__(self, driver: ChromiumPage): 8 | self.driver = driver 9 | 10 | def solveCaptcha(self): 11 | iframe_inner = self.driver("@title=reCAPTCHA") 12 | time.sleep(0.1) 13 | 14 | # Click on the recaptcha 15 | iframe_inner('.rc-anchor-content', timeout=1).click() 16 | self.driver.wait.ele_displayed("xpath://iframe[contains(@title, 'recaptcha')]", timeout=3) 17 | 18 | # Sometimes just clicking on the recaptcha is enough to solve it 19 | if self.isSolved(): 20 | return 21 | 22 | # Get the new iframe 23 | # iframe = self.driver("xpath://iframe[contains(@title, 'recaptcha')]") 24 | 25 | # Click on the audio button 26 | # iframe('#recaptcha-audio-button', timeout=1).click() 27 | # time.sleep(.3) 28 | 29 | # # Get the audio source 30 | # src = iframe('#audio-source').attrs['src'] 31 | # 32 | # # Download the audio to the temp folder 33 | # path_to_mp3 = os.path.normpath(os.path.join((os.getenv("TEMP") if os.name=="nt" else "/tmp/")+ str(random.randrange(1,1000))+".mp3")) 34 | # path_to_wav = os.path.normpath(os.path.join((os.getenv("TEMP") if os.name=="nt" else "/tmp/")+ str(random.randrange(1,1000))+".wav")) 35 | # 36 | # urllib.request.urlretrieve(src, path_to_mp3) 37 | # 38 | # # Convert mp3 to wav 39 | # sound = pydub.AudioSegment.from_mp3(path_to_mp3) 40 | # sound.export(path_to_wav, format="wav") 41 | # sample_audio = speech_recognition.AudioFile(path_to_wav) 42 | # r = speech_recognition.Recognizer() 43 | # with sample_audio as source: 44 | # audio = r.record(source) 45 | # 46 | # # Recognize the audio 47 | # key = r.recognize_google(audio) 48 | # 49 | # # Input the key 50 | # iframe('#audio-response').input(key.lower()) 51 | # time.sleep(0.1) 52 | # 53 | # # Submit the key 54 | # iframe('#audio-response').input(Keys.ENTER) 55 | # time.sleep(.4) 56 | # 57 | # # Check if the captcha is solved 58 | # if self.isSolved(): 59 | # return 60 | # else: 61 | # raise Exception("Failed to solve the captcha") 62 | 63 | def isSolved(self): 64 | try: 65 | return "style" in self.driver.ele(".recaptcha-checkbox-checkmark", timeout=1).attrs 66 | except: 67 | return False 68 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Author : 4 | # @Time : 2024/5/18 22:48 5 | # @File : main.py 6 | # @annotation : 7 | import random 8 | import time 9 | from DrissionPage import WebPage 10 | from utils.captcha import RecaptchaSolver 11 | from utils.seat_filter import filter_golden_seat, find_seat 12 | from utils.auto_fill_info import fillPersonalInfo, fillPaymentInfo 13 | import config 14 | 15 | driver = WebPage() 16 | driver.post(url=config.INITIAL_URL) 17 | for i in driver.cookies(): 18 | if list(i.values())[0] == 'TMem%5FNO': 19 | config.BizMemberCode = i.get('value') 20 | # while True: 21 | # # 获取当前时间 22 | # now = datetime.now() 23 | # 24 | # # 检查当前时间是否为晚上七点(小时为19且分钟为0) 25 | # if now.hour == 19 and now.minute == 00: 26 | # print("It's 7 PM!") 27 | # break 28 | # 29 | # # 等待0.1秒后再次检查 30 | # time.sleep(0.3) 31 | # 32 | driver.get(url=config.getInitialUrl(BizMemberCode=config.BizMemberCode)) 33 | 34 | 35 | def solve_recaptcha(tab): 36 | recaptchaSolver = RecaptchaSolver(tab) 37 | while True: 38 | try: 39 | recaptchaSolver.solveCaptcha() 40 | break 41 | except Exception as e: 42 | print(e) 43 | 44 | 45 | time.sleep(2) 46 | if driver.get_tab(title="인터파크 티켓"): 47 | print("Waiting") 48 | driver.get_tab(title="인터파크 티켓").wait.title_change("INTERPARK", timeout=10000) 49 | print("Waiting Finished") 50 | time.sleep(3) 51 | 52 | while True: 53 | tab = driver.get_tab(title="INTERPARK") 54 | if tab: 55 | break 56 | 57 | if tab is not None: 58 | tab.run_cdp_loaded('Runtime.evaluate', 59 | expression="alert=function(x){console.log(x)}") # override interpark js functions 60 | tab.run_cdp_loaded('Runtime.evaluate', expression="window.close=function(x){console.log(x)}") 61 | 62 | tab.ele(f'xpath://*[@id="LargeNextBtnImage"]').click() 63 | driver.wait.doc_loaded() 64 | tab.run_cdp_loaded('Runtime.evaluate', expression="javascript:fnNextStep('P')") 65 | if tab.ele("@title=reCAPTCHA", timeout=1): 66 | print("Solving recaptcha") 67 | solve_recaptcha(tab) 68 | while True: 69 | try: 70 | tab.ele(f'xpath:/html/body/form[1]/div/div[1]/div[1]/div[1]/div/select[1]', timeout=3).select.by_value( 71 | config.TIME) 72 | tab.ele(f'xpath:/html/body/form[1]/div/div[1]/div[1]/div[1]/div/select[2]', timeout=3).select.by_index(1) 73 | time.sleep(1.5) 74 | seat_iframe = tab.get_frame('#ifrmSeatDetail').html 75 | avail_seats = find_seat(seat_iframe) 76 | # avail_seats = filter_golden_seat(find_seat(seat_iframe)) 77 | if len(avail_seats) > 0: 78 | break 79 | except Exception as e: 80 | print(e) 81 | pass 82 | random_seat = random.choice(avail_seats) 83 | print(random_seat) 84 | SID = random_seat.get('me') 85 | tab.ele(f'xpath://*[@id="{SID}"]').before().click() 86 | tab.ele(f'xpath://*[@id="NextStepImage"]').click() 87 | tab.ele(f'xpath://*[@id="PriceRow001"]/td[3]/select').select.by_value("1") 88 | tab.ele(f'xpath://*[@id="SmallNextBtnImage"]').click() 89 | fillPersonalInfo(tab) 90 | tab.ele(f'xpath://*[@id="SmallNextBtnImage"]').click() 91 | fillPaymentInfo(tab) 92 | --------------------------------------------------------------------------------