2021-12-01 18:31:19 +00:00
|
|
|
|
#!/usr/bin/env python3
|
2019-10-01 17:52:13 +00:00
|
|
|
|
#encoding=utf-8
|
2022-11-23 04:39:46 +00:00
|
|
|
|
# 'seleniumwire' and 'selenium 4' raise error when running python 2.x
|
|
|
|
|
# PS: python 2.x will be removed in future.
|
2022-11-17 18:17:19 +00:00
|
|
|
|
#執行方式:python chrome_tixcraft.py 或 python3 chrome_tixcraft.py
|
2021-12-01 18:31:19 +00:00
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
import platform
|
|
|
|
|
import json
|
|
|
|
|
import random
|
2022-10-20 05:09:32 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
from selenium import webdriver
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# for close tab.
|
|
|
|
|
from selenium.common.exceptions import NoSuchWindowException
|
|
|
|
|
from selenium.common.exceptions import UnexpectedAlertPresentException
|
|
|
|
|
from selenium.common.exceptions import NoAlertPresentException
|
2022-11-17 18:17:19 +00:00
|
|
|
|
from selenium.common.exceptions import WebDriverException
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# for alert 2
|
|
|
|
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
|
|
|
from selenium.webdriver.support import expected_conditions as EC
|
2022-11-17 18:17:19 +00:00
|
|
|
|
from selenium.webdriver.support.ui import Select
|
|
|
|
|
from selenium.webdriver.common.by import By
|
2023-01-11 13:58:55 +00:00
|
|
|
|
from selenium.webdriver.common.keys import Keys
|
2021-12-01 18:31:19 +00:00
|
|
|
|
# for selenium 4
|
|
|
|
|
from selenium.webdriver.chrome.service import Service
|
2023-01-02 06:53:28 +00:00
|
|
|
|
from selenium.webdriver.common.action_chains import ActionChains
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# for wait #1
|
|
|
|
|
import time
|
|
|
|
|
import re
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
# for error output
|
|
|
|
|
import logging
|
|
|
|
|
logging.basicConfig()
|
|
|
|
|
logger = logging.getLogger('logger')
|
2019-12-14 19:13:20 +00:00
|
|
|
|
# for check reg_info
|
|
|
|
|
import requests
|
2019-12-18 03:45:48 +00:00
|
|
|
|
import warnings
|
|
|
|
|
from urllib3.exceptions import InsecureRequestWarning
|
|
|
|
|
warnings.simplefilter('ignore',InsecureRequestWarning)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
# ocr
|
|
|
|
|
import base64
|
2023-01-11 14:26:49 +00:00
|
|
|
|
try:
|
|
|
|
|
import ddddocr
|
2023-01-14 05:26:42 +00:00
|
|
|
|
|
|
|
|
|
#PS: python 3.11.1 raise PIL conflict.
|
|
|
|
|
from NonBrowser import NonBrowser
|
2023-01-11 14:26:49 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
2021-12-01 18:31:19 +00:00
|
|
|
|
import ssl
|
|
|
|
|
ssl._create_default_https_context = ssl._create_unverified_context
|
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
CONST_APP_VERSION = u"MaxBot (2023.01.14) ver.6"
|
2022-12-15 11:26:51 +00:00
|
|
|
|
|
2022-11-21 19:01:04 +00:00
|
|
|
|
CONST_HOMEPAGE_DEFAULT = "https://tixcraft.com"
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
CONST_FROM_TOP_TO_BOTTOM = u"from top to bottom"
|
|
|
|
|
CONST_FROM_BOTTOM_TO_TOP = u"from bottom to top"
|
|
|
|
|
CONST_RANDOM = u"random"
|
|
|
|
|
CONST_SELECT_ORDER_DEFAULT = CONST_FROM_TOP_TO_BOTTOM
|
|
|
|
|
CONST_SELECT_OPTIONS_DEFAULT = (CONST_FROM_TOP_TO_BOTTOM, CONST_FROM_BOTTOM_TO_TOP, CONST_RANDOM)
|
|
|
|
|
CONST_SELECT_OPTIONS_ARRAY = [CONST_FROM_TOP_TO_BOTTOM, CONST_FROM_BOTTOM_TO_TOP, CONST_RANDOM]
|
|
|
|
|
|
2022-02-18 18:53:55 +00:00
|
|
|
|
CONT_STRING_1_SEATS_REMAINING = [u'@1 seat(s) remaining',u'剩餘 1@',u'@1 席残り']
|
2021-03-21 06:14:20 +00:00
|
|
|
|
|
2022-01-12 17:14:27 +00:00
|
|
|
|
def get_app_root():
|
|
|
|
|
# 讀取檔案裡的參數值
|
|
|
|
|
basis = ""
|
|
|
|
|
if hasattr(sys, 'frozen'):
|
|
|
|
|
basis = sys.executable
|
|
|
|
|
else:
|
|
|
|
|
basis = sys.argv[0]
|
|
|
|
|
app_root = os.path.dirname(basis)
|
|
|
|
|
return app_root
|
|
|
|
|
|
|
|
|
|
def get_config_dict():
|
|
|
|
|
config_json_filename = 'settings.json'
|
|
|
|
|
app_root = get_app_root()
|
|
|
|
|
config_filepath = os.path.join(app_root, config_json_filename)
|
|
|
|
|
config_dict = None
|
|
|
|
|
if os.path.isfile(config_filepath):
|
|
|
|
|
with open(config_filepath) as json_data:
|
|
|
|
|
config_dict = json.load(json_data)
|
|
|
|
|
return config_dict
|
|
|
|
|
|
2022-11-06 09:10:35 +00:00
|
|
|
|
def format_keyword_string(keyword):
|
|
|
|
|
if not keyword is None:
|
|
|
|
|
if len(keyword) > 0:
|
|
|
|
|
keyword = keyword.replace('/','/')
|
2022-11-09 20:16:41 +00:00
|
|
|
|
keyword = keyword.replace(' ','')
|
|
|
|
|
keyword = keyword.replace(',','')
|
|
|
|
|
keyword = keyword.replace(',','')
|
|
|
|
|
keyword = keyword.replace('$','')
|
2022-11-06 09:10:35 +00:00
|
|
|
|
keyword = keyword.replace(' ','').lower()
|
|
|
|
|
return keyword
|
|
|
|
|
|
|
|
|
|
def find_continuous_number(text):
|
2023-01-02 20:37:54 +00:00
|
|
|
|
chars = "0123456789"
|
|
|
|
|
return find_continuous_pattern(chars, text)
|
|
|
|
|
|
|
|
|
|
def find_continuous_text(text):
|
|
|
|
|
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
|
return find_continuous_pattern(chars, text)
|
|
|
|
|
|
|
|
|
|
def find_continuous_pattern(allowed_char, text):
|
2022-11-06 09:10:35 +00:00
|
|
|
|
ret = ""
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_allowed_char_start = False
|
2022-11-06 09:10:35 +00:00
|
|
|
|
for char in text:
|
|
|
|
|
#print("char:", char)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if char in allowed_char:
|
|
|
|
|
if len(ret)==0 and not is_allowed_char_start:
|
|
|
|
|
is_allowed_char_start = True
|
|
|
|
|
if is_allowed_char_start:
|
2022-11-06 09:10:35 +00:00
|
|
|
|
ret += char
|
|
|
|
|
else:
|
|
|
|
|
# make not continuous
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_allowed_char_start = False
|
2022-11-06 09:10:35 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
2022-10-25 16:04:29 +00:00
|
|
|
|
def get_favoriate_extension_path(webdriver_path):
|
|
|
|
|
no_google_analytics_path = os.path.join(webdriver_path,"no_google_analytics_1.1.0.0.crx")
|
2023-01-12 08:55:28 +00:00
|
|
|
|
no_ad_path = os.path.join(webdriver_path,"Adblock_3.15.2.0.crx")
|
2022-10-25 16:04:29 +00:00
|
|
|
|
return no_google_analytics_path, no_ad_path
|
|
|
|
|
|
|
|
|
|
def get_chromedriver_path(webdriver_path):
|
|
|
|
|
chromedriver_path = os.path.join(webdriver_path,"chromedriver")
|
|
|
|
|
if platform.system().lower()=="windows":
|
|
|
|
|
chromedriver_path = os.path.join(webdriver_path,"chromedriver.exe")
|
|
|
|
|
return chromedriver_path
|
|
|
|
|
|
2022-11-17 18:17:19 +00:00
|
|
|
|
def load_chromdriver_normal(webdriver_path, driver_type, adblock_plus_enable):
|
2022-10-25 16:04:29 +00:00
|
|
|
|
chrome_options = webdriver.ChromeOptions()
|
|
|
|
|
|
|
|
|
|
chromedriver_path = get_chromedriver_path(webdriver_path)
|
|
|
|
|
|
2022-11-09 20:16:41 +00:00
|
|
|
|
# some windows cause: timed out receiving message from renderer
|
2022-11-17 18:17:19 +00:00
|
|
|
|
if adblock_plus_enable:
|
|
|
|
|
# PS: this is ocx version.
|
|
|
|
|
no_google_analytics_path, no_ad_path = get_favoriate_extension_path(webdriver_path)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
2022-11-17 18:17:19 +00:00
|
|
|
|
if os.path.exists(no_google_analytics_path):
|
|
|
|
|
chrome_options.add_extension(no_google_analytics_path)
|
|
|
|
|
if os.path.exists(no_ad_path):
|
|
|
|
|
chrome_options.add_extension(no_ad_path)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
chrome_options.add_argument('--disable-features=TranslateUI')
|
|
|
|
|
chrome_options.add_argument('--disable-translate')
|
|
|
|
|
chrome_options.add_argument('--lang=zh-TW')
|
|
|
|
|
|
|
|
|
|
# for navigator.webdriver
|
|
|
|
|
chrome_options.add_experimental_option("excludeSwitches", ['enable-automation'])
|
2023-01-07 21:43:30 +00:00
|
|
|
|
# Deprecated chrome option is ignored: useAutomationExtension
|
|
|
|
|
#chrome_options.add_experimental_option('useAutomationExtension', False)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
chrome_options.add_experimental_option("prefs", {"credentials_enable_service": False, "profile.password_manager_enabled": False})
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
#caps = DesiredCapabilities().CHROME
|
|
|
|
|
caps = chrome_options.to_capabilities()
|
|
|
|
|
|
|
|
|
|
#caps["pageLoadStrategy"] = u"normal" # complete
|
|
|
|
|
caps["pageLoadStrategy"] = u"eager" # interactive
|
|
|
|
|
#caps["pageLoadStrategy"] = u"none"
|
|
|
|
|
|
|
|
|
|
#caps["unhandledPromptBehavior"] = u"dismiss and notify" # default
|
2022-11-20 07:57:16 +00:00
|
|
|
|
#caps["unhandledPromptBehavior"] = u"ignore"
|
2022-10-25 16:04:29 +00:00
|
|
|
|
#caps["unhandledPromptBehavior"] = u"dismiss"
|
2022-11-20 07:57:16 +00:00
|
|
|
|
caps["unhandledPromptBehavior"] = u"accept"
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
chrome_service = Service(chromedriver_path)
|
|
|
|
|
|
|
|
|
|
# method 6: Selenium Stealth
|
2022-11-20 07:57:16 +00:00
|
|
|
|
driver = webdriver.Chrome(service=chrome_service, options=chrome_options, desired_capabilities=caps)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
if driver_type=="stealth":
|
|
|
|
|
from selenium_stealth import stealth
|
|
|
|
|
# Selenium Stealth settings
|
|
|
|
|
stealth(driver,
|
|
|
|
|
languages=["zh-TW", "zh"],
|
|
|
|
|
vendor="Google Inc.",
|
|
|
|
|
platform="Win32",
|
|
|
|
|
webgl_vendor="Intel Inc.",
|
|
|
|
|
renderer="Intel Iris OpenGL Engine",
|
|
|
|
|
fix_hairline=True,
|
|
|
|
|
)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
#print("driver capabilities", driver.capabilities)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
return driver
|
|
|
|
|
|
2022-11-17 18:17:19 +00:00
|
|
|
|
def load_chromdriver_uc(webdriver_path, adblock_plus_enable):
|
2022-10-25 16:04:29 +00:00
|
|
|
|
import undetected_chromedriver as uc
|
|
|
|
|
|
|
|
|
|
chromedriver_path = get_chromedriver_path(webdriver_path)
|
|
|
|
|
|
|
|
|
|
options = uc.ChromeOptions()
|
|
|
|
|
options.page_load_strategy="eager"
|
2022-11-20 07:57:16 +00:00
|
|
|
|
|
2022-10-25 16:04:29 +00:00
|
|
|
|
#print("strategy", options.page_load_strategy)
|
|
|
|
|
|
2022-11-17 18:17:19 +00:00
|
|
|
|
if adblock_plus_enable:
|
|
|
|
|
no_google_analytics_path, no_ad_path = get_favoriate_extension_path(webdriver_path)
|
|
|
|
|
no_google_analytics_folder_path = no_google_analytics_path.replace('.crx','')
|
|
|
|
|
no_ad_folder_path = no_ad_path.replace('.crx','')
|
|
|
|
|
load_extension_path = ""
|
|
|
|
|
if os.path.exists(no_google_analytics_folder_path):
|
|
|
|
|
load_extension_path += "," + no_google_analytics_folder_path
|
|
|
|
|
if os.path.exists(no_ad_folder_path):
|
|
|
|
|
load_extension_path += "," + no_ad_folder_path
|
|
|
|
|
if len(load_extension_path) > 0:
|
|
|
|
|
options.add_argument('--load-extension=' + load_extension_path[1:])
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
options.add_argument('--disable-features=TranslateUI')
|
|
|
|
|
options.add_argument('--disable-translate')
|
|
|
|
|
options.add_argument('--lang=zh-TW')
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
options.add_argument("--password-store=basic")
|
|
|
|
|
options.add_experimental_option("prefs", {"credentials_enable_service": False, "profile.password_manager_enabled": False})
|
|
|
|
|
|
|
|
|
|
caps = options.to_capabilities()
|
|
|
|
|
caps["unhandledPromptBehavior"] = u"accept"
|
|
|
|
|
|
2022-11-14 09:26:52 +00:00
|
|
|
|
driver = None
|
2022-10-25 16:04:29 +00:00
|
|
|
|
if os.path.exists(chromedriver_path):
|
|
|
|
|
print("Use user driver path:", chromedriver_path)
|
|
|
|
|
#driver = uc.Chrome(service=chrome_service, options=options, suppress_welcome=False)
|
|
|
|
|
is_local_chrome_browser_lower = False
|
|
|
|
|
try:
|
2022-11-21 20:21:00 +00:00
|
|
|
|
driver = uc.Chrome(executable_path=chromedriver_path, options=options, desired_capabilities=caps, suppress_welcome=False)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
if "cannot connect to chrome" in str(exc):
|
|
|
|
|
if "This version of ChromeDriver only supports Chrome version" in str(exc):
|
|
|
|
|
is_local_chrome_browser_lower = True
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_local_chrome_browser_lower:
|
|
|
|
|
print("Use local user downloaded chromedriver to lunch chrome browser.")
|
|
|
|
|
driver_type = "selenium"
|
2022-11-17 18:17:19 +00:00
|
|
|
|
driver = load_chromdriver_normal(webdriver_path, driver_type, adblock_plus_enable)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
else:
|
|
|
|
|
print("Oops! web driver not on path:",chromedriver_path )
|
|
|
|
|
print('let uc automatically download chromedriver.')
|
2022-11-21 20:21:00 +00:00
|
|
|
|
driver = uc.Chrome(options=options, desired_capabilities=caps, suppress_welcome=False)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
if driver is None:
|
|
|
|
|
print("create web drive object fail!")
|
|
|
|
|
else:
|
|
|
|
|
download_dir_path="."
|
|
|
|
|
params = {
|
|
|
|
|
"behavior": "allow",
|
|
|
|
|
"downloadPath": os.path.realpath(download_dir_path)
|
|
|
|
|
}
|
|
|
|
|
#print("assign setDownloadBehavior.")
|
|
|
|
|
driver.execute_cdp_cmd("Page.setDownloadBehavior", params)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
#print("driver capabilities", driver.capabilities)
|
2022-10-25 16:04:29 +00:00
|
|
|
|
|
|
|
|
|
return driver
|
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
def close_browser_tabs(driver):
|
2022-11-09 10:44:29 +00:00
|
|
|
|
if not driver is None:
|
|
|
|
|
try:
|
|
|
|
|
window_handles_count = len(driver.window_handles)
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if window_handles_count > 1:
|
2022-11-09 10:44:29 +00:00
|
|
|
|
driver.switch_to.window(driver.window_handles[1])
|
|
|
|
|
driver.close()
|
|
|
|
|
driver.switch_to.window(driver.window_handles[0])
|
|
|
|
|
except Exception as excSwithFail:
|
|
|
|
|
pass
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def get_driver_by_config(config_dict, driver_type):
|
|
|
|
|
global driver
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
homepage = None
|
|
|
|
|
browser = None
|
|
|
|
|
language = "English"
|
|
|
|
|
ticket_number = "2"
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
auto_press_next_step_button = False # default not checked.
|
|
|
|
|
auto_fill_ticket_number = False # default not checked.
|
|
|
|
|
auto_guess_options = False # default not checked.
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
kktix_area_auto_select_mode = ""
|
|
|
|
|
kktix_area_keyword = ""
|
|
|
|
|
kktix_date_keyword = ""
|
2022-03-24 15:22:43 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
pass_1_seat_remaining_enable = False # default not checked.
|
|
|
|
|
pass_date_is_sold_out_enable = False # default not checked.
|
|
|
|
|
auto_reload_coming_soon_page_enable = True # default checked.
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
area_keyword_1 = ""
|
|
|
|
|
area_keyword_2 = ""
|
|
|
|
|
area_keyword_3 = ""
|
|
|
|
|
area_keyword_4 = ""
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
date_keyword = ""
|
2019-12-14 19:13:20 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
date_auto_select_enable = None
|
|
|
|
|
date_auto_select_mode = ""
|
2019-12-14 19:13:20 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
area_auto_select_enable = None
|
|
|
|
|
area_auto_select_mode = ""
|
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
# read config.
|
|
|
|
|
homepage = config_dict["homepage"]
|
|
|
|
|
browser = config_dict["browser"]
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
# output debug message in client side.
|
|
|
|
|
ticket_number = str(config_dict["ticket_number"])
|
2022-11-24 21:40:40 +00:00
|
|
|
|
pass_1_seat_remaining_enable = config_dict["pass_1_seat_remaining"]
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
|
|
|
|
# for ["kktix"]
|
|
|
|
|
auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"]
|
|
|
|
|
auto_fill_ticket_number = config_dict["kktix"]["auto_fill_ticket_number"]
|
|
|
|
|
kktix_area_auto_select_mode = config_dict["kktix"]["area_mode"].strip()
|
|
|
|
|
if not kktix_area_auto_select_mode in CONST_SELECT_OPTIONS_ARRAY:
|
|
|
|
|
kktix_area_auto_select_mode = CONST_SELECT_ORDER_DEFAULT
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
kktix_area_keyword_1 = config_dict["kktix"]["area_keyword_1"].strip()
|
|
|
|
|
kktix_area_keyword_1_and = config_dict["kktix"]["area_keyword_1_and"].strip()
|
|
|
|
|
kktix_area_keyword_2 = config_dict["kktix"]["area_keyword_2"].strip()
|
|
|
|
|
kktix_area_keyword_2_and = config_dict["kktix"]["area_keyword_2_and"].strip()
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
# disable password brute force attack
|
|
|
|
|
# PS: because of the question is always variable.
|
2022-06-24 17:29:48 +00:00
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
auto_guess_options = config_dict["kktix"]["auto_guess_options"]
|
|
|
|
|
|
|
|
|
|
# for ["tixcraft"]
|
|
|
|
|
date_auto_select_enable = config_dict["tixcraft"]["date_auto_select"]["enable"]
|
|
|
|
|
date_auto_select_mode = config_dict["tixcraft"]["date_auto_select"]["mode"]
|
|
|
|
|
if not date_auto_select_mode in CONST_SELECT_OPTIONS_ARRAY:
|
|
|
|
|
date_auto_select_mode = CONST_SELECT_ORDER_DEFAULT
|
|
|
|
|
|
|
|
|
|
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
|
|
|
|
|
|
|
|
|
|
area_auto_select_enable = config_dict["tixcraft"]["area_auto_select"]["enable"]
|
|
|
|
|
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"]
|
|
|
|
|
if not area_auto_select_mode in CONST_SELECT_OPTIONS_ARRAY:
|
|
|
|
|
area_auto_select_mode = CONST_SELECT_ORDER_DEFAULT
|
|
|
|
|
|
|
|
|
|
area_keyword_1 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_1"].strip()
|
|
|
|
|
area_keyword_2 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_2"].strip()
|
|
|
|
|
area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip()
|
|
|
|
|
area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip()
|
|
|
|
|
|
|
|
|
|
pass_date_is_sold_out_enable = config_dict["tixcraft"]["pass_date_is_sold_out"]
|
|
|
|
|
auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
|
|
|
|
|
|
|
|
|
|
# output config:
|
|
|
|
|
print("maxbot app version", CONST_APP_VERSION)
|
|
|
|
|
print("python version", platform.python_version())
|
2023-01-12 08:51:05 +00:00
|
|
|
|
print("platform", platform.platform())
|
2022-11-23 04:39:46 +00:00
|
|
|
|
print("homepage", homepage)
|
|
|
|
|
print("browser", browser)
|
|
|
|
|
print("ticket_number", ticket_number)
|
2022-11-24 21:40:40 +00:00
|
|
|
|
print("pass_1_seat_remaining", pass_1_seat_remaining_enable)
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
|
|
|
|
# for kktix
|
|
|
|
|
print("==[kktix]==")
|
|
|
|
|
print("auto_press_next_step_button", auto_press_next_step_button)
|
|
|
|
|
print("auto_fill_ticket_number", auto_fill_ticket_number)
|
|
|
|
|
print("kktix_area_keyword_1", kktix_area_keyword_1)
|
|
|
|
|
print("kktix_area_keyword_1_and", kktix_area_keyword_1_and)
|
|
|
|
|
print("kktix_area_keyword_2", kktix_area_keyword_2)
|
|
|
|
|
print("kktix_area_keyword_2_and", kktix_area_keyword_2_and)
|
|
|
|
|
print("auto_guess_options", auto_guess_options)
|
|
|
|
|
|
|
|
|
|
# for tixcraft
|
|
|
|
|
print("==[tixcraft]==")
|
|
|
|
|
print("date_auto_select_enable", date_auto_select_enable)
|
|
|
|
|
print("date_auto_select_mode", date_auto_select_mode)
|
|
|
|
|
print("date_keyword", date_keyword)
|
2023-01-12 08:51:05 +00:00
|
|
|
|
print("pass_date_is_sold_out", pass_date_is_sold_out_enable)
|
|
|
|
|
print("auto_reload_coming_soon_page", auto_reload_coming_soon_page_enable)
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
|
|
|
|
print("area_auto_select_enable", area_auto_select_enable)
|
|
|
|
|
print("area_auto_select_mode", area_auto_select_mode)
|
|
|
|
|
print("area_keyword_1", area_keyword_1)
|
|
|
|
|
print("area_keyword_2", area_keyword_2)
|
|
|
|
|
print("area_keyword_3", area_keyword_3)
|
|
|
|
|
print("area_keyword_4", area_keyword_4)
|
|
|
|
|
|
2023-01-12 08:51:05 +00:00
|
|
|
|
print("presale_code", config_dict["tixcraft"]["presale_code"])
|
|
|
|
|
print("ocr_captcha", config_dict['ocr_captcha'])
|
|
|
|
|
print("==[advanced]==")
|
|
|
|
|
print("play_captcha_sound", config_dict["advanced"]["play_captcha_sound"]["enable"])
|
|
|
|
|
print("sound file path", config_dict["advanced"]["play_captcha_sound"]["filename"])
|
|
|
|
|
print("adblock_plus_enable", config_dict["advanced"]["adblock_plus_enable"])
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
|
|
|
|
# entry point
|
|
|
|
|
if homepage is None:
|
|
|
|
|
homepage = ""
|
|
|
|
|
if len(homepage) == 0:
|
|
|
|
|
homepage = CONST_HOMEPAGE_DEFAULT
|
|
|
|
|
|
|
|
|
|
Root_Dir = get_app_root()
|
|
|
|
|
webdriver_path = os.path.join(Root_Dir, "webdriver")
|
|
|
|
|
print("platform.system().lower():", platform.system().lower())
|
|
|
|
|
|
|
|
|
|
adblock_plus_enable = config_dict["advanced"]["adblock_plus_enable"]
|
|
|
|
|
print("adblock_plus_enable:", adblock_plus_enable)
|
|
|
|
|
|
|
|
|
|
if browser == "chrome":
|
|
|
|
|
# method 6: Selenium Stealth
|
|
|
|
|
if driver_type != "undetected_chromedriver":
|
|
|
|
|
driver = load_chromdriver_normal(webdriver_path, driver_type, adblock_plus_enable)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
else:
|
2022-11-23 04:39:46 +00:00
|
|
|
|
# method 5: uc
|
|
|
|
|
# multiprocessing not work bug.
|
|
|
|
|
if platform.system().lower()=="windows":
|
|
|
|
|
if hasattr(sys, 'frozen'):
|
|
|
|
|
from multiprocessing import freeze_support
|
|
|
|
|
freeze_support()
|
|
|
|
|
driver = load_chromdriver_uc(webdriver_path, adblock_plus_enable)
|
|
|
|
|
|
|
|
|
|
if browser == "firefox":
|
|
|
|
|
# default os is linux/mac
|
|
|
|
|
chromedriver_path = os.path.join(webdriver_path,"geckodriver")
|
|
|
|
|
if platform.system().lower()=="windows":
|
|
|
|
|
chromedriver_path = os.path.join(webdriver_path,"geckodriver.exe")
|
|
|
|
|
|
|
|
|
|
firefox_service = Service(chromedriver_path)
|
|
|
|
|
driver = webdriver.Firefox(service=firefox_service)
|
|
|
|
|
|
|
|
|
|
#print("try to close opened tabs.")
|
|
|
|
|
'''
|
|
|
|
|
time.sleep(1.0)
|
|
|
|
|
for i in range(1):
|
|
|
|
|
close_browser_tabs(driver)
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
if driver is None:
|
|
|
|
|
print("create web driver object fail @_@;")
|
2022-01-12 17:14:27 +00:00
|
|
|
|
else:
|
2022-11-23 04:39:46 +00:00
|
|
|
|
try:
|
|
|
|
|
print("goto url:", homepage)
|
|
|
|
|
if homepage=="https://tixcraft.com":
|
|
|
|
|
homepage="https://tixcraft.com/user/changeLanguage/lang/zh_tw"
|
|
|
|
|
driver.get(homepage)
|
|
|
|
|
except WebDriverException as exce2:
|
|
|
|
|
print('oh no not again, WebDriverException')
|
|
|
|
|
print('WebDriverException:', exce2)
|
|
|
|
|
except Exception as exce1:
|
|
|
|
|
print('get URL Exception:', exec1)
|
|
|
|
|
pass
|
2021-12-24 10:52:37 +00:00
|
|
|
|
|
2022-01-12 17:14:27 +00:00
|
|
|
|
return driver
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
# common functions.
|
|
|
|
|
def find_between( s, first, last ):
|
|
|
|
|
try:
|
|
|
|
|
start = s.index( first ) + len( first )
|
|
|
|
|
end = s.index( last, start )
|
|
|
|
|
return s[start:end]
|
|
|
|
|
except ValueError:
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
# convert web string to reg pattern
|
|
|
|
|
def convert_string_to_pattern(my_str, dynamic_length=True):
|
|
|
|
|
my_hint_anwser_length = len(my_str)
|
|
|
|
|
my_formated = ""
|
|
|
|
|
if my_hint_anwser_length > 0:
|
|
|
|
|
my_anwser_symbols = u"()[]<>{}-"
|
|
|
|
|
for idx in range(my_hint_anwser_length):
|
|
|
|
|
char = my_str[idx:idx+1]
|
|
|
|
|
|
|
|
|
|
if char in my_anwser_symbols:
|
|
|
|
|
my_formated += (u'\\' + char)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
pattern = re.compile(u"[A-Z]")
|
|
|
|
|
match_result = pattern.match(char)
|
|
|
|
|
#print("match_result A:", match_result)
|
|
|
|
|
if not match_result is None:
|
|
|
|
|
my_formated += u"[A-Z]"
|
|
|
|
|
|
|
|
|
|
pattern = re.compile(u"[a-z]")
|
|
|
|
|
match_result = pattern.match(char)
|
|
|
|
|
#print("match_result a:", match_result)
|
|
|
|
|
if not match_result is None:
|
|
|
|
|
my_formated += u"[a-z]"
|
|
|
|
|
|
|
|
|
|
pattern = re.compile(u"[\d]")
|
|
|
|
|
match_result = pattern.match(char)
|
|
|
|
|
#print("match_result d:", match_result)
|
|
|
|
|
if not match_result is None:
|
|
|
|
|
my_formated += u"[\d]"
|
|
|
|
|
|
|
|
|
|
# for dynamic length
|
|
|
|
|
if dynamic_length:
|
|
|
|
|
for i in range(10):
|
|
|
|
|
my_formated = my_formated.replace(u"[A-Z][A-Z]",u"[A-Z]")
|
|
|
|
|
my_formated = my_formated.replace(u"[a-z][a-z]",u"[a-z]")
|
|
|
|
|
my_formated = my_formated.replace(u"[\d][\d]",u"[\d]")
|
|
|
|
|
|
|
|
|
|
my_formated = my_formated.replace(u"[A-Z]",u"[A-Z]+")
|
|
|
|
|
my_formated = my_formated.replace(u"[a-z]",u"[a-z]+")
|
|
|
|
|
my_formated = my_formated.replace(u"[\d]",u"[\d]+")
|
|
|
|
|
return my_formated
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
def guess_answer_list_from_multi_options(tmp_text):
|
|
|
|
|
options_list = None
|
|
|
|
|
if options_list is None:
|
|
|
|
|
if u'【' in tmp_text and u'】' in tmp_text:
|
|
|
|
|
options_list = re.findall(u'【.*?】', tmp_text)
|
|
|
|
|
if len(options_list) <= 2:
|
|
|
|
|
options_list = None
|
|
|
|
|
|
|
|
|
|
if options_list is None:
|
|
|
|
|
if u'(' in tmp_text and u')' in tmp_text:
|
|
|
|
|
options_list = re.findall(u'\(.*?\)', tmp_text)
|
|
|
|
|
if len(options_list) <= 2:
|
|
|
|
|
options_list = None
|
|
|
|
|
|
|
|
|
|
if options_list is None:
|
|
|
|
|
if u'[' in tmp_text and u']' in tmp_text:
|
|
|
|
|
options_list = re.findall(u'[.*?]', tmp_text)
|
|
|
|
|
if len(options_list) <= 2:
|
|
|
|
|
options_list = None
|
|
|
|
|
|
|
|
|
|
return_list = None
|
2023-01-03 22:12:21 +00:00
|
|
|
|
if not options_list is None:
|
|
|
|
|
options_list_length = len(options_list)
|
|
|
|
|
if options_list_length > 2:
|
|
|
|
|
is_all_options_same_length = True
|
|
|
|
|
for i in range(options_list_length-1):
|
|
|
|
|
if len(options_list[i]) != len(options_list[i]):
|
|
|
|
|
is_all_options_same_length = False
|
|
|
|
|
|
|
|
|
|
if is_all_options_same_length:
|
|
|
|
|
return_list = []
|
|
|
|
|
for each_option in options_list:
|
|
|
|
|
return_list.append(each_option[1:-1])
|
2023-01-02 20:37:54 +00:00
|
|
|
|
return return_list
|
|
|
|
|
|
|
|
|
|
#PS: this may get a wrong answer list. XD
|
|
|
|
|
def guess_answer_list_from_symbols(captcha_text_div_text):
|
|
|
|
|
return_list = None
|
|
|
|
|
# need replace to space to get first options.
|
|
|
|
|
tmp_text = captcha_text_div_text
|
|
|
|
|
tmp_text = tmp_text.replace(u'?',u' ')
|
|
|
|
|
tmp_text = tmp_text.replace(u'?',u' ')
|
|
|
|
|
tmp_text = tmp_text.replace(u'。',u' ')
|
|
|
|
|
|
|
|
|
|
delimitor_symbols_left = [u"(",u"[",u"{", " ", " ", " ", " "]
|
|
|
|
|
delimitor_symbols_right = [u")",u"]",u"}", ":", ".", ")", "-"]
|
|
|
|
|
idx = -1
|
|
|
|
|
for idx in range(len(delimitor_symbols_left)):
|
|
|
|
|
symbol_left = delimitor_symbols_left[idx]
|
|
|
|
|
symbol_right = delimitor_symbols_right[idx]
|
|
|
|
|
if symbol_left in tmp_text and symbol_right in tmp_text and u'半形' in tmp_text:
|
|
|
|
|
hint_list = re.findall(u'\\'+ symbol_left + u'[\\w]+\\'+ symbol_right , tmp_text)
|
|
|
|
|
#print("hint_list:", hint_list)
|
|
|
|
|
if not hint_list is None:
|
|
|
|
|
if len(hint_list) > 1:
|
|
|
|
|
return_list = []
|
|
|
|
|
my_answer_delimitor = symbol_right
|
|
|
|
|
for options in hint_list:
|
|
|
|
|
if len(options) > 2:
|
|
|
|
|
my_anwser = options[1:-1]
|
|
|
|
|
#print("my_anwser:",my_anwser)
|
|
|
|
|
if len(my_anwser) > 0:
|
|
|
|
|
return_list.append(my_anwser)
|
|
|
|
|
|
|
|
|
|
if not return_list is None:
|
|
|
|
|
break
|
|
|
|
|
return return_list
|
|
|
|
|
|
|
|
|
|
def get_offical_hint_string_from_symbol(symbol, tmp_text):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
|
|
|
|
offical_hint_string = ""
|
|
|
|
|
if symbol in tmp_text:
|
|
|
|
|
# start to guess offical hint
|
|
|
|
|
if offical_hint_string == "":
|
|
|
|
|
if u'【' in tmp_text and u'】' in tmp_text:
|
|
|
|
|
hint_list = re.findall(u'【.*?】', tmp_text)
|
|
|
|
|
if not hint_list is None:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("【.*?】hint_list:", hint_list)
|
|
|
|
|
for hint in hint_list:
|
|
|
|
|
if symbol in hint:
|
|
|
|
|
offical_hint_string = hint[1:-1]
|
|
|
|
|
break
|
|
|
|
|
if offical_hint_string == "":
|
|
|
|
|
if u'(' in tmp_text and u')' in tmp_text:
|
|
|
|
|
hint_list = re.findall(u'\(.*?\)', tmp_text)
|
|
|
|
|
if not hint_list is None:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("\(.*?\)hint_list:", hint_list)
|
|
|
|
|
for hint in hint_list:
|
|
|
|
|
if symbol in hint:
|
|
|
|
|
offical_hint_string = hint[1:-1]
|
|
|
|
|
break
|
|
|
|
|
if offical_hint_string == "":
|
|
|
|
|
if u'[' in tmp_text and u']' in tmp_text:
|
|
|
|
|
hint_list = re.findall(u'[.*?]', tmp_text)
|
|
|
|
|
if not hint_list is None:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("[.*?]hint_list:", hint_list)
|
|
|
|
|
for hint in hint_list:
|
|
|
|
|
if symbol in hint:
|
|
|
|
|
offical_hint_string = hint[1:-1]
|
|
|
|
|
break
|
|
|
|
|
if offical_hint_string == "":
|
|
|
|
|
offical_hint_string = tmp_text
|
|
|
|
|
return offical_hint_string
|
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
def guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text):
|
2023-01-02 20:37:54 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
return_list = None
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
tmp_text = format_question_string(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
my_question = ""
|
|
|
|
|
my_options = ""
|
|
|
|
|
offical_hint_string = ""
|
|
|
|
|
offical_hint_string_anwser = ""
|
|
|
|
|
my_anwser_formated = ""
|
2019-10-01 17:52:13 +00:00
|
|
|
|
my_answer_delimitor = ""
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if my_question == "":
|
|
|
|
|
if u"?" in tmp_text:
|
|
|
|
|
question_index = tmp_text.find(u"?")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
my_question = tmp_text[:question_index+1]
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if my_question == "":
|
2019-10-01 17:52:13 +00:00
|
|
|
|
if u"。" in tmp_text:
|
|
|
|
|
question_index = tmp_text.find(u"。")
|
|
|
|
|
my_question = tmp_text[:question_index+1]
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if my_question == "":
|
|
|
|
|
my_question = tmp_text
|
|
|
|
|
#print(u"my_question:", my_question)
|
|
|
|
|
|
|
|
|
|
# ps: hint_list is not options list
|
|
|
|
|
|
|
|
|
|
if offical_hint_string == "":
|
|
|
|
|
offical_hint_string = get_offical_hint_string_from_symbol(CONST_EXAMPLE_SYMBOL, tmp_text)
|
|
|
|
|
if len(offical_hint_string) > 0:
|
|
|
|
|
right_part = offical_hint_string.split(CONST_EXAMPLE_SYMBOL)[1]
|
|
|
|
|
if len(offical_hint_string) == len(tmp_text):
|
|
|
|
|
offical_hint_string = right_part
|
|
|
|
|
|
|
|
|
|
new_hint = find_continuous_text(right_part)
|
|
|
|
|
if len(new_hint) > 0:
|
|
|
|
|
offical_hint_string_anwser = new_hint
|
|
|
|
|
|
|
|
|
|
if offical_hint_string == "":
|
|
|
|
|
# for: 若你覺得答案為 a,請輸入 a
|
|
|
|
|
if '答案' in tmp_text and CONST_INPUT_SYMBOL in tmp_text:
|
|
|
|
|
offical_hint_string = get_offical_hint_string_from_symbol(CONST_INPUT_SYMBOL, tmp_text)
|
|
|
|
|
if len(offical_hint_string) > 0:
|
|
|
|
|
right_part = offical_hint_string.split(CONST_INPUT_SYMBOL)[1]
|
|
|
|
|
if len(offical_hint_string) == len(tmp_text):
|
|
|
|
|
offical_hint_string = right_part
|
|
|
|
|
|
|
|
|
|
new_hint = find_continuous_text(right_part)
|
|
|
|
|
if len(new_hint) > 0:
|
|
|
|
|
# TODO: 答案為B需填入Bb)
|
|
|
|
|
#if u'答案' in offical_hint_string and CONST_INPUT_SYMBOL in offical_hint_string:
|
|
|
|
|
offical_hint_string_anwser = new_hint
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("offical_hint_string:",offical_hint_string)
|
|
|
|
|
|
|
|
|
|
# try rule4:
|
|
|
|
|
# get hint from rule 3: without '(' & '), but use "*"
|
|
|
|
|
if len(offical_hint_string) == 0:
|
|
|
|
|
target_symbol = u"*"
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", star_index + len(target_symbol))
|
|
|
|
|
offical_hint_string = tmp_text[star_index: space_index]
|
|
|
|
|
|
|
|
|
|
# is need to merge next block
|
|
|
|
|
if len(offical_hint_string) > 0:
|
|
|
|
|
target_symbol = offical_hint_string + u" "
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
next_block_index = star_index + len(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", next_block_index)
|
|
|
|
|
next_block = tmp_text[next_block_index: space_index]
|
|
|
|
|
if CONST_EXAMPLE_SYMBOL in next_block:
|
|
|
|
|
offical_hint_string += u' ' + next_block
|
|
|
|
|
|
|
|
|
|
# try rule5:
|
|
|
|
|
# get hint from rule 3: n個半形英文大寫
|
|
|
|
|
if len(offical_hint_string) == 0:
|
|
|
|
|
target_symbol = u"個半形英文大寫"
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", star_index)
|
|
|
|
|
answer_char_count = tmp_text[star_index-1:star_index]
|
|
|
|
|
if answer_char_count.isnumeric():
|
|
|
|
|
star_index -= 1
|
|
|
|
|
offical_hint_string_anwser = u'A' * int(answer_char_count)
|
|
|
|
|
offical_hint_string = tmp_text[star_index: space_index]
|
|
|
|
|
|
|
|
|
|
target_symbol = u"個英文大寫"
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", star_index)
|
|
|
|
|
answer_char_count = tmp_text[star_index-1:star_index]
|
|
|
|
|
if answer_char_count.isnumeric():
|
|
|
|
|
star_index -= 1
|
|
|
|
|
offical_hint_string_anwser = u'A' * int(answer_char_count)
|
|
|
|
|
offical_hint_string = tmp_text[star_index: space_index]
|
|
|
|
|
|
|
|
|
|
target_symbol = u"個半形英文小寫"
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", star_index)
|
|
|
|
|
answer_char_count = tmp_text[star_index-1:star_index]
|
|
|
|
|
if answer_char_count.isnumeric():
|
|
|
|
|
star_index -= 1
|
|
|
|
|
offical_hint_string_anwser = u'a' * int(answer_char_count)
|
|
|
|
|
offical_hint_string = tmp_text[star_index: space_index]
|
|
|
|
|
|
|
|
|
|
target_symbol = u"個英文小寫"
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", star_index)
|
|
|
|
|
answer_char_count = tmp_text[star_index-1:star_index]
|
|
|
|
|
if answer_char_count.isnumeric():
|
|
|
|
|
star_index -= 1
|
|
|
|
|
offical_hint_string_anwser = u'a' * int(answer_char_count)
|
|
|
|
|
offical_hint_string = tmp_text[star_index: space_index]
|
|
|
|
|
|
|
|
|
|
target_symbol = u"個英數半形字"
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", star_index)
|
|
|
|
|
answer_char_count = tmp_text[star_index-1:star_index]
|
|
|
|
|
if answer_char_count.isnumeric():
|
|
|
|
|
star_index -= 1
|
|
|
|
|
my_anwser_formated = u'[A-Za-z\d]' * int(answer_char_count)
|
|
|
|
|
offical_hint_string = tmp_text[star_index: space_index]
|
|
|
|
|
|
|
|
|
|
target_symbol = u"個半形"
|
|
|
|
|
if target_symbol in tmp_text :
|
|
|
|
|
star_index = tmp_text.find(target_symbol)
|
|
|
|
|
space_index = tmp_text.find(u" ", star_index)
|
|
|
|
|
answer_char_count = tmp_text[star_index-1:star_index]
|
|
|
|
|
if answer_char_count.isnumeric():
|
|
|
|
|
star_index -= 1
|
|
|
|
|
my_anwser_formated = u'[A-Za-z\d]' * int(answer_char_count)
|
|
|
|
|
offical_hint_string = tmp_text[star_index: space_index]
|
|
|
|
|
|
|
|
|
|
if len(offical_hint_string) > 0:
|
|
|
|
|
#print("offical_hint_string_anwser:", offical_hint_string_anwser)
|
|
|
|
|
my_anwser_formated = convert_string_to_pattern(offical_hint_string_anwser)
|
|
|
|
|
|
|
|
|
|
my_options = tmp_text
|
|
|
|
|
if len(my_question) < len(tmp_text):
|
2019-10-01 17:52:13 +00:00
|
|
|
|
my_options = my_options.replace(my_question,u"")
|
2023-01-02 20:37:54 +00:00
|
|
|
|
my_options = my_options.replace(offical_hint_string,u"")
|
|
|
|
|
#print("tmp_text:", tmp_text)
|
|
|
|
|
#print("my_options:", my_options)
|
|
|
|
|
#print("offical_hint_string:", offical_hint_string)
|
|
|
|
|
|
|
|
|
|
# try rule7:
|
|
|
|
|
# check is chinese/english in question, if match, apply my_options rule.
|
|
|
|
|
if len(offical_hint_string) > 0:
|
|
|
|
|
tmp_text_org = captcha_text_div_text
|
|
|
|
|
if CONST_EXAMPLE_SYMBOL in tmp_text:
|
|
|
|
|
tmp_text_org = tmp_text_org.replace(u'Ex:','ex:')
|
|
|
|
|
target_symbol = u"ex:"
|
|
|
|
|
if target_symbol in tmp_text_org :
|
|
|
|
|
star_index = tmp_text_org.find(target_symbol)
|
|
|
|
|
my_options = tmp_text_org[star_index-1:]
|
|
|
|
|
|
|
|
|
|
#print(u"my_options:", my_options)
|
|
|
|
|
|
|
|
|
|
if len(my_anwser_formated) > 0:
|
|
|
|
|
allow_delimitor_symbols = ")].: }"
|
|
|
|
|
pattern = re.compile(my_anwser_formated)
|
|
|
|
|
search_result = pattern.search(my_options)
|
|
|
|
|
if not search_result is None:
|
|
|
|
|
(span_start, span_end) = search_result.span()
|
|
|
|
|
if len(my_options) > (span_end+1)+1:
|
|
|
|
|
maybe_delimitor = my_options[span_end+0:span_end+1]
|
|
|
|
|
if maybe_delimitor in allow_delimitor_symbols:
|
|
|
|
|
my_answer_delimitor = maybe_delimitor
|
|
|
|
|
#print(u"my_answer_delimitor:", my_answer_delimitor)
|
|
|
|
|
|
|
|
|
|
if len(my_anwser_formated) > 0:
|
|
|
|
|
#print("text:" , re.findall('\([\w]+\)', tmp_text))
|
|
|
|
|
new_pattern = my_anwser_formated
|
|
|
|
|
if len(my_answer_delimitor) > 0:
|
|
|
|
|
new_pattern = my_anwser_formated + u'\\' + my_answer_delimitor
|
|
|
|
|
return_list = re.findall(new_pattern, my_options)
|
|
|
|
|
|
|
|
|
|
if not return_list is None:
|
|
|
|
|
if len(return_list) == 1:
|
|
|
|
|
# re-sample for this case.
|
|
|
|
|
return_list = re.findall(my_anwser_formated, my_options)
|
|
|
|
|
|
|
|
|
|
return return_list
|
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
def format_question_string(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text):
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
tmp_text = captcha_text_div_text
|
|
|
|
|
tmp_text = tmp_text.replace(u' ',u' ')
|
|
|
|
|
tmp_text = tmp_text.replace(u':',u':')
|
|
|
|
|
# for hint
|
|
|
|
|
tmp_text = tmp_text.replace(u'*',u'*')
|
|
|
|
|
|
|
|
|
|
# replace ex.
|
|
|
|
|
tmp_text = tmp_text.replace(u'例如', CONST_EXAMPLE_SYMBOL)
|
|
|
|
|
tmp_text = tmp_text.replace(u'如:', CONST_EXAMPLE_SYMBOL)
|
2023-01-14 08:05:00 +00:00
|
|
|
|
tmp_text = tmp_text.replace(u'如為', CONST_EXAMPLE_SYMBOL+'為')
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
tmp_text = tmp_text.replace(u'舉例', CONST_EXAMPLE_SYMBOL)
|
|
|
|
|
if not CONST_EXAMPLE_SYMBOL in tmp_text:
|
|
|
|
|
tmp_text = tmp_text.replace(u'例', CONST_EXAMPLE_SYMBOL)
|
|
|
|
|
# important, maybe 例 & ex occurs at same time.
|
|
|
|
|
tmp_text = tmp_text.replace(u'ex:', CONST_EXAMPLE_SYMBOL)
|
|
|
|
|
tmp_text = tmp_text.replace(u'Ex:', CONST_EXAMPLE_SYMBOL)
|
|
|
|
|
|
|
|
|
|
#若你覺得
|
|
|
|
|
#PS:這個,可能會造成更多問題,呵呵。
|
|
|
|
|
SYMBOL_IF_LIST = ['假設','如果','若']
|
|
|
|
|
for symbol_if in SYMBOL_IF_LIST:
|
|
|
|
|
if symbol_if in tmp_text and '答案' in tmp_text:
|
|
|
|
|
tmp_text = tmp_text.replace('覺得', '')
|
|
|
|
|
tmp_text = tmp_text.replace('認為', '')
|
|
|
|
|
tmp_text = tmp_text.replace(symbol_if + '你答案', CONST_EXAMPLE_SYMBOL + '答案')
|
|
|
|
|
tmp_text = tmp_text.replace(symbol_if + '答案', CONST_EXAMPLE_SYMBOL + '答案')
|
|
|
|
|
|
|
|
|
|
tmp_text = tmp_text.replace(u'填入', CONST_INPUT_SYMBOL)
|
|
|
|
|
|
|
|
|
|
#tmp_text = tmp_text.replace(u'[',u'(')
|
|
|
|
|
#tmp_text = tmp_text.replace(u']',u')')
|
|
|
|
|
tmp_text = tmp_text.replace(u'?',u'?')
|
|
|
|
|
|
|
|
|
|
tmp_text = tmp_text.replace(u'(',u'(')
|
|
|
|
|
tmp_text = tmp_text.replace(u')',u')')
|
|
|
|
|
|
|
|
|
|
return tmp_text
|
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
def get_answer_list_by_question(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text):
|
2023-01-02 20:37:54 +00:00
|
|
|
|
return_list = None
|
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
tmp_text = format_question_string(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
# guess answer list from multi-options: 【】() []
|
|
|
|
|
if return_list is None:
|
|
|
|
|
return_list = guess_answer_list_from_multi_options(tmp_text)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if return_list is None:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
return_list = guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
# try rule8:
|
|
|
|
|
if return_list is None:
|
|
|
|
|
return_list = guess_answer_list_from_symbols(captcha_text_div_text)
|
|
|
|
|
|
|
|
|
|
return return_list
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-09 10:44:29 +00:00
|
|
|
|
# close some div on home url.
|
|
|
|
|
def tixcraft_home(driver):
|
2023-01-13 19:01:47 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
2022-11-09 10:44:29 +00:00
|
|
|
|
accept_all_cookies_btn = None
|
|
|
|
|
try:
|
|
|
|
|
accept_all_cookies_btn = driver.find_element(By.ID, 'onetrust-accept-btn-handler')
|
|
|
|
|
except Exception as exc:
|
2023-01-13 19:01:47 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("find accept_all_cookies_btn fail")
|
2022-11-09 10:44:29 +00:00
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if accept_all_cookies_btn is not None:
|
2022-11-09 18:36:17 +00:00
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
|
|
|
|
if accept_all_cookies_btn.is_enabled() and accept_all_cookies_btn.is_displayed():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
2023-01-13 19:01:47 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("accept_all_cookies_btn visible. start to press.")
|
2022-11-09 10:44:29 +00:00
|
|
|
|
try:
|
|
|
|
|
accept_all_cookies_btn.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("try to click accept_all_cookies_btn fail")
|
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("arguments[0].click();", accept_all_cookies_btn)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-13 19:01:47 +00:00
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("accept_all_cookies_btn invisible.")
|
2022-11-09 10:44:29 +00:00
|
|
|
|
|
|
|
|
|
close_all_alert_btns = None
|
|
|
|
|
try:
|
|
|
|
|
close_all_alert_btns = driver.find_elements(By.CSS_SELECTOR, "[class='close-alert']")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find close_all_alert_btns fail")
|
|
|
|
|
|
|
|
|
|
if close_all_alert_btns is not None:
|
|
|
|
|
#print('alert count:', len(close_all_alert_btns))
|
|
|
|
|
for alert_btn in close_all_alert_btns:
|
2022-11-09 18:36:17 +00:00
|
|
|
|
# fix bug: Message: stale element reference: element is not attached to the page document
|
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
|
|
|
|
if alert_btn.is_enabled() and alert_btn.is_displayed():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
2022-11-09 10:44:29 +00:00
|
|
|
|
try:
|
|
|
|
|
alert_btn.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("try to click alert_btn fail")
|
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("arguments[0].click();", alert_btn)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# from detail to game
|
2022-01-12 17:14:27 +00:00
|
|
|
|
def tixcraft_redirect(driver, url):
|
2022-03-24 15:22:43 +00:00
|
|
|
|
ret = False
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
game_name = ""
|
|
|
|
|
|
|
|
|
|
# get game_name from url
|
2023-01-11 13:58:55 +00:00
|
|
|
|
url_split = url.split("/")
|
|
|
|
|
if len(url_split) >= 6:
|
|
|
|
|
game_name = url_split[5]
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2020-07-25 20:35:54 +00:00
|
|
|
|
if "/activity/detail/%s" % (game_name,) in url:
|
2020-02-03 15:51:05 +00:00
|
|
|
|
# to support teamear
|
2020-07-25 20:35:54 +00:00
|
|
|
|
entry_url = url.replace("/activity/detail/","/activity/game/")
|
2022-06-24 17:29:48 +00:00
|
|
|
|
print("redirec to new url:", entry_url)
|
|
|
|
|
try:
|
|
|
|
|
driver.get(entry_url)
|
|
|
|
|
except Exception as exec1:
|
|
|
|
|
pass
|
2022-03-24 15:22:43 +00:00
|
|
|
|
ret = True
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def tixcraft_date_auto_select(driver, url, config_dict):
|
2023-01-03 18:54:42 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2023-01-12 08:51:05 +00:00
|
|
|
|
show_debug_message = False # online
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
# read config.
|
|
|
|
|
date_auto_select_mode = config_dict["tixcraft"]["date_auto_select"]["mode"]
|
2022-11-18 22:59:34 +00:00
|
|
|
|
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
|
2022-11-16 15:43:53 +00:00
|
|
|
|
pass_date_is_sold_out_enable = config_dict["tixcraft"]["pass_date_is_sold_out"]
|
|
|
|
|
auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
|
|
|
|
|
|
2022-03-17 01:15:05 +00:00
|
|
|
|
# PS: for big events, check sold out text maybe not helpful, due to database is too busy.
|
2022-03-24 15:22:43 +00:00
|
|
|
|
sold_out_text_list = ["選購一空","No tickets available","空席なし"]
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
game_name = ""
|
|
|
|
|
|
2020-07-25 20:35:54 +00:00
|
|
|
|
if "/activity/game/" in url:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
url_split = url.split("/")
|
|
|
|
|
if len(url_split) >= 6:
|
|
|
|
|
game_name = url_split[5]
|
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if show_debug_message:
|
2022-01-12 17:14:27 +00:00
|
|
|
|
print('get date game_name:', game_name)
|
|
|
|
|
print("date_auto_select_mode:", date_auto_select_mode)
|
|
|
|
|
print("date_keyword:", date_keyword)
|
|
|
|
|
|
2022-03-24 15:22:43 +00:00
|
|
|
|
check_game_detail = False
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# choose date
|
2020-07-25 20:35:54 +00:00
|
|
|
|
if "/activity/game/%s" % (game_name,) in url:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if show_debug_message:
|
2022-03-24 15:22:43 +00:00
|
|
|
|
if len(date_keyword) == 0:
|
2022-01-12 17:14:27 +00:00
|
|
|
|
print("date keyword is empty.")
|
2022-03-24 15:22:43 +00:00
|
|
|
|
else:
|
|
|
|
|
print("date keyword:", date_keyword)
|
|
|
|
|
check_game_detail = True
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
date_list = None
|
2022-03-24 15:22:43 +00:00
|
|
|
|
if check_game_detail:
|
|
|
|
|
try:
|
|
|
|
|
date_list = driver.find_elements(By.CSS_SELECTOR, '#gameList > table > tbody > tr')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find #gameList fail")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
is_coming_soon = False
|
|
|
|
|
coming_soon_condictions_list = ['開賣','剩餘','天','小時','分鐘','秒','0',':','/']
|
|
|
|
|
|
|
|
|
|
button_list = None
|
|
|
|
|
if date_list is not None:
|
2022-03-24 15:22:43 +00:00
|
|
|
|
button_list = []
|
2023-01-11 13:58:55 +00:00
|
|
|
|
for row in date_list:
|
|
|
|
|
# step 1: check keyword.
|
|
|
|
|
is_match_keyword_row = False
|
2022-03-24 15:22:43 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
row_text = ""
|
|
|
|
|
try:
|
|
|
|
|
row_text = row.text
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("get text fail")
|
|
|
|
|
# should use continue or break?
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if row_text is None:
|
2022-03-24 15:22:43 +00:00
|
|
|
|
row_text = ""
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
is_match_all_coming_soon_condiction = True
|
|
|
|
|
for condiction_string in coming_soon_condictions_list:
|
|
|
|
|
if not condiction_string in row_text:
|
|
|
|
|
is_match_all_coming_soon_condiction = False
|
|
|
|
|
break
|
|
|
|
|
if is_match_all_coming_soon_condiction:
|
|
|
|
|
is_coming_soon = True
|
|
|
|
|
break
|
2022-11-13 04:50:53 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
if len(date_keyword) == 0:
|
|
|
|
|
# no keyword, match all.
|
|
|
|
|
is_match_keyword_row = True
|
|
|
|
|
else:
|
|
|
|
|
# check keyword.
|
|
|
|
|
if date_keyword in row_text:
|
2022-03-24 15:22:43 +00:00
|
|
|
|
is_match_keyword_row = True
|
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
# step 2: check sold out.
|
|
|
|
|
if is_match_keyword_row:
|
|
|
|
|
if pass_date_is_sold_out_enable:
|
|
|
|
|
for sold_out_item in sold_out_text_list:
|
|
|
|
|
row_text_right_part = row_text[(len(sold_out_item)+5)*-1:]
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 13:58:55 +00:00
|
|
|
|
print("check right part text:", row_text_right_part)
|
|
|
|
|
if sold_out_item in row_text_right_part:
|
|
|
|
|
is_match_keyword_row = False
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 13:58:55 +00:00
|
|
|
|
print("match sold out text: %s, skip this row." % (sold_out_item))
|
|
|
|
|
|
|
|
|
|
# no need check next language item.
|
2022-03-24 15:22:43 +00:00
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
# step 3: add to list.
|
|
|
|
|
if is_match_keyword_row:
|
|
|
|
|
el = None
|
|
|
|
|
try:
|
|
|
|
|
el = row.find_element(By.CSS_SELECTOR, '.btn-next')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("find .btn-next fail")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if el is not None:
|
|
|
|
|
button_list.append(el)
|
|
|
|
|
if date_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
# only need one row.
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("match date row, only need first row, start to break")
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
is_date_selected = False
|
|
|
|
|
if button_list is not None:
|
2022-03-24 15:22:43 +00:00
|
|
|
|
if len(button_list) > 0:
|
|
|
|
|
# default first row.
|
|
|
|
|
target_row_index = 0
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-03-24 15:22:43 +00:00
|
|
|
|
if date_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(button_list) - 1
|
|
|
|
|
|
|
|
|
|
if date_auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(button_list)-1)
|
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-12 08:51:05 +00:00
|
|
|
|
print("clicking row:", target_row_index+1)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
try:
|
2022-03-24 15:22:43 +00:00
|
|
|
|
el = button_list[target_row_index]
|
|
|
|
|
el.click()
|
2022-09-19 16:20:51 +00:00
|
|
|
|
is_date_selected = True
|
2022-03-24 15:22:43 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("try to click .btn-next fail")
|
2022-09-19 16:20:51 +00:00
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("arguments[0].click();", el)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-10-18 18:15:05 +00:00
|
|
|
|
# PS: Is this case need to reload page?
|
2022-03-24 15:22:43 +00:00
|
|
|
|
# (A)user input keywords, with matched text, but no hyperlink to click.
|
|
|
|
|
# (B)user input keywords, but not no matched text with hyperlink to click.
|
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
# [PS]: current reload condition only when
|
|
|
|
|
if auto_reload_coming_soon_page_enable:
|
|
|
|
|
if is_coming_soon:
|
|
|
|
|
# case 2: match one row is coming soon.
|
2022-03-17 01:15:05 +00:00
|
|
|
|
try:
|
2023-01-11 13:58:55 +00:00
|
|
|
|
driver.refresh()
|
2022-03-17 01:15:05 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-11 13:58:55 +00:00
|
|
|
|
else:
|
|
|
|
|
if not is_date_selected:
|
|
|
|
|
# case 1: No hyperlink button.
|
|
|
|
|
el_list = None
|
|
|
|
|
try:
|
|
|
|
|
el_list = driver.find_elements(By.CSS_SELECTOR, '.btn-next')
|
|
|
|
|
if el_list is None:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
else:
|
|
|
|
|
if len(el_list) == 0:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-03-24 15:22:43 +00:00
|
|
|
|
return is_date_selected
|
|
|
|
|
|
2019-10-27 01:31:22 +00:00
|
|
|
|
# PURPOSE: get target area list.
|
2022-10-18 18:15:05 +00:00
|
|
|
|
# RETURN:
|
2021-03-22 09:07:28 +00:00
|
|
|
|
# is_need_refresh
|
2023-01-02 06:53:28 +00:00
|
|
|
|
# matched_blocks
|
|
|
|
|
# PS: matched_blocks will be None, if length equals zero.
|
2022-02-18 18:53:55 +00:00
|
|
|
|
def get_tixcraft_target_area(el, area_keyword, area_auto_select_mode, pass_1_seat_remaining_enable):
|
2022-11-18 22:59:34 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
2022-02-18 18:53:55 +00:00
|
|
|
|
|
2019-10-27 01:31:22 +00:00
|
|
|
|
is_need_refresh = False
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks = None
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2021-03-22 09:07:28 +00:00
|
|
|
|
area_list = None
|
|
|
|
|
area_list_count = 0
|
2019-10-27 01:31:22 +00:00
|
|
|
|
if el is not None:
|
2021-03-21 06:14:20 +00:00
|
|
|
|
try:
|
|
|
|
|
area_list = el.find_elements(By.TAG_NAME, 'a')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("find area list a tag fail")
|
|
|
|
|
pass
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2021-03-21 06:14:20 +00:00
|
|
|
|
if area_list is not None:
|
2021-03-22 09:07:28 +00:00
|
|
|
|
area_list_count = len(area_list)
|
|
|
|
|
if area_list_count == 0:
|
2023-01-12 08:51:05 +00:00
|
|
|
|
print("area list is empty, do refresh!")
|
2019-10-27 01:31:22 +00:00
|
|
|
|
is_need_refresh = True
|
|
|
|
|
else:
|
2023-01-12 08:51:05 +00:00
|
|
|
|
print("area list is None, do refresh!")
|
2021-03-21 06:14:20 +00:00
|
|
|
|
is_need_refresh = True
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2021-03-22 09:07:28 +00:00
|
|
|
|
if area_list_count > 0:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks = []
|
2021-03-22 09:07:28 +00:00
|
|
|
|
for row in area_list:
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
try:
|
|
|
|
|
row_is_enabled = row.is_enabled()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
row_text = ""
|
|
|
|
|
if row_is_enabled:
|
2021-03-21 06:14:20 +00:00
|
|
|
|
try:
|
2021-03-22 09:07:28 +00:00
|
|
|
|
row_text = row.text
|
2021-03-21 06:14:20 +00:00
|
|
|
|
except Exception as exc:
|
2021-03-22 09:07:28 +00:00
|
|
|
|
print("get text fail")
|
|
|
|
|
break
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2022-11-13 04:50:53 +00:00
|
|
|
|
if row_text is None:
|
|
|
|
|
row_text = ""
|
|
|
|
|
|
2021-03-22 09:07:28 +00:00
|
|
|
|
if len(row_text) > 0:
|
2022-10-22 01:19:57 +00:00
|
|
|
|
# clean stop word.
|
2022-11-06 09:10:35 +00:00
|
|
|
|
row_text = format_keyword_string(row_text)
|
2022-10-22 01:19:57 +00:00
|
|
|
|
|
2021-03-22 09:07:28 +00:00
|
|
|
|
is_append_this_row = False
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2021-03-22 09:07:28 +00:00
|
|
|
|
if len(area_keyword) > 0:
|
2022-10-22 01:19:57 +00:00
|
|
|
|
# clean stop word.
|
2022-11-06 09:10:35 +00:00
|
|
|
|
area_keyword = format_keyword_string(area_keyword)
|
2022-10-22 01:19:57 +00:00
|
|
|
|
|
2022-11-09 17:56:12 +00:00
|
|
|
|
# allow only input stop word in keyword fields.
|
|
|
|
|
# for keyword#2 to select all.
|
|
|
|
|
if len(area_keyword) > 0:
|
2021-03-22 09:07:28 +00:00
|
|
|
|
# must match keyword.
|
|
|
|
|
if area_keyword in row_text:
|
2021-03-21 06:14:20 +00:00
|
|
|
|
is_append_this_row = True
|
2021-03-22 09:07:28 +00:00
|
|
|
|
else:
|
|
|
|
|
# without keyword.
|
|
|
|
|
is_append_this_row = True
|
|
|
|
|
|
|
|
|
|
if is_append_this_row:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("pass_1_seat_remaining_enable:", pass_1_seat_remaining_enable)
|
2021-03-22 09:07:28 +00:00
|
|
|
|
if pass_1_seat_remaining_enable:
|
|
|
|
|
area_item_font_el = None
|
|
|
|
|
try:
|
|
|
|
|
#print('try to find font tag at row:', row_text)
|
|
|
|
|
area_item_font_el = row.find_element(By.TAG_NAME, 'font')
|
|
|
|
|
if not area_item_font_el is None:
|
|
|
|
|
font_el_text = area_item_font_el.text
|
2022-11-13 04:50:53 +00:00
|
|
|
|
if font_el_text is None:
|
|
|
|
|
font_el_text = ""
|
2022-02-18 18:53:55 +00:00
|
|
|
|
font_el_text = "@%s@" % (font_el_text)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print('font tag text:', font_el_text)
|
|
|
|
|
pass
|
|
|
|
|
for check_item in CONT_STRING_1_SEATS_REMAINING:
|
|
|
|
|
if check_item in font_el_text:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("match pass 1 seats remaining 1 full text:", row_text)
|
|
|
|
|
print("match pass 1 seats remaining 2 font text:", font_el_text)
|
|
|
|
|
is_append_this_row = False
|
2021-03-22 09:07:28 +00:00
|
|
|
|
else:
|
|
|
|
|
#print("row withou font tag.")
|
2021-03-21 06:14:20 +00:00
|
|
|
|
pass
|
2021-03-22 09:07:28 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("find font text in a tag fail:", exc)
|
|
|
|
|
pass
|
2021-03-21 06:14:20 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("is_append_this_row:", is_append_this_row)
|
|
|
|
|
|
2021-03-22 09:07:28 +00:00
|
|
|
|
if is_append_this_row:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks.append(row)
|
2021-03-21 06:14:20 +00:00
|
|
|
|
|
2021-03-22 09:07:28 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
print("only need first item, break area list loop.")
|
|
|
|
|
break
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("row_text:" + row_text)
|
|
|
|
|
print("match:" + area_keyword)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if len(matched_blocks) == 0:
|
|
|
|
|
matched_blocks = None
|
2021-03-22 09:07:28 +00:00
|
|
|
|
is_need_refresh = True
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
return is_need_refresh, matched_blocks
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
# PS: auto refresh condition 1: no keyword + no hyperlink.
|
|
|
|
|
# PS: auto refresh condition 2: with keyword + no hyperlink.
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def tixcraft_area_auto_select(driver, url, config_dict):
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
# read config.
|
|
|
|
|
area_keyword_1 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_1"].strip()
|
|
|
|
|
area_keyword_2 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_2"].strip()
|
|
|
|
|
area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip()
|
|
|
|
|
area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip()
|
|
|
|
|
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"]
|
2022-11-24 21:40:40 +00:00
|
|
|
|
|
|
|
|
|
pass_1_seat_remaining_enable = config_dict["pass_1_seat_remaining"]
|
|
|
|
|
# disable pass 1 seat remaining when target ticket number is 1.
|
|
|
|
|
ticket_number = config_dict["ticket_number"]
|
|
|
|
|
if ticket_number == 1:
|
|
|
|
|
pass_1_seat_remaining_enable = False
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("area_keyword_1, area_keyword_2:", area_keyword_1, area_keyword_2)
|
2022-11-09 17:56:12 +00:00
|
|
|
|
print("area_keyword_3, area_keyword_4:", area_keyword_3, area_keyword_4)
|
2022-02-18 18:53:55 +00:00
|
|
|
|
|
2020-07-25 20:35:54 +00:00
|
|
|
|
if '/ticket/area/' in url:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
#driver.switch_to.default_content()
|
|
|
|
|
|
|
|
|
|
el = None
|
|
|
|
|
try:
|
|
|
|
|
el = driver.find_element(By.CSS_SELECTOR, '.zone')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find .zone fail, do nothing.")
|
|
|
|
|
|
|
|
|
|
if el is not None:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_1, area_auto_select_mode, pass_1_seat_remaining_enable)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("is_need_refresh for keyword1:", is_need_refresh)
|
|
|
|
|
|
|
|
|
|
if is_need_refresh:
|
2019-10-27 01:31:22 +00:00
|
|
|
|
if areas is None:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("use area keyword #2", area_keyword_2)
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-02-18 18:53:55 +00:00
|
|
|
|
# only when keyword#2 filled to query.
|
|
|
|
|
if len(area_keyword_2) > 0 :
|
|
|
|
|
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_2, area_auto_select_mode, pass_1_seat_remaining_enable)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-02-18 18:53:55 +00:00
|
|
|
|
print("is_need_refresh for keyword2:", is_need_refresh)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-09 17:56:12 +00:00
|
|
|
|
if is_need_refresh:
|
|
|
|
|
if areas is None:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-11-09 17:56:12 +00:00
|
|
|
|
print("use area keyword #3", area_keyword_3)
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-09 17:56:12 +00:00
|
|
|
|
# only when keyword#3 filled to query.
|
|
|
|
|
if len(area_keyword_3) > 0 :
|
|
|
|
|
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_3, area_auto_select_mode, pass_1_seat_remaining_enable)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-11-09 17:56:12 +00:00
|
|
|
|
print("is_need_refresh for keyword3:", is_need_refresh)
|
|
|
|
|
|
|
|
|
|
if is_need_refresh:
|
|
|
|
|
if areas is None:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-11-09 17:56:12 +00:00
|
|
|
|
print("use area keyword #4", area_keyword_4)
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-09 17:56:12 +00:00
|
|
|
|
# only when keyword#4 filled to query.
|
|
|
|
|
if len(area_keyword_4) > 0 :
|
|
|
|
|
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_4, area_auto_select_mode, pass_1_seat_remaining_enable)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2022-11-09 17:56:12 +00:00
|
|
|
|
print("is_need_refresh for keyword4:", is_need_refresh)
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
area_target = None
|
|
|
|
|
if areas is not None:
|
|
|
|
|
#print("area_auto_select_mode", area_auto_select_mode)
|
|
|
|
|
#print("len(areas)", len(areas))
|
|
|
|
|
if len(areas) > 0:
|
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
|
|
|
|
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(areas)-1
|
|
|
|
|
|
|
|
|
|
if area_auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(areas)-1)
|
|
|
|
|
|
|
|
|
|
#print("target_row_index", target_row_index)
|
|
|
|
|
area_target = areas[target_row_index]
|
|
|
|
|
|
|
|
|
|
if area_target is not None:
|
|
|
|
|
try:
|
2022-11-13 04:50:53 +00:00
|
|
|
|
#print("area text:", area_target.text)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
area_target.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click area a link fail, start to retry...")
|
|
|
|
|
try:
|
2022-09-19 16:20:51 +00:00
|
|
|
|
driver.execute_script("arguments[0].click();", area_target)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click area a link fail, after reftry still fail.")
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# auto refresh for area list page.
|
|
|
|
|
if is_need_refresh:
|
|
|
|
|
try:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
el_selectSeat_iframe = None
|
|
|
|
|
try:
|
|
|
|
|
el_selectSeat_iframe = driver.find_element_by_xpath("//iframe[contains(@src,'/ticket/selectSeat/')]")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("find seat iframe fail")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if el_selectSeat_iframe is not None:
|
|
|
|
|
driver.switch_to.frame(el_selectSeat_iframe)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# click one seat
|
|
|
|
|
el_seat = None
|
|
|
|
|
try:
|
|
|
|
|
el_seat = driver.find_element(By.CSS_SELECTOR, '.empty')
|
|
|
|
|
if el_seat is not None:
|
|
|
|
|
try:
|
|
|
|
|
el_seat.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("click area button fail")
|
|
|
|
|
pass
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find empty seat fail")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# click submit button
|
|
|
|
|
el_confirm_seat = None
|
|
|
|
|
try:
|
|
|
|
|
el_confirm_seat = driver.find_element(By.ID, 'submitSeat')
|
|
|
|
|
if el_confirm_seat is not None:
|
|
|
|
|
try:
|
|
|
|
|
el_confirm_seat.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("click area button fail")
|
|
|
|
|
pass
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find submitSeat fail")
|
|
|
|
|
'''
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def tixcraft_ticket_agree(driver):
|
2022-11-16 17:52:38 +00:00
|
|
|
|
click_plan = "A"
|
2022-11-16 15:43:53 +00:00
|
|
|
|
#click_plan = "B"
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# check agree
|
|
|
|
|
form_checkbox = None
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if click_plan == "A":
|
|
|
|
|
try:
|
|
|
|
|
form_checkbox = driver.find_element(By.ID, 'TicketForm_agree')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find TicketForm_agree fail")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
is_finish_checkbox_click = False
|
|
|
|
|
if form_checkbox is not None:
|
|
|
|
|
try:
|
|
|
|
|
# TODO: check the status: checked.
|
|
|
|
|
if form_checkbox.is_enabled():
|
2023-01-12 22:29:58 +00:00
|
|
|
|
if not form_checkbox.is_selected():
|
|
|
|
|
form_checkbox.click()
|
2022-11-16 15:43:53 +00:00
|
|
|
|
is_finish_checkbox_click = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click TicketForm_agree fail")
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-15 11:26:51 +00:00
|
|
|
|
# 使用 plan B.
|
|
|
|
|
#if not is_finish_checkbox_click:
|
|
|
|
|
# alway not use Plan B.
|
|
|
|
|
if False:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
try:
|
2022-11-16 17:52:38 +00:00
|
|
|
|
print("use plan_b to check TicketForm_agree.")
|
2022-11-16 15:43:53 +00:00
|
|
|
|
driver.execute_script("$(\"input[type='checkbox']\").prop('checked', true);")
|
|
|
|
|
#driver.execute_script("document.getElementById(\"TicketForm_agree\").checked;")
|
|
|
|
|
is_finish_checkbox_click = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("javascript check TicketForm_agree fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
return is_finish_checkbox_click
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def tixcraft_ticket_number_auto_fill(driver, select_obj, ticket_number):
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = False
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if select_obj is not None:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
|
|
|
|
# target ticket number
|
2022-11-16 15:43:53 +00:00
|
|
|
|
select_obj.select_by_visible_text(ticket_number)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
#select.select_by_value(ticket_number)
|
|
|
|
|
#select.select_by_index(int(ticket_number))
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("select_by_visible_text ticket_number fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# target ticket number
|
2022-11-16 15:43:53 +00:00
|
|
|
|
select_obj.select_by_visible_text(ticket_number)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
#select.select_by_value(ticket_number)
|
|
|
|
|
#select.select_by_index(int(ticket_number))
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("select_by_visible_text ticket_number fail...2")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
|
|
|
|
# try buy one ticket
|
|
|
|
|
try:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
select_obj.select_by_visible_text("1")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
#select.select_by_value("1")
|
|
|
|
|
#select.select_by_index(int(ticket_number))
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("select_by_visible_text 1 fail")
|
|
|
|
|
pass
|
|
|
|
|
|
2022-12-15 11:26:51 +00:00
|
|
|
|
# Plan B.
|
2023-01-02 06:53:28 +00:00
|
|
|
|
# if not is_ticket_number_assigned:
|
2022-12-15 11:26:51 +00:00
|
|
|
|
if False:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if select is not None:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
# target ticket number
|
|
|
|
|
#select.select_by_visible_text(ticket_number)
|
|
|
|
|
print("assign ticker number by jQuery:",ticket_number)
|
|
|
|
|
driver.execute_script("$(\"input[type='select']\").val(\""+ ticket_number +"\");")
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
print("jQuery select_by_visible_text ticket_number fail (after click.)")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
return is_ticket_number_assigned
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-27 15:38:13 +00:00
|
|
|
|
def tixcraft_verify(driver, presale_code):
|
2022-11-20 07:57:16 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = False # online
|
2022-11-20 07:57:16 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = False
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string = None
|
2022-12-27 15:38:13 +00:00
|
|
|
|
if len(presale_code) > 0:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string = presale_code
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
form_select = None
|
|
|
|
|
try:
|
|
|
|
|
form_select = driver.find_element(By.CSS_SELECTOR, '.zone-verify')
|
|
|
|
|
except Exception as exc:
|
2023-01-07 22:23:37 +00:00
|
|
|
|
print("find verify textbox fail")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
pass
|
|
|
|
|
|
2022-11-13 04:50:53 +00:00
|
|
|
|
question_text = None
|
|
|
|
|
if form_select is not None:
|
|
|
|
|
try:
|
|
|
|
|
question_text = form_select.text
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("get text fail")
|
|
|
|
|
|
|
|
|
|
html_text = ""
|
|
|
|
|
if question_text is not None:
|
|
|
|
|
if len(question_text) > 0:
|
2023-01-07 22:23:37 +00:00
|
|
|
|
# format question text.
|
2022-11-13 04:50:53 +00:00
|
|
|
|
html_text = question_text
|
|
|
|
|
html_text = html_text.replace(u'「',u'【')
|
|
|
|
|
html_text = html_text.replace(u'〔',u'【')
|
|
|
|
|
html_text = html_text.replace(u'[',u'【')
|
|
|
|
|
html_text = html_text.replace(u'〖',u'【')
|
|
|
|
|
html_text = html_text.replace(u'[',u'【')
|
|
|
|
|
|
|
|
|
|
html_text = html_text.replace(u'」',u'】')
|
|
|
|
|
html_text = html_text.replace(u'〕',u'】')
|
|
|
|
|
html_text = html_text.replace(u']',u'】')
|
|
|
|
|
html_text = html_text.replace(u'〗',u'】')
|
|
|
|
|
html_text = html_text.replace(u']',u'】')
|
|
|
|
|
|
|
|
|
|
if u'【' in html_text and u'】' in html_text:
|
|
|
|
|
# PS: 這個太容易沖突,因為問題類型太多,不能直接使用。
|
2023-01-02 20:37:54 +00:00
|
|
|
|
#inferred_answer_string = find_between(html_text, u"【", u"】")
|
2022-11-13 04:50:53 +00:00
|
|
|
|
pass
|
2019-10-27 03:44:53 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("html_text:", html_text)
|
|
|
|
|
|
2019-10-27 03:44:53 +00:00
|
|
|
|
is_options_in_question = False
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
# 請輸入"YES",代表您已詳閱且瞭解並同意。
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if inferred_answer_string is None:
|
2023-01-07 22:23:37 +00:00
|
|
|
|
if u'輸入"YES"' in html_text:
|
|
|
|
|
if u'已詳閱' in html_text or '請詳閱' in html_text:
|
|
|
|
|
if u'同意' in html_text:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string = 'YES'
|
2019-10-27 04:33:06 +00:00
|
|
|
|
|
2023-01-07 22:23:37 +00:00
|
|
|
|
# 購票前請詳閱注意事項,並於驗證碼欄位輸入【同意】繼續購票流程。
|
|
|
|
|
if inferred_answer_string is None:
|
|
|
|
|
if '驗證碼' in html_text or '驗證欄位' in html_text:
|
|
|
|
|
if '已詳閱' in html_text or '請詳閱' in html_text:
|
|
|
|
|
if '輸入【同意】' in html_text:
|
|
|
|
|
inferred_answer_string = '同意'
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
print("inferred_answer_string:", inferred_answer_string)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
|
|
|
|
|
form_input = None
|
|
|
|
|
try:
|
|
|
|
|
form_input = driver.find_element(By.CSS_SELECTOR, '#checkCode')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find verify code fail")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
default_value = None
|
|
|
|
|
if form_input is not None:
|
|
|
|
|
try:
|
|
|
|
|
default_value = form_input.get_attribute('value')
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
print("find verify code fail")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
pass
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if default_value is None:
|
|
|
|
|
default_value = ""
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if not inferred_answer_string is None:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
is_password_sent = False
|
|
|
|
|
if len(default_value)==0:
|
2022-09-19 16:20:51 +00:00
|
|
|
|
try:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
# PS: sometime may send key twice...
|
|
|
|
|
form_input.clear()
|
2023-01-02 20:37:54 +00:00
|
|
|
|
form_input.send_keys(inferred_answer_string)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
is_password_sent = True
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("sent password by bot.")
|
2022-09-19 16:20:51 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if default_value == inferred_answer_string:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("sent password by previous time.")
|
|
|
|
|
is_password_sent = True
|
|
|
|
|
|
|
|
|
|
if is_password_sent:
|
|
|
|
|
submit_btn = None
|
|
|
|
|
try:
|
|
|
|
|
submit_btn = driver.find_element(By.ID, 'submitButton')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("find submit button fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
2022-09-19 16:20:51 +00:00
|
|
|
|
is_submited = False
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if not submit_btn is None:
|
|
|
|
|
for i in range(3):
|
2022-11-09 18:36:17 +00:00
|
|
|
|
try:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if submit_btn.is_enabled():
|
|
|
|
|
submit_btn.click()
|
|
|
|
|
is_submited = True
|
|
|
|
|
if show_debug_message:
|
2023-01-07 21:43:30 +00:00
|
|
|
|
print("press submit button at time #", i+1)
|
2022-11-09 18:36:17 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if is_submited:
|
|
|
|
|
break
|
2023-01-07 21:43:30 +00:00
|
|
|
|
|
|
|
|
|
if is_submited:
|
|
|
|
|
for i in range(3):
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
alert_ret = check_pop_alert(driver)
|
|
|
|
|
if alert_ret:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("press accept button at time #", i+1)
|
|
|
|
|
break
|
2019-10-27 01:31:22 +00:00
|
|
|
|
else:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if len(default_value)==0:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
form_input.click()
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
2023-01-12 15:30:34 +00:00
|
|
|
|
def tixcraft_change_captcha(driver,url):
|
|
|
|
|
try:
|
|
|
|
|
driver.execute_script(f"document.querySelector('.verify-img').children[0].setAttribute('src','{url}');")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("edit captcha element fail")
|
|
|
|
|
|
2023-01-12 11:41:49 +00:00
|
|
|
|
def tixcraft_toast(driver, message):
|
|
|
|
|
toast_element = None
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = ".remark-word"
|
|
|
|
|
toast_element = driver.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
if not toast_element is None:
|
|
|
|
|
driver.execute_script("arguments[0].innerHTML='%s';" % message, toast_element)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find toast element fail")
|
|
|
|
|
|
2023-01-12 22:29:58 +00:00
|
|
|
|
def tixcraft_keyin_captcha_code(driver, answer = "", auto_submit = False):
|
2023-01-11 13:58:55 +00:00
|
|
|
|
is_verifyCode_editing = False
|
2023-01-12 22:29:58 +00:00
|
|
|
|
is_form_sumbited = False
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
|
|
|
|
# manually keyin verify code.
|
|
|
|
|
# start to input verify code.
|
|
|
|
|
form_verifyCode = None
|
|
|
|
|
try:
|
|
|
|
|
form_verifyCode = driver.find_element(By.ID, 'TicketForm_verifyCode')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find form_verifyCode fail")
|
|
|
|
|
|
|
|
|
|
if form_verifyCode is not None:
|
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
|
|
|
|
if form_verifyCode.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
|
|
|
|
try:
|
|
|
|
|
form_verifyCode.click()
|
|
|
|
|
is_verifyCode_editing = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click form_verifyCode fail, tring to use javascript.")
|
|
|
|
|
# plan B
|
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("document.getElementById(\"TicketForm_verifyCode\").focus();")
|
|
|
|
|
is_verifyCode_editing = True
|
|
|
|
|
except Exception as exc:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
print("click form_verifyCode fail.")
|
|
|
|
|
|
|
|
|
|
#print("start to fill answer.")
|
|
|
|
|
try:
|
|
|
|
|
if len(answer) > 0:
|
|
|
|
|
form_verifyCode.send_keys(answer)
|
|
|
|
|
if auto_submit:
|
|
|
|
|
form_verifyCode.send_keys(Keys.ENTER)
|
|
|
|
|
is_verifyCode_editing = False
|
|
|
|
|
is_form_sumbited = True
|
|
|
|
|
else:
|
|
|
|
|
driver.execute_script("document.getElementById(\"TicketForm_verifyCode\").select();")
|
|
|
|
|
if len(answer) > 0:
|
|
|
|
|
tixcraft_toast(driver, "※ 按 Enter 如果答案是: " + answer)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("send_keys ocr answer fail.")
|
|
|
|
|
|
|
|
|
|
return is_verifyCode_editing, is_form_sumbited
|
|
|
|
|
|
2023-01-13 19:01:47 +00:00
|
|
|
|
def tixcraft_reload_captcha(driver, domain_name):
|
2023-01-12 22:29:58 +00:00
|
|
|
|
# manually keyin verify code.
|
|
|
|
|
# start to input verify code.
|
|
|
|
|
ret = False
|
|
|
|
|
form_captcha = None
|
|
|
|
|
try:
|
2023-01-13 19:01:47 +00:00
|
|
|
|
image_id = 'yw0'
|
|
|
|
|
if 'indievox.com' in domain_name:
|
|
|
|
|
image_id = 'TicketForm_verifyCode-image'
|
|
|
|
|
form_captcha = driver.find_element(By.ID, image_id)
|
2023-01-12 22:29:58 +00:00
|
|
|
|
if not form_captcha is None:
|
|
|
|
|
form_captcha.click()
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find form_captcha fail")
|
|
|
|
|
|
|
|
|
|
return ret
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
|
|
|
|
#PS: credit to LinShihJhang's share
|
2023-01-13 19:01:47 +00:00
|
|
|
|
def tixcraft_auto_ocr(driver, ocr, away_from_keyboard_enable, previous_answer, Captcha_Browser, ocr_captcha_image_source, domain_name):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
2023-01-11 13:58:55 +00:00
|
|
|
|
print("start to ddddocr")
|
2023-01-13 19:01:47 +00:00
|
|
|
|
|
|
|
|
|
CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_BROWSER = "NonBrowser"
|
|
|
|
|
CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_CANVAS = "canvas"
|
2023-01-12 23:23:19 +00:00
|
|
|
|
|
2023-01-12 22:29:58 +00:00
|
|
|
|
is_need_redo_ocr = False
|
|
|
|
|
is_form_sumbited = False
|
|
|
|
|
|
2023-01-11 14:26:49 +00:00
|
|
|
|
orc_answer = None
|
|
|
|
|
if not ocr is None:
|
2023-01-13 19:01:47 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("away_from_keyboard_enable:", away_from_keyboard_enable)
|
|
|
|
|
print("previous_answer:", previous_answer)
|
|
|
|
|
print("ocr_captcha_image_source:", ocr_captcha_image_source)
|
|
|
|
|
|
|
|
|
|
ocr_start_time = time.time()
|
|
|
|
|
|
|
|
|
|
img_base64 = None
|
|
|
|
|
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_BROWSER:
|
2023-01-14 05:26:42 +00:00
|
|
|
|
if not Captcha_Browser is None:
|
|
|
|
|
img_base64 = base64.b64decode(Captcha_Browser.Request_Captcha())
|
2023-01-13 19:01:47 +00:00
|
|
|
|
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_CANVAS:
|
|
|
|
|
image_id = 'yw0'
|
|
|
|
|
if 'indievox.com' in domain_name:
|
|
|
|
|
image_id = 'TicketForm_verifyCode-image'
|
|
|
|
|
try:
|
|
|
|
|
form_verifyCode_base64 = driver.execute_async_script("""
|
|
|
|
|
var canvas = document.createElement('canvas');
|
|
|
|
|
var context = canvas.getContext('2d');
|
|
|
|
|
var img = document.getElementById('%s');
|
|
|
|
|
canvas.height = img.naturalHeight;
|
|
|
|
|
canvas.width = img.naturalWidth;
|
|
|
|
|
context.drawImage(img, 0, 0);
|
|
|
|
|
callback = arguments[arguments.length - 1];
|
|
|
|
|
callback(canvas.toDataURL());
|
|
|
|
|
""" % (image_id))
|
|
|
|
|
img_base64 = base64.b64decode(form_verifyCode_base64.split(',')[1])
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("canvas exception:", str(exc))
|
|
|
|
|
pass
|
|
|
|
|
if not img_base64 is None:
|
|
|
|
|
try:
|
|
|
|
|
orc_answer = ocr.classification(img_base64)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
ocr_done_time = time.time()
|
|
|
|
|
ocr_elapsed_time = ocr_done_time - ocr_start_time
|
|
|
|
|
print("ocr elapsed time:", "{:.3f}".format(ocr_elapsed_time))
|
2023-01-11 17:36:29 +00:00
|
|
|
|
else:
|
|
|
|
|
print("ddddocr is None")
|
2023-01-12 23:23:19 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
if not orc_answer is None:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
orc_answer = orc_answer.strip()
|
2023-01-11 13:58:55 +00:00
|
|
|
|
print("orc_answer:", orc_answer)
|
|
|
|
|
if len(orc_answer)==4:
|
2023-01-13 09:27:08 +00:00
|
|
|
|
who_care_var, is_form_sumbited = tixcraft_keyin_captcha_code(driver, answer = orc_answer, auto_submit = away_from_keyboard_enable)
|
2023-01-11 13:58:55 +00:00
|
|
|
|
else:
|
2023-01-13 00:43:16 +00:00
|
|
|
|
if not away_from_keyboard_enable:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
tixcraft_keyin_captcha_code(driver)
|
2023-01-13 09:27:08 +00:00
|
|
|
|
tixcraft_toast(driver, "※ OCR辨識失敗Q_Q,驗證碼請手動輸入...")
|
2023-01-12 22:29:58 +00:00
|
|
|
|
else:
|
|
|
|
|
is_need_redo_ocr = True
|
|
|
|
|
if previous_answer != orc_answer:
|
|
|
|
|
previous_answer = orc_answer
|
|
|
|
|
print("click captcha again")
|
2023-01-13 19:01:47 +00:00
|
|
|
|
if True:
|
|
|
|
|
# selenium solution.
|
|
|
|
|
tixcraft_reload_captcha(driver, domain_name)
|
|
|
|
|
|
|
|
|
|
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_CANVAS:
|
|
|
|
|
time.sleep(0.3)
|
|
|
|
|
else:
|
|
|
|
|
# Non_Browser solution.
|
2023-01-14 05:26:42 +00:00
|
|
|
|
if not Captcha_Browser is None:
|
|
|
|
|
new_captcha_url = Captcha_Browser.Request_Refresh_Captcha() #取得新的CAPTCHA
|
|
|
|
|
if new_captcha_url != "":
|
|
|
|
|
tixcraft_change_captcha(driver, new_captcha_url) #更改CAPTCHA圖
|
2023-01-11 17:36:29 +00:00
|
|
|
|
else:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
print("orc_answer is None")
|
|
|
|
|
print("previous_answer:", previous_answer)
|
|
|
|
|
if previous_answer is None:
|
|
|
|
|
tixcraft_keyin_captcha_code(driver)
|
|
|
|
|
else:
|
|
|
|
|
# page is not ready, retry again.
|
2023-01-13 00:43:16 +00:00
|
|
|
|
# PS: usually occur in async script get captcha image.
|
2023-01-12 22:29:58 +00:00
|
|
|
|
is_need_redo_ocr = True
|
|
|
|
|
|
|
|
|
|
return is_need_redo_ocr, previous_answer, is_form_sumbited
|
2023-01-11 14:26:49 +00:00
|
|
|
|
|
2023-01-13 19:01:47 +00:00
|
|
|
|
def tixcraft_ticket_main(driver, config_dict, ocr, Captcha_Browser, domain_name):
|
2022-12-15 11:26:51 +00:00
|
|
|
|
auto_check_agree = config_dict["auto_check_agree"]
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
2023-01-12 11:41:49 +00:00
|
|
|
|
ocr_captcha_enable = config_dict["ocr_captcha"]["enable"]
|
2023-01-13 00:43:16 +00:00
|
|
|
|
away_from_keyboard_enable = config_dict["ocr_captcha"]["force_submit"]
|
|
|
|
|
if not ocr_captcha_enable:
|
|
|
|
|
away_from_keyboard_enable = False
|
2023-01-13 19:01:47 +00:00
|
|
|
|
ocr_captcha_image_source = config_dict["ocr_captcha"]["image_source"]
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
2022-12-15 11:26:51 +00:00
|
|
|
|
if auto_check_agree:
|
|
|
|
|
tixcraft_ticket_agree(driver)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
|
|
|
|
# allow agree not enable to assign ticket number.
|
2019-10-01 17:52:13 +00:00
|
|
|
|
form_select = None
|
|
|
|
|
try:
|
|
|
|
|
#form_select = driver.find_element(By.TAG_NAME, 'select')
|
2022-11-16 15:43:53 +00:00
|
|
|
|
#PS: select box may appear many in the page with different price.
|
2019-10-01 17:52:13 +00:00
|
|
|
|
form_select = driver.find_element(By.CSS_SELECTOR, '.mobile-select')
|
2022-11-13 04:50:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find select fail")
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
select_obj = None
|
2022-11-13 04:50:53 +00:00
|
|
|
|
if form_select is not None:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
is_visible = False
|
2022-11-13 04:50:53 +00:00
|
|
|
|
try:
|
2022-12-15 11:26:51 +00:00
|
|
|
|
if form_select.is_enabled():
|
|
|
|
|
is_visible = True
|
2022-11-13 04:50:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if is_visible:
|
2022-11-13 04:50:53 +00:00
|
|
|
|
try:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
select_obj = Select(form_select)
|
2022-11-13 04:50:53 +00:00
|
|
|
|
except Exception as exc:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
pass
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = False
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if not select_obj is None:
|
|
|
|
|
row_text = None
|
|
|
|
|
try:
|
|
|
|
|
row_text = select_obj.first_selected_option.text
|
|
|
|
|
except Exception as exc:
|
2022-11-13 04:50:53 +00:00
|
|
|
|
pass
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if not row_text is None:
|
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
if row_text != "0":
|
|
|
|
|
# ticket assign.
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
is_verifyCode_editing = False
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
# must wait select object ready to assign ticket number.
|
|
|
|
|
if not is_ticket_number_assigned:
|
|
|
|
|
# only this case:"ticket number changed by bot" to play sound!
|
|
|
|
|
# PS: I assume each time assign ticket number will succufully changed, so let sound play first.
|
|
|
|
|
check_and_play_sound_for_captcha(config_dict)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
ticket_number = str(config_dict["ticket_number"])
|
|
|
|
|
is_ticket_number_assigned = tixcraft_ticket_number_auto_fill(driver, select_obj, ticket_number)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
# must wait ticket number assign to focus captcha.
|
|
|
|
|
if is_ticket_number_assigned:
|
2023-01-12 08:51:05 +00:00
|
|
|
|
if not ocr_captcha_enable:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
is_verifyCode_editing = tixcraft_keyin_captcha_code(driver)
|
2023-01-11 13:58:55 +00:00
|
|
|
|
else:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
previous_answer = None
|
2023-01-11 13:58:55 +00:00
|
|
|
|
is_verifyCode_editing = True
|
2023-01-12 22:29:58 +00:00
|
|
|
|
for redo_ocr in range(999):
|
2023-01-13 19:01:47 +00:00
|
|
|
|
is_need_redo_ocr, previous_answer, is_form_sumbited = tixcraft_auto_ocr(driver, ocr, away_from_keyboard_enable, previous_answer, Captcha_Browser, ocr_captcha_image_source, domain_name)
|
2023-01-12 22:29:58 +00:00
|
|
|
|
if is_form_sumbited:
|
|
|
|
|
# start next loop.
|
|
|
|
|
is_verifyCode_editing = False
|
|
|
|
|
break
|
2023-01-13 00:43:16 +00:00
|
|
|
|
|
|
|
|
|
if not away_from_keyboard_enable:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
break
|
2023-01-13 00:43:16 +00:00
|
|
|
|
|
2023-01-12 22:29:58 +00:00
|
|
|
|
if not is_need_redo_ocr:
|
|
|
|
|
break
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
|
|
|
|
if is_verifyCode_editing:
|
|
|
|
|
print("goto is_verifyCode_editing == True")
|
|
|
|
|
|
2022-11-16 17:52:38 +00:00
|
|
|
|
return is_verifyCode_editing
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2020-10-20 16:31:30 +00:00
|
|
|
|
# PS: There are two "Next" button in kktix.
|
|
|
|
|
# : 1: /events/xxx
|
|
|
|
|
# : 2: /events/xxx/registrations/new
|
2022-11-07 10:15:35 +00:00
|
|
|
|
# : This is ONLY for case-1, because case-2 lenght >5
|
2022-01-12 17:14:27 +00:00
|
|
|
|
def kktix_events_press_next_button(driver):
|
2020-10-20 16:31:30 +00:00
|
|
|
|
ret = False
|
|
|
|
|
|
|
|
|
|
# let javascript to enable button.
|
2022-11-16 15:43:53 +00:00
|
|
|
|
time.sleep(0.1)
|
2020-10-20 16:31:30 +00:00
|
|
|
|
|
2022-09-19 16:20:51 +00:00
|
|
|
|
wait = WebDriverWait(driver, 1)
|
|
|
|
|
next_step_button = None
|
2020-10-20 16:31:30 +00:00
|
|
|
|
try:
|
|
|
|
|
# method #3 wait
|
|
|
|
|
next_step_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div.tickets a.btn-point')))
|
|
|
|
|
if not next_step_button is None:
|
|
|
|
|
if next_step_button.is_enabled():
|
|
|
|
|
next_step_button.click()
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("wait form-actions div wait to be clickable Exception:")
|
2022-01-12 17:14:27 +00:00
|
|
|
|
#print(exc)
|
2020-10-20 16:31:30 +00:00
|
|
|
|
pass
|
|
|
|
|
|
2022-09-19 16:20:51 +00:00
|
|
|
|
if not next_step_button is None:
|
2022-11-09 18:36:17 +00:00
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
|
|
|
|
if next_step_button.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
2022-09-19 16:20:51 +00:00
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("arguments[0].click();", next_step_button)
|
2020-10-20 16:31:30 +00:00
|
|
|
|
ret = True
|
2022-09-19 16:20:51 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2020-10-20 16:31:30 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
# : This is for case-2 next button.
|
2022-01-12 17:14:27 +00:00
|
|
|
|
def kktix_press_next_button(driver):
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = False
|
|
|
|
|
|
2022-09-19 16:20:51 +00:00
|
|
|
|
wait = WebDriverWait(driver, 1)
|
|
|
|
|
next_step_button = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
|
|
|
|
# method #1
|
|
|
|
|
#form_actions_div = None
|
|
|
|
|
#form_actions_div = driver.find_element(By.ID, 'registrationsNewApp')
|
|
|
|
|
#next_step_button = form_actions_div.find_element(By.CSS_SELECTOR, 'div.form-actions button.btn-primary')
|
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
# method #2
|
|
|
|
|
# next_step_button = driver.find_element(By.CSS_SELECTOR, '#registrationsNewApp div.form-actions button.btn-primary')
|
|
|
|
|
|
|
|
|
|
# method #3 wait
|
2019-10-01 17:52:13 +00:00
|
|
|
|
next_step_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#registrationsNewApp div.form-actions button.btn-primary')))
|
|
|
|
|
if not next_step_button is None:
|
|
|
|
|
if next_step_button.is_enabled():
|
|
|
|
|
next_step_button.click()
|
|
|
|
|
ret = True
|
|
|
|
|
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("wait form-actions div wait to be clickable Exception:")
|
|
|
|
|
print(exc)
|
2022-09-19 16:20:51 +00:00
|
|
|
|
#pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-09-19 16:20:51 +00:00
|
|
|
|
if not next_step_button is None:
|
2022-11-09 18:36:17 +00:00
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
|
|
|
|
if next_step_button.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-09 18:36:17 +00:00
|
|
|
|
if is_visible:
|
2022-09-19 16:20:51 +00:00
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("arguments[0].click();", next_step_button)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = True
|
2022-09-19 16:20:51 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
def kktix_captcha_text_value(captcha_inner_div):
|
|
|
|
|
ret = ""
|
|
|
|
|
|
|
|
|
|
if captcha_inner_div is not None:
|
|
|
|
|
try:
|
|
|
|
|
captcha_password_text = captcha_inner_div.find_element(By.TAG_NAME, "input")
|
|
|
|
|
if not captcha_password_text is None:
|
|
|
|
|
ret = captcha_password_text.get_attribute('value')
|
|
|
|
|
else:
|
|
|
|
|
print("find captcha input field fail")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find captcha_inner_div Exception:")
|
|
|
|
|
#print(exc)
|
|
|
|
|
pass
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
def kktix_input_captcha_text(captcha_password_input_tag, inferred_answer_string, force_overwrite = False):
|
2022-10-18 18:15:05 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
#show_debug_message = False # online
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
is_cpatcha_sent = False
|
|
|
|
|
inputed_captcha_text = ""
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if not captcha_password_input_tag is None:
|
|
|
|
|
if force_overwrite:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
try:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
captcha_password_input_tag.send_keys(inferred_answer_string)
|
|
|
|
|
print("send captcha keys:" + inferred_answer_string)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
is_cpatcha_sent = True
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inputed_captcha_text = inferred_answer_string
|
2022-11-18 22:59:34 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
# not force overwrite:
|
|
|
|
|
inputed_captcha_text = None
|
|
|
|
|
try:
|
|
|
|
|
inputed_captcha_text = captcha_password_input_tag.get_attribute('value')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
if inputed_captcha_text is None:
|
|
|
|
|
inputed_captcha_text = ""
|
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if len(inputed_captcha_text) == 0:
|
|
|
|
|
try:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
captcha_password_input_tag.send_keys(inferred_answer_string)
|
|
|
|
|
print("send captcha keys:" + inferred_answer_string)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
is_cpatcha_sent = True
|
2022-11-18 22:59:34 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
return is_cpatcha_sent
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-24 21:40:40 +00:00
|
|
|
|
def kktix_travel_price_list(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_keyword_1, kktix_area_keyword_1_and):
|
2022-11-10 17:19:03 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2023-01-03 18:54:42 +00:00
|
|
|
|
show_debug_message = False # online
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
areas = None
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = False
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-10-21 13:18:07 +00:00
|
|
|
|
ticket_price_list = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
|
|
|
|
ticket_price_list = driver.find_elements(By.CSS_SELECTOR, '.display-table-row')
|
2022-10-21 13:18:07 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
ticket_price_list = None
|
2022-10-21 13:18:07 +00:00
|
|
|
|
print("find ticket-price span Exception:")
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
price_list_count = 0
|
2022-10-21 13:18:07 +00:00
|
|
|
|
if ticket_price_list is not None:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
price_list_count = len(ticket_price_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("found price count:", price_list_count)
|
|
|
|
|
print("start to travel rows..........")
|
|
|
|
|
else:
|
|
|
|
|
print("find ticket-price span fail")
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
is_travel_interrupted = False
|
|
|
|
|
|
|
|
|
|
if price_list_count > 0:
|
|
|
|
|
areas = []
|
|
|
|
|
|
|
|
|
|
# clean stop word.
|
2022-11-23 04:39:46 +00:00
|
|
|
|
kktix_area_keyword_1 = format_keyword_string(kktix_area_keyword_1)
|
|
|
|
|
kktix_area_keyword_1_and = format_keyword_string(kktix_area_keyword_1_and)
|
2022-11-10 17:19:03 +00:00
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
2022-11-23 04:39:46 +00:00
|
|
|
|
print('kktix_area_keyword_1:', kktix_area_keyword_1)
|
|
|
|
|
print('kktix_area_keyword_1_and:', kktix_area_keyword_1_and)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
row_index = 0
|
|
|
|
|
for row in ticket_price_list:
|
|
|
|
|
row_index += 1
|
2022-10-21 13:18:07 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
row_text = ""
|
|
|
|
|
try:
|
|
|
|
|
row_text = row.text
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("get text:", row_text, ",at row:", row_index)
|
|
|
|
|
except Exception as exc:
|
2022-10-21 13:18:07 +00:00
|
|
|
|
row_text = ""
|
2022-11-10 17:19:03 +00:00
|
|
|
|
is_travel_interrupted = True
|
|
|
|
|
print("get text fail.")
|
|
|
|
|
|
2022-11-13 04:50:53 +00:00
|
|
|
|
if row_text is None:
|
|
|
|
|
row_text = ""
|
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
# clean stop word.
|
|
|
|
|
row_text = format_keyword_string(row_text)
|
|
|
|
|
|
|
|
|
|
# check ticket input textbox.
|
|
|
|
|
ticket_price_input = None
|
2022-10-21 13:18:07 +00:00
|
|
|
|
try:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
ticket_price_input = row.find_element(By.CSS_SELECTOR, "input[type='text']")
|
2022-10-21 13:18:07 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
pass
|
2022-10-21 13:18:07 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if ticket_price_input is not None:
|
|
|
|
|
current_ticket_number = ""
|
|
|
|
|
is_visible = False
|
2022-10-22 01:19:57 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
current_ticket_number = str(ticket_price_input.get_attribute('value')).strip()
|
|
|
|
|
is_visible = ticket_price_input.is_enabled()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if len(current_ticket_number) > 0:
|
|
|
|
|
if current_ticket_number != "0":
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2022-10-22 01:19:57 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if is_ticket_number_assigned:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
# no need to travel
|
|
|
|
|
break
|
|
|
|
|
|
2022-11-24 21:40:40 +00:00
|
|
|
|
is_danger_notice = False
|
|
|
|
|
if ticket_number > 1:
|
|
|
|
|
# start to check danger notice.
|
|
|
|
|
span_danger_popup = None
|
|
|
|
|
try:
|
|
|
|
|
span_danger_popup = row.find_element(By.CSS_SELECTOR, "span.danger")
|
|
|
|
|
if span_danger_popup.is_displayed():
|
|
|
|
|
is_danger_notice = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
2022-11-24 21:40:40 +00:00
|
|
|
|
if is_danger_notice:
|
|
|
|
|
# skip this row, because assign will fail, or fill ticket number as 1.
|
|
|
|
|
if pass_1_seat_remaining_enable:
|
|
|
|
|
continue
|
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if is_visible:
|
|
|
|
|
is_match_area = False
|
|
|
|
|
match_area_code = 0
|
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
if len(kktix_area_keyword_1) == 0:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
# keyword #1, empty, direct add to list.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 1
|
|
|
|
|
else:
|
|
|
|
|
# MUST match keyword #1.
|
2022-11-23 04:39:46 +00:00
|
|
|
|
if kktix_area_keyword_1 in row_text:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
#print('match keyword#1')
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
# because of logic between keywords is AND!
|
2022-11-23 04:39:46 +00:00
|
|
|
|
if len(kktix_area_keyword_1_and) == 0:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
#print('keyword#2 is empty, directly match.')
|
|
|
|
|
# keyword #2 is empty, direct append.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 2
|
|
|
|
|
else:
|
2022-11-23 04:39:46 +00:00
|
|
|
|
if kktix_area_keyword_1_and in row_text:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
#print('match keyword#2')
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 3
|
2022-11-06 09:10:35 +00:00
|
|
|
|
else:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
#print('not match keyword#2')
|
|
|
|
|
pass
|
2022-10-21 13:18:07 +00:00
|
|
|
|
else:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
#print('not match keyword#1')
|
|
|
|
|
pass
|
2019-12-14 19:13:20 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("is_match_area:", is_match_area)
|
|
|
|
|
print("match_area_code:", match_area_code)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if is_match_area:
|
|
|
|
|
areas.append(row)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if is_travel_interrupted:
|
|
|
|
|
# not sure to break or continue..., maybe break better.
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
else:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("no any price list found.")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# unknow issue...
|
|
|
|
|
if is_travel_interrupted:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
return is_ticket_number_assigned, areas
|
2022-11-10 17:19:03 +00:00
|
|
|
|
|
2022-11-24 21:40:40 +00:00
|
|
|
|
def kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and):
|
2022-11-10 17:19:03 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = False # online
|
2022-11-10 17:19:03 +00:00
|
|
|
|
|
2022-11-24 21:40:40 +00:00
|
|
|
|
ticket_number_str = str(ticket_number)
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned, areas = kktix_travel_price_list(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_keyword_1, kktix_area_keyword_1_and)
|
2022-11-10 17:19:03 +00:00
|
|
|
|
|
|
|
|
|
target_area = None
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if not is_ticket_number_assigned:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
if areas is not None:
|
|
|
|
|
if len(areas) > 0:
|
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
|
|
|
|
if kktix_area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if kktix_area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(areas)-1
|
|
|
|
|
|
|
|
|
|
if kktix_area_auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(areas)-1)
|
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("target_row_index", target_row_index)
|
|
|
|
|
target_area = areas[target_row_index]
|
|
|
|
|
|
|
|
|
|
ticket_price_input = None
|
|
|
|
|
if target_area is not None:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('try to get input box element.')
|
|
|
|
|
try:
|
2022-11-13 04:50:53 +00:00
|
|
|
|
#print("target_area text", target_area.text)
|
2022-11-10 17:19:03 +00:00
|
|
|
|
ticket_price_input = target_area.find_element(By.CSS_SELECTOR, "input[type='text']")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-09 18:36:17 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
current_ticket_number = ""
|
|
|
|
|
is_visible = False
|
|
|
|
|
if ticket_price_input is not None:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("try to get input box value.")
|
|
|
|
|
try:
|
|
|
|
|
current_ticket_number = str(ticket_price_input.get_attribute('value')).strip()
|
|
|
|
|
is_visible = ticket_price_input.is_enabled()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-09 18:36:17 +00:00
|
|
|
|
|
2022-11-10 17:19:03 +00:00
|
|
|
|
if is_visible and len(current_ticket_number) > 0:
|
|
|
|
|
if current_ticket_number == "0":
|
|
|
|
|
try:
|
2022-11-24 21:40:40 +00:00
|
|
|
|
print("asssign ticket number:%s" % ticket_number_str)
|
2022-11-10 17:19:03 +00:00
|
|
|
|
ticket_price_input.clear()
|
2022-11-24 21:40:40 +00:00
|
|
|
|
ticket_price_input.send_keys(ticket_number_str)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-10 17:19:03 +00:00
|
|
|
|
print("asssign ticket number to ticket-price field Exception:")
|
|
|
|
|
print(exc)
|
|
|
|
|
try:
|
|
|
|
|
ticket_price_input.clear()
|
|
|
|
|
ticket_price_input.send_keys("1")
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2022-11-10 17:19:03 +00:00
|
|
|
|
except Exception as exc2:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("value already assigned.")
|
|
|
|
|
# already assigned.
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
return is_ticket_number_assigned
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
def kktix_get_web_datetime(registrationsNewApp_div):
|
2022-10-18 18:15:05 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2022-11-13 18:34:22 +00:00
|
|
|
|
show_debug_message = False # online
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-12-06 18:36:43 +00:00
|
|
|
|
web_datetime = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2019-12-06 18:36:43 +00:00
|
|
|
|
is_found_web_datetime = False
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
|
|
|
|
el_web_datetime_list = None
|
|
|
|
|
if not registrationsNewApp_div is None:
|
|
|
|
|
try:
|
2019-12-06 18:36:43 +00:00
|
|
|
|
el_web_datetime_list = registrationsNewApp_div.find_elements(By.TAG_NAME, 'td')
|
2022-10-18 18:15:05 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("find td.ng-binding Exception")
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
|
|
|
|
#print("is_found_web_datetime", is_found_web_datetime)
|
|
|
|
|
|
|
|
|
|
if el_web_datetime_list is not None:
|
|
|
|
|
el_web_datetime_list_count = len(el_web_datetime_list)
|
|
|
|
|
if el_web_datetime_list_count > 0:
|
|
|
|
|
el_web_datetime = None
|
|
|
|
|
for el_web_datetime in el_web_datetime_list:
|
2022-11-13 04:50:53 +00:00
|
|
|
|
el_web_datetime_text = None
|
2022-10-18 18:15:05 +00:00
|
|
|
|
try:
|
|
|
|
|
el_web_datetime_text = el_web_datetime.text
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("el_web_datetime_text:", el_web_datetime_text)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('parse web datetime fail:')
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
2022-11-13 04:50:53 +00:00
|
|
|
|
|
|
|
|
|
if el_web_datetime_text is not None:
|
|
|
|
|
if len(el_web_datetime_text) > 0:
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
#print("now:", now)
|
|
|
|
|
for guess_year in range(now.year,now.year+3):
|
|
|
|
|
current_year = str(guess_year)
|
|
|
|
|
if current_year in el_web_datetime_text:
|
|
|
|
|
if u'/' in el_web_datetime_text:
|
|
|
|
|
web_datetime = el_web_datetime_text
|
|
|
|
|
is_found_web_datetime = True
|
|
|
|
|
break
|
|
|
|
|
if is_found_web_datetime:
|
|
|
|
|
break
|
2022-10-18 18:15:05 +00:00
|
|
|
|
else:
|
|
|
|
|
print("find td.ng-binding fail")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('is_found_web_datetime:', is_found_web_datetime)
|
|
|
|
|
print('web_datetime:', web_datetime)
|
|
|
|
|
|
2019-12-06 18:36:43 +00:00
|
|
|
|
return web_datetime
|
|
|
|
|
|
2022-01-12 17:14:27 +00:00
|
|
|
|
def kktix_check_agree_checkbox(driver):
|
2019-10-01 17:52:13 +00:00
|
|
|
|
is_need_refresh = False
|
2019-12-06 18:36:43 +00:00
|
|
|
|
is_finish_checkbox_click = False
|
2019-12-04 16:26:40 +00:00
|
|
|
|
|
|
|
|
|
person_agree_terms_checkbox = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2019-12-04 16:26:40 +00:00
|
|
|
|
person_agree_terms_checkbox = driver.find_element(By.ID, 'person_agree_terms')
|
2022-11-18 22:59:34 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find person_agree_terms checkbox Exception")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if person_agree_terms_checkbox is not None:
|
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
2019-12-04 16:26:40 +00:00
|
|
|
|
if person_agree_terms_checkbox.is_enabled():
|
2022-11-18 22:59:34 +00:00
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
|
|
|
|
is_checkbox_checked = False
|
|
|
|
|
try:
|
|
|
|
|
if person_agree_terms_checkbox.is_selected():
|
|
|
|
|
is_checkbox_checked = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if not is_checkbox_checked:
|
|
|
|
|
#print('send check to checkbox')
|
|
|
|
|
try:
|
2019-12-04 16:26:40 +00:00
|
|
|
|
person_agree_terms_checkbox.click()
|
2019-12-06 18:36:43 +00:00
|
|
|
|
is_finish_checkbox_click = True
|
2022-11-18 22:59:34 +00:00
|
|
|
|
except Exception as exc:
|
2019-12-04 16:26:40 +00:00
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
else:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
#print('checked')
|
|
|
|
|
is_finish_checkbox_click = True
|
2019-12-04 16:26:40 +00:00
|
|
|
|
else:
|
|
|
|
|
is_need_refresh = True
|
2022-11-18 22:59:34 +00:00
|
|
|
|
else:
|
|
|
|
|
is_need_refresh = True
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if is_need_refresh:
|
|
|
|
|
print("find person_agree_terms checkbox fail, do refresh page.")
|
2019-12-06 18:36:43 +00:00
|
|
|
|
|
|
|
|
|
return is_need_refresh, is_finish_checkbox_click
|
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
def kktix_check_register_status(url):
|
2020-10-20 16:31:30 +00:00
|
|
|
|
#ex: https://xxx.kktix.cc/events/xxx
|
|
|
|
|
prefix_list = ['.com/events/','.cc/events/']
|
2019-12-14 19:13:20 +00:00
|
|
|
|
postfix = '/registrations/new'
|
2020-10-20 16:31:30 +00:00
|
|
|
|
|
|
|
|
|
is_match_event_code = False
|
|
|
|
|
event_code = ""
|
|
|
|
|
for prefix in prefix_list:
|
|
|
|
|
event_code = find_between(url,prefix,postfix)
|
|
|
|
|
if len(event_code) > 0:
|
|
|
|
|
is_match_event_code = True
|
|
|
|
|
#print('event_code:',event_code)
|
2020-10-24 03:22:14 +00:00
|
|
|
|
break
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
html_result = None
|
2020-10-20 16:31:30 +00:00
|
|
|
|
if is_match_event_code:
|
2020-10-24 03:22:14 +00:00
|
|
|
|
url = "https://kktix.com/g/events/%s/register_info" % (event_code)
|
|
|
|
|
#print('event_code:',event_code)
|
|
|
|
|
#print("url:", url)
|
2019-12-06 18:36:43 +00:00
|
|
|
|
|
2022-11-06 12:37:24 +00:00
|
|
|
|
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
|
2019-12-14 19:13:20 +00:00
|
|
|
|
headers = {"Accept-Language": "zh-TW,zh;q=0.5", 'User-Agent': user_agent}
|
2019-12-06 18:36:43 +00:00
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
try:
|
2022-11-06 12:37:24 +00:00
|
|
|
|
html_result = requests.get(url , headers=headers, timeout=0.7, allow_redirects=False)
|
2019-12-14 19:13:20 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-06 12:37:24 +00:00
|
|
|
|
html_result = None
|
2019-12-14 19:13:20 +00:00
|
|
|
|
print("send reg_info request fail:")
|
|
|
|
|
print(exc)
|
2019-12-06 18:36:43 +00:00
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
registerStatus = None
|
|
|
|
|
if not html_result is None:
|
|
|
|
|
status_code = html_result.status_code
|
2020-10-24 03:22:14 +00:00
|
|
|
|
#print("status_code:",status_code)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
if status_code == 200:
|
|
|
|
|
html_text = html_result.text
|
|
|
|
|
#print("html_text:", html_text)
|
2019-12-04 16:26:40 +00:00
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
try:
|
|
|
|
|
jsLoads = json.loads(html_text)
|
|
|
|
|
if 'inventory' in jsLoads:
|
|
|
|
|
if 'registerStatus' in jsLoads['inventory']:
|
|
|
|
|
registerStatus = jsLoads['inventory']['registerStatus']
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("load reg_info json fail:")
|
|
|
|
|
print(exc)
|
2019-12-04 16:26:40 +00:00
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2020-10-24 03:22:14 +00:00
|
|
|
|
#print("registerStatus:", registerStatus)
|
2019-12-14 19:13:20 +00:00
|
|
|
|
return registerStatus
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
def get_answer_string_from_web_date(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, registrationsNewApp_div, captcha_text_div_text):
|
2022-10-18 18:15:05 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2022-11-06 09:10:35 +00:00
|
|
|
|
show_debug_message = False # online
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_need_parse_web_datetime = False
|
|
|
|
|
# '半形阿拉伯數字' & '半形數字'
|
|
|
|
|
if u'半形' in captcha_text_div_text and u'字' in captcha_text_div_text:
|
|
|
|
|
if u'演出日期' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
|
|
|
|
if u'活動日期' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
|
|
|
|
if u'表演日期' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
|
|
|
|
if u'開始日期' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
|
|
|
|
if u'演唱會日期' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
|
|
|
|
if u'展覽日期' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
|
|
|
|
if u'音樂會日期' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
|
|
|
|
if u'the date of the show you purchased' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_datetime = True
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("is_need_parse_web_datetime:", is_need_parse_web_datetime)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if is_need_parse_web_datetime:
|
|
|
|
|
web_datetime = kktix_get_web_datetime(registrationsNewApp_div)
|
|
|
|
|
if not web_datetime is None:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("web_datetime:", web_datetime)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
captcha_text_formatted = format_question_string(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("captcha_text_formatted", captcha_text_formatted)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
my_datetime_foramted = None
|
2022-11-13 18:34:22 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
# MMDD
|
|
|
|
|
if my_datetime_foramted is None:
|
|
|
|
|
if u'4位半形' in captcha_text_formatted:
|
|
|
|
|
my_datetime_foramted = "%m%d"
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
# for "如為2月30日,請輸入0230"
|
|
|
|
|
if my_datetime_foramted is None:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
right_part = ""
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if CONST_EXAMPLE_SYMBOL in captcha_text_formatted:
|
|
|
|
|
right_part = captcha_text_formatted.split(CONST_EXAMPLE_SYMBOL)[1]
|
2023-01-14 08:05:00 +00:00
|
|
|
|
|
|
|
|
|
if CONST_INPUT_SYMBOL in right_part:
|
|
|
|
|
right_part = right_part.split(CONST_INPUT_SYMBOL)[1]
|
2023-01-02 20:37:54 +00:00
|
|
|
|
number_text = find_continuous_number(right_part)
|
|
|
|
|
|
|
|
|
|
my_anwser_formated = convert_string_to_pattern(number_text, dynamic_length=False)
|
|
|
|
|
if my_anwser_formated == u"[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]":
|
|
|
|
|
my_datetime_foramted = "%Y%m%d"
|
|
|
|
|
if my_anwser_formated == u"[\\d][\\d][\\d][\\d]":
|
|
|
|
|
my_datetime_foramted = "%m%d"
|
|
|
|
|
#print("my_datetime_foramted:", my_datetime_foramted)
|
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("my_datetime_foramted", my_datetime_foramted)
|
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if my_datetime_foramted is None:
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
for guess_year in range(now.year-4,now.year+2):
|
|
|
|
|
current_year = str(guess_year)
|
|
|
|
|
if current_year in captcha_text_formatted:
|
|
|
|
|
my_hint_index = captcha_text_formatted.find(current_year)
|
|
|
|
|
my_hint_anwser = captcha_text_formatted[my_hint_index:]
|
|
|
|
|
#print("my_hint_anwser:", my_hint_anwser)
|
|
|
|
|
# get after.
|
|
|
|
|
my_delimitor_symbol = CONST_EXAMPLE_SYMBOL
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[my_delimitor_index+len(my_delimitor_symbol):]
|
|
|
|
|
#print("my_hint_anwser:", my_hint_anwser)
|
|
|
|
|
# get before.
|
|
|
|
|
my_delimitor_symbol = u','
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[:my_delimitor_index]
|
|
|
|
|
my_delimitor_symbol = u'。'
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[:my_delimitor_index]
|
|
|
|
|
# PS: space may not is delimitor...
|
|
|
|
|
my_delimitor_symbol = u' '
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[:my_delimitor_index]
|
|
|
|
|
#remove last char.
|
|
|
|
|
remove_last_char_list = [')','(','.','。',')','(','[',']']
|
|
|
|
|
for check_char in remove_last_char_list:
|
|
|
|
|
if my_hint_anwser[-1:]==check_char:
|
|
|
|
|
my_hint_anwser = my_hint_anwser[:-1]
|
|
|
|
|
|
|
|
|
|
my_anwser_formated = convert_string_to_pattern(my_hint_anwser, dynamic_length=False)
|
|
|
|
|
if my_anwser_formated == u"[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]":
|
|
|
|
|
my_datetime_foramted = "%Y%m%d"
|
|
|
|
|
if my_anwser_formated == u"[\\d][\\d][\\d][\\d]/[\\d][\\d]/[\\d][\\d]":
|
|
|
|
|
my_datetime_foramted = "%Y/%m/%d"
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("my_hint_anwser:", my_hint_anwser)
|
|
|
|
|
print("my_anwser_formated:", my_anwser_formated)
|
|
|
|
|
print("my_datetime_foramted:", my_datetime_foramted)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if not my_datetime_foramted is None:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
my_delimitor_symbol = ' '
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if my_delimitor_symbol in web_datetime:
|
|
|
|
|
web_datetime = web_datetime[:web_datetime.find(my_delimitor_symbol)]
|
|
|
|
|
date_time = datetime.strptime(web_datetime,u"%Y/%m/%d")
|
|
|
|
|
if show_debug_message:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
print("our web date_time:", date_time)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
ans = None
|
|
|
|
|
try:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
if not date_time is None:
|
|
|
|
|
ans = date_time.strftime(my_datetime_foramted)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
inferred_answer_string = ans
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
print("web date_time anwser:", ans)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
return inferred_answer_string
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-14 08:05:00 +00:00
|
|
|
|
def get_answer_string_from_web_time(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, registrationsNewApp_div, captcha_text_div_text):
|
2023-01-02 20:37:54 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2023-01-14 08:05:00 +00:00
|
|
|
|
show_debug_message = False # online
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string = None
|
|
|
|
|
|
|
|
|
|
# parse '演出時間'
|
|
|
|
|
is_need_parse_web_time = False
|
|
|
|
|
if u'半形' in captcha_text_div_text:
|
|
|
|
|
if u'演出時間' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_time = True
|
|
|
|
|
if u'表演時間' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_time = True
|
|
|
|
|
if u'開始時間' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_time = True
|
|
|
|
|
if u'演唱會時間' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_time = True
|
|
|
|
|
if u'展覽時間' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_time = True
|
|
|
|
|
if u'音樂會時間' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_time = True
|
|
|
|
|
if u'the time of the show you purchased' in captcha_text_div_text:
|
|
|
|
|
is_need_parse_web_time = True
|
|
|
|
|
|
|
|
|
|
#print("is_need_parse_web_time", is_need_parse_web_time)
|
|
|
|
|
if is_need_parse_web_time:
|
|
|
|
|
web_datetime = None
|
|
|
|
|
if not registrationsNewApp_div is None:
|
|
|
|
|
web_datetime = kktix_get_web_datetime(registrationsNewApp_div)
|
|
|
|
|
if not web_datetime is None:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
tmp_text = format_question_string(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
my_datetime_foramted = None
|
|
|
|
|
|
|
|
|
|
if my_datetime_foramted is None:
|
|
|
|
|
my_hint_anwser = tmp_text
|
|
|
|
|
|
|
|
|
|
my_delimitor_symbol = CONST_EXAMPLE_SYMBOL
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[my_delimitor_index+len(my_delimitor_symbol):]
|
|
|
|
|
#print("my_hint_anwser:", my_hint_anwser)
|
|
|
|
|
# get before.
|
|
|
|
|
my_delimitor_symbol = u','
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[:my_delimitor_index]
|
|
|
|
|
my_delimitor_symbol = u'。'
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[:my_delimitor_index]
|
|
|
|
|
# PS: space may not is delimitor...
|
|
|
|
|
my_delimitor_symbol = u' '
|
|
|
|
|
if my_delimitor_symbol in my_hint_anwser:
|
|
|
|
|
my_delimitor_index = my_hint_anwser.find(my_delimitor_symbol)
|
|
|
|
|
my_hint_anwser = my_hint_anwser[:my_delimitor_index]
|
|
|
|
|
my_anwser_formated = convert_string_to_pattern(my_hint_anwser, dynamic_length=False)
|
|
|
|
|
#print("my_hint_anwser:", my_hint_anwser)
|
|
|
|
|
#print(u"my_anwser_formated:", my_anwser_formated)
|
|
|
|
|
if my_anwser_formated == u"[\\d][\\d][\\d][\\d]":
|
|
|
|
|
my_datetime_foramted = "%H%M"
|
|
|
|
|
if u'12小時' in tmp_text:
|
|
|
|
|
my_datetime_foramted = "%I%M"
|
|
|
|
|
|
|
|
|
|
if my_anwser_formated == u"[\\d][\\d]:[\\d][\\d]":
|
|
|
|
|
my_datetime_foramted = "%H:%M"
|
|
|
|
|
if u'12小時' in tmp_text:
|
|
|
|
|
my_datetime_foramted = "%I:%M"
|
|
|
|
|
|
|
|
|
|
if not my_datetime_foramted is None:
|
|
|
|
|
date_delimitor_symbol = u'('
|
|
|
|
|
if date_delimitor_symbol in web_datetime:
|
|
|
|
|
date_delimitor_symbol_index = web_datetime.find(date_delimitor_symbol)
|
|
|
|
|
if date_delimitor_symbol_index > 8:
|
|
|
|
|
web_datetime = web_datetime[:date_delimitor_symbol_index-1]
|
|
|
|
|
date_time = datetime.strptime(web_datetime,u"%Y/%m/%d %H:%M")
|
|
|
|
|
#print("date_time:", date_time)
|
|
|
|
|
ans = None
|
|
|
|
|
try:
|
|
|
|
|
ans = date_time.strftime(my_datetime_foramted)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
inferred_answer_string = ans
|
|
|
|
|
#print(u"my_anwser:", ans)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
return inferred_answer_string
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
def check_answer_keep_symbol(captcha_text_div_text):
|
|
|
|
|
is_need_keep_symbol = False
|
2022-11-06 09:10:35 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
# format text
|
|
|
|
|
keep_symbol_tmp = captcha_text_div_text
|
|
|
|
|
keep_symbol_tmp = keep_symbol_tmp.replace(u'也',u'須')
|
|
|
|
|
keep_symbol_tmp = keep_symbol_tmp.replace(u'必須',u'須')
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
keep_symbol_tmp = keep_symbol_tmp.replace(u'全都',u'都')
|
|
|
|
|
keep_symbol_tmp = keep_symbol_tmp.replace(u'全部都',u'都')
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
keep_symbol_tmp = keep_symbol_tmp.replace(u'一致',u'相同')
|
|
|
|
|
keep_symbol_tmp = keep_symbol_tmp.replace(u'一樣',u'相同')
|
|
|
|
|
keep_symbol_tmp = keep_symbol_tmp.replace(u'相等',u'相同')
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if u'符號須都相同' in keep_symbol_tmp:
|
|
|
|
|
is_need_keep_symbol = True
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if u'符號都相同' in keep_symbol_tmp:
|
|
|
|
|
is_need_keep_symbol = True
|
|
|
|
|
|
|
|
|
|
if u'符號須相同' in keep_symbol_tmp:
|
|
|
|
|
is_need_keep_symbol = True
|
|
|
|
|
|
|
|
|
|
return is_need_keep_symbol
|
|
|
|
|
|
|
|
|
|
def get_answer_list_from_question_string(registrationsNewApp_div, captcha_text_div_text):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
|
|
|
|
inferred_answer_string = None
|
|
|
|
|
answer_list = None
|
|
|
|
|
is_need_keep_symbol = check_answer_keep_symbol(captcha_text_div_text)
|
|
|
|
|
|
|
|
|
|
CONST_EXAMPLE_SYMBOL = "範例"
|
2023-01-14 08:05:00 +00:00
|
|
|
|
CONST_INPUT_SYMBOL = "輸入"
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
# 請在下方空白處輸入引號內文字:
|
|
|
|
|
if inferred_answer_string is None:
|
|
|
|
|
is_use_quota_message = False
|
|
|
|
|
if u"「" in captcha_text_div_text and u"」" in captcha_text_div_text:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
if u'下' in captcha_text_div_text and u'空' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u'引號' in captcha_text_div_text and u'字' in captcha_text_div_text:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_use_quota_message = True
|
2023-01-14 08:05:00 +00:00
|
|
|
|
if u'半形' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u'引號' in captcha_text_div_text and u'字' in captcha_text_div_text:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_use_quota_message = True
|
|
|
|
|
#print("is_use_quota_message:" , is_use_quota_message)
|
|
|
|
|
if is_use_quota_message:
|
|
|
|
|
inferred_answer_string = find_between(captcha_text_div_text, u"「", u"」")
|
|
|
|
|
#print("find captcha text:" , inferred_answer_string)
|
|
|
|
|
|
|
|
|
|
if inferred_answer_string is None:
|
|
|
|
|
is_use_quota_message = False
|
|
|
|
|
if u"【" in captcha_text_div_text and u"】" in captcha_text_div_text:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
if u'下' in captcha_text_div_text and u'空' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u'引號' in captcha_text_div_text and u'字' in captcha_text_div_text:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_use_quota_message = True
|
2023-01-14 08:05:00 +00:00
|
|
|
|
if u'半形' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u'引號' in captcha_text_div_text and u'字' in captcha_text_div_text:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_use_quota_message = True
|
|
|
|
|
#print("is_use_quota_message:" , is_use_quota_message)
|
|
|
|
|
if is_use_quota_message:
|
|
|
|
|
inferred_answer_string = find_between(captcha_text_div_text, u"【", u"】")
|
|
|
|
|
#print("find captcha text:" , inferred_answer_string)
|
|
|
|
|
|
|
|
|
|
# parse '演出日期'
|
|
|
|
|
if inferred_answer_string is None:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
inferred_answer_string = get_answer_string_from_web_date(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, registrationsNewApp_div, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
# parse '演出時間'
|
|
|
|
|
if inferred_answer_string is None:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
inferred_answer_string = get_answer_string_from_web_time(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, registrationsNewApp_div, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
|
|
|
|
# name of event.
|
|
|
|
|
if inferred_answer_string is None:
|
|
|
|
|
if u"name of event" in captcha_text_div_text:
|
|
|
|
|
if u'(' in captcha_text_div_text and u')' in captcha_text_div_text and u'ans:' in captcha_text_div_text.lower():
|
|
|
|
|
target_symbol = u"("
|
|
|
|
|
star_index = captcha_text_div_text.find(target_symbol)
|
|
|
|
|
target_symbol = u":"
|
|
|
|
|
star_index = captcha_text_div_text.find(target_symbol, star_index)
|
|
|
|
|
target_symbol = u")"
|
|
|
|
|
end_index = captcha_text_div_text.find(target_symbol, star_index)
|
|
|
|
|
inferred_answer_string = captcha_text_div_text[star_index+1:end_index]
|
|
|
|
|
#print("inferred_answer_string:", inferred_answer_string)
|
|
|
|
|
|
|
|
|
|
# 二題式,組合問題。
|
|
|
|
|
is_combine_two_question = False
|
|
|
|
|
if u"第一題" in captcha_text_div_text and u"第二題" in captcha_text_div_text:
|
|
|
|
|
is_combine_two_question = True
|
|
|
|
|
if u"Q1." in captcha_text_div_text and u"Q2." in captcha_text_div_text:
|
|
|
|
|
if u"二題" in captcha_text_div_text:
|
|
|
|
|
is_combine_two_question = True
|
|
|
|
|
if u"2題" in captcha_text_div_text:
|
|
|
|
|
is_combine_two_question = True
|
|
|
|
|
if u"Q1:" in captcha_text_div_text and u"Q2:" in captcha_text_div_text:
|
|
|
|
|
if u"二題" in captcha_text_div_text:
|
|
|
|
|
is_combine_two_question = True
|
|
|
|
|
if u"2題" in captcha_text_div_text:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
is_combine_two_question = True
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if u"Q1 " in captcha_text_div_text and u"Q2 " in captcha_text_div_text:
|
|
|
|
|
if u"二題" in captcha_text_div_text:
|
|
|
|
|
is_combine_two_question = True
|
|
|
|
|
if u"2題" in captcha_text_div_text:
|
|
|
|
|
is_combine_two_question = True
|
|
|
|
|
if is_combine_two_question:
|
|
|
|
|
inferred_answer_string = None
|
|
|
|
|
#print("is_combine_two_question:", is_combine_two_question)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# still no answer.
|
|
|
|
|
if inferred_answer_string is None:
|
|
|
|
|
if not is_combine_two_question:
|
2023-01-14 08:05:00 +00:00
|
|
|
|
answer_list = get_answer_list_by_question(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captcha_text_div_text)
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("guess answer list:", answer_list)
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("skip to guess answer because of combine question...")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
else:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
print("got an inferred_answer_string:", inferred_answer_string)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return inferred_answer_string, answer_list
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
def kktix_reg_new_captcha(registrationsNewApp_div, captcha_inner_div):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
captcha_text_div = None
|
|
|
|
|
try:
|
|
|
|
|
captcha_text_div = captcha_inner_div.find_element(By.TAG_NAME, "p")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
print("find p tag(captcha_text_div) fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
|
|
|
|
captcha_text_div_text = None
|
|
|
|
|
if captcha_text_div is not None:
|
|
|
|
|
try:
|
|
|
|
|
captcha_text_div_text = captcha_text_div.text
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# try to auto answer options.
|
|
|
|
|
answer_list = None
|
|
|
|
|
inferred_answer_string = None
|
|
|
|
|
|
|
|
|
|
if not captcha_text_div_text is None:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("captcha_text_div_text:", captcha_text_div_text)
|
|
|
|
|
inferred_answer_string, answer_list = get_answer_list_from_question_string(registrationsNewApp_div, captcha_text_div_text)
|
|
|
|
|
|
|
|
|
|
return inferred_answer_string, answer_list
|
2022-11-06 09:10:35 +00:00
|
|
|
|
|
2022-11-24 21:40:40 +00:00
|
|
|
|
def kktix_double_check_all_text_value(driver, ticket_number_str):
|
2022-11-18 22:59:34 +00:00
|
|
|
|
is_do_press_next_button = False
|
2022-11-06 09:10:35 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# double check ticket input textbox.
|
|
|
|
|
ticket_price_input_list = None
|
|
|
|
|
try:
|
|
|
|
|
# PS: unable directly access text's value attribute via css selector or xpath on KKTix!
|
|
|
|
|
my_css_selector = "input[type='text']"
|
|
|
|
|
#print("my_css_selector:", my_css_selector)
|
|
|
|
|
ticket_price_input_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if ticket_price_input_list is not None:
|
|
|
|
|
#print("bingo, found one of ticket number textbox.")
|
|
|
|
|
row_index = 0
|
|
|
|
|
for ticket_price_input in ticket_price_input_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
current_ticket_number = ""
|
|
|
|
|
try:
|
|
|
|
|
current_ticket_number = str(ticket_price_input.get_attribute('value')).strip()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
if current_ticket_number is None:
|
|
|
|
|
current_ticket_number = ""
|
|
|
|
|
if len(current_ticket_number) > 0:
|
|
|
|
|
#print(row_index, "current_ticket_number:", current_ticket_number)
|
2022-11-24 21:40:40 +00:00
|
|
|
|
if current_ticket_number == ticket_number_str:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
#print("bingo, match target ticket number.")
|
|
|
|
|
|
|
|
|
|
# ONLY, this case to auto press next button.
|
|
|
|
|
is_do_press_next_button = True
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
return is_do_press_next_button
|
2020-01-21 13:30:30 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
def kktix_reg_new_main(driver, answer_index, is_finish_checkbox_click, config_dict):
|
|
|
|
|
show_debug_message = True # debug.
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = False # online
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# part 1: check div.
|
|
|
|
|
registrationsNewApp_div = None
|
|
|
|
|
try:
|
|
|
|
|
registrationsNewApp_div = driver.find_element(By.CSS_SELECTOR, '#registrationsNewApp')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
#print("find input fail:", exc)
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# part 2: assign ticket number
|
2022-11-24 21:40:40 +00:00
|
|
|
|
ticket_number_str = str(config_dict["ticket_number"])
|
|
|
|
|
|
|
|
|
|
pass_1_seat_remaining_enable = config_dict["pass_1_seat_remaining"]
|
|
|
|
|
# disable pass 1 seat remaining when target ticket number is 1.
|
|
|
|
|
ticket_number = config_dict["ticket_number"]
|
|
|
|
|
if ticket_number == 1:
|
|
|
|
|
pass_1_seat_remaining_enable = False
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = False
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if not registrationsNewApp_div is None:
|
|
|
|
|
kktix_area_auto_select_mode = config_dict["kktix"]["area_mode"]
|
2022-11-23 04:39:46 +00:00
|
|
|
|
kktix_area_keyword_1 = config_dict["kktix"]["area_keyword_1"].strip()
|
|
|
|
|
kktix_area_keyword_1_and = config_dict["kktix"]["area_keyword_1_and"].strip()
|
|
|
|
|
kktix_area_keyword_2 = config_dict["kktix"]["area_keyword_2"].strip()
|
|
|
|
|
kktix_area_keyword_2_and = config_dict["kktix"]["area_keyword_2_and"].strip()
|
|
|
|
|
|
|
|
|
|
for retry_index in range(2):
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and)
|
|
|
|
|
if not is_ticket_number_assigned:
|
|
|
|
|
is_ticket_number_assigned = kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and)
|
2023-01-03 22:12:21 +00:00
|
|
|
|
#PS: keyword_2 not input, means all rows are match.
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if not is_ticket_number_assigned:
|
|
|
|
|
is_ticket_number_assigned = kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_2, kktix_area_keyword_2_and)
|
|
|
|
|
if is_ticket_number_assigned:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
break
|
2023-01-02 06:53:28 +00:00
|
|
|
|
#print('is_ticket_number_assigned:', is_ticket_number_assigned)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# part 3: captcha
|
|
|
|
|
is_captcha_appear = False
|
|
|
|
|
is_captcha_appear_and_filled_password = False
|
|
|
|
|
answer_list = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
# TODO: in guess options mode, no need to travel div again.
|
|
|
|
|
captcha_inner_div = None
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if is_ticket_number_assigned:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
try:
|
|
|
|
|
captcha_inner_div = driver.find_element(By.CSS_SELECTOR, '.custom-captcha-inner')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
captcha_password_input_tag = None
|
|
|
|
|
if not captcha_inner_div is None:
|
|
|
|
|
try:
|
|
|
|
|
captcha_password_input_tag = captcha_inner_div.find_element(By.TAG_NAME, "input")
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("found captcha input field")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if not captcha_password_input_tag is None:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string = None
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if captcha_inner_div is not None:
|
|
|
|
|
is_captcha_appear = True
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("found captcha_inner_div layor.")
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
auto_guess_options = config_dict["kktix"]["auto_guess_options"]
|
2022-12-27 15:38:13 +00:00
|
|
|
|
user_guess_string = config_dict["kktix"]["user_guess_string"]
|
|
|
|
|
|
|
|
|
|
if len(user_guess_string) > 0:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string = user_guess_string
|
2022-12-27 15:38:13 +00:00
|
|
|
|
else:
|
|
|
|
|
if auto_guess_options:
|
2023-01-02 20:37:54 +00:00
|
|
|
|
inferred_answer_string, answer_list = kktix_reg_new_captcha(registrationsNewApp_div, captcha_inner_div)
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if inferred_answer_string is not None:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
# password is not None, try to send.
|
2023-01-02 20:37:54 +00:00
|
|
|
|
is_cpatcha_sent = kktix_input_captcha_text(captcha_password_input_tag, inferred_answer_string)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if is_cpatcha_sent:
|
|
|
|
|
is_captcha_appear_and_filled_password = True
|
|
|
|
|
else:
|
|
|
|
|
is_try_to_focus = False
|
|
|
|
|
if answer_list is None:
|
|
|
|
|
is_try_to_focus = True
|
|
|
|
|
else:
|
|
|
|
|
if len(answer_list)==0:
|
|
|
|
|
is_try_to_focus = True
|
|
|
|
|
|
|
|
|
|
if is_try_to_focus:
|
|
|
|
|
# password is None, focus to input, and play sound.
|
|
|
|
|
inputed_captcha_text = None
|
|
|
|
|
try:
|
|
|
|
|
inputed_captcha_text = captcha_password_input_tag.get_attribute('value')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
if inputed_captcha_text is None:
|
|
|
|
|
inputed_captcha_text = ""
|
|
|
|
|
if len(inputed_captcha_text) == 0:
|
|
|
|
|
try:
|
2022-12-27 15:38:13 +00:00
|
|
|
|
#print("focus() captcha to input.")
|
2022-11-20 07:57:16 +00:00
|
|
|
|
check_and_play_sound_for_captcha(config_dict)
|
|
|
|
|
captcha_password_input_tag.click()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
# let user to input answer, bot sleep 1 second.
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("is_captcha_appear:", is_captcha_appear)
|
|
|
|
|
print("is_captcha_appear_and_filled_password:", is_captcha_appear_and_filled_password)
|
2019-12-06 18:36:43 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# retry check agree checkbox again.
|
|
|
|
|
if not is_finish_checkbox_click:
|
2022-12-15 11:26:51 +00:00
|
|
|
|
auto_check_agree = config_dict["auto_check_agree"]
|
|
|
|
|
if auto_check_agree:
|
|
|
|
|
is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
|
|
|
|
is_do_press_next_button = False
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if is_ticket_number_assigned:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"]
|
2022-11-23 04:39:46 +00:00
|
|
|
|
if auto_press_next_step_button:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if is_finish_checkbox_click:
|
2022-11-24 21:40:40 +00:00
|
|
|
|
is_do_press_next_button = kktix_double_check_all_text_value(driver, ticket_number_str)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
else:
|
|
|
|
|
print("still unable to assign checkbox as selected.")
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("is_do_press_next_button:", is_do_press_next_button)
|
|
|
|
|
|
|
|
|
|
if is_do_press_next_button:
|
|
|
|
|
if not is_captcha_appear:
|
|
|
|
|
click_ret = kktix_press_next_button(driver)
|
|
|
|
|
else:
|
|
|
|
|
if is_captcha_appear_and_filled_password:
|
|
|
|
|
# for easy guest mode, we can fill the password correct.
|
|
|
|
|
#print("for easy guest mode, we can fill the password correct.")
|
|
|
|
|
click_ret = kktix_press_next_button(driver)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
else:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# not is easy guest mode.
|
|
|
|
|
#print("# not is easy guest mode.")
|
|
|
|
|
|
|
|
|
|
# merge with password dictionary, so need remove duplicate list
|
|
|
|
|
# PS: now, there are no password dictionary.
|
|
|
|
|
if not answer_list is None:
|
|
|
|
|
if len(answer_list) > 1:
|
|
|
|
|
unique = [x for i, x in enumerate(answer_list) if answer_list.index(x) == i]
|
|
|
|
|
answer_list = unique
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
# start to try answers.
|
2022-11-18 22:59:34 +00:00
|
|
|
|
if not answer_list is None:
|
|
|
|
|
# for popular event
|
|
|
|
|
if len(answer_list) > 0:
|
|
|
|
|
if answer_index < len(answer_list)-1:
|
|
|
|
|
if kktix_captcha_text_value(captcha_inner_div) == "":
|
|
|
|
|
answer_index += 1
|
2023-01-02 20:37:54 +00:00
|
|
|
|
answer_string = answer_list[answer_index]
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 20:37:54 +00:00
|
|
|
|
if len(answer_string) > 0:
|
|
|
|
|
print("send answer:" + answer_string)
|
|
|
|
|
is_cpatcha_sent = kktix_input_captcha_text(captcha_password_input_tag, answer_string)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if is_cpatcha_sent:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
kktix_press_next_button(driver)
|
2022-10-22 01:19:57 +00:00
|
|
|
|
else:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# exceed index, do nothing.
|
2022-10-22 01:19:57 +00:00
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
else:
|
2022-12-27 15:38:13 +00:00
|
|
|
|
# captcha appeared, but we don't have answer list.
|
2022-11-18 22:59:34 +00:00
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return answer_index
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def kktix_reg_new(driver, url, answer_index, kktix_register_status_last, config_dict):
|
2019-12-14 19:13:20 +00:00
|
|
|
|
registerStatus = kktix_register_status_last
|
|
|
|
|
|
|
|
|
|
# auto refresh for area list page.
|
|
|
|
|
is_need_refresh = False
|
|
|
|
|
is_finish_checkbox_click = False
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if registerStatus is None:
|
|
|
|
|
registerStatus = kktix_check_register_status(url)
|
|
|
|
|
if not registerStatus is None:
|
|
|
|
|
print("registerStatus:", registerStatus)
|
|
|
|
|
# OUT_OF_STOCK
|
|
|
|
|
if registerStatus != 'IN_STOCK':
|
|
|
|
|
is_need_refresh = True
|
|
|
|
|
|
2022-12-15 11:26:51 +00:00
|
|
|
|
auto_check_agree = config_dict["auto_check_agree"]
|
|
|
|
|
if auto_check_agree:
|
|
|
|
|
if not is_need_refresh:
|
2022-01-12 17:14:27 +00:00
|
|
|
|
is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver)
|
2022-12-15 11:26:51 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_finish_checkbox_click:
|
|
|
|
|
# retry again.
|
|
|
|
|
is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
#print('check agree_terms_checkbox, is_need_refresh:',is_need_refresh)
|
2019-12-14 19:13:20 +00:00
|
|
|
|
|
|
|
|
|
if is_need_refresh:
|
|
|
|
|
try:
|
|
|
|
|
print("try to refresh page...")
|
|
|
|
|
driver.refresh()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("refresh fail")
|
|
|
|
|
pass
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-12-14 19:13:20 +00:00
|
|
|
|
# reset answer_index
|
|
|
|
|
answer_index = -1
|
|
|
|
|
registerStatus = None
|
|
|
|
|
else:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
# check is able to buy.
|
|
|
|
|
auto_fill_ticket_number = config_dict["kktix"]["auto_fill_ticket_number"]
|
|
|
|
|
if auto_fill_ticket_number:
|
|
|
|
|
answer_index = kktix_reg_new_main(driver, answer_index, is_finish_checkbox_click, config_dict)
|
2019-12-14 19:13:20 +00:00
|
|
|
|
|
|
|
|
|
return answer_index, registerStatus
|
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
|
|
|
|
|
# PURPOSE: get target area list.
|
2022-01-26 12:49:16 +00:00
|
|
|
|
# PS: this is main block, use keyword to get rows.
|
|
|
|
|
# PS: it seems use date_auto_select_mode instead of area_auto_select_mode
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def get_fami_target_area(driver, date_keyword, area_keyword_1, area_keyword_2, area_keyword_3, area_keyword_4, area_auto_select_mode):
|
2022-01-26 12:49:16 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = False # online
|
2022-01-26 12:49:16 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
date_keyword = format_keyword_string(date_keyword)
|
|
|
|
|
area_keyword_1 = format_keyword_string(area_keyword_1)
|
|
|
|
|
area_keyword_2 = format_keyword_string(area_keyword_2)
|
|
|
|
|
area_keyword_3 = format_keyword_string(area_keyword_3)
|
|
|
|
|
area_keyword_4 = format_keyword_string(area_keyword_4)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("try to find area block by keywords...")
|
2021-12-24 10:52:37 +00:00
|
|
|
|
|
|
|
|
|
area_list = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2021-12-24 10:52:37 +00:00
|
|
|
|
my_css_selector = "table.session__list > tbody > tr"
|
|
|
|
|
area_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
2023-01-04 12:02:55 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find #session date list fail")
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print(exc)
|
2022-01-26 12:49:16 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
#PS: some blocks are generate by ajax, not appear at first time.
|
|
|
|
|
formated_area_list = None
|
|
|
|
|
if area_list is not None:
|
|
|
|
|
area_list_length = len(area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("lenth of area rows:", area_list_length)
|
2022-01-26 12:49:16 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if area_list_length > 0:
|
|
|
|
|
formated_area_list = []
|
2022-01-26 12:49:16 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
# filter list.
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = "button"
|
|
|
|
|
el_btn = row.find_element(By.TAG_NAME, my_css_selector)
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
if not el_btn.is_enabled():
|
|
|
|
|
#print("row's button disabled!")
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
2022-01-26 12:49:16 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if row_is_enabled:
|
|
|
|
|
formated_area_list.append(row)
|
2022-01-26 12:49:16 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
matched_blocks = None
|
|
|
|
|
if not formated_area_list is None:
|
|
|
|
|
if len(formated_area_list) > 0:
|
|
|
|
|
matched_blocks = []
|
2022-01-26 12:49:16 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if len(date_keyword)==0 and len(area_keyword_1)==0 and len(area_keyword_2) == 0:
|
|
|
|
|
# select all.
|
|
|
|
|
matched_blocks = formated_area_list
|
|
|
|
|
else:
|
|
|
|
|
# match keyword.
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in formated_area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
#print("row index:", row_index)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
date_html_text = ""
|
|
|
|
|
area_html_text = ""
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
row_text = ""
|
|
|
|
|
try:
|
2021-12-24 10:52:37 +00:00
|
|
|
|
my_css_selector = "td:nth-child(1)"
|
|
|
|
|
td_date = row.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
if td_date is not None:
|
|
|
|
|
#print("date:", td_date.text)
|
2023-01-04 12:02:55 +00:00
|
|
|
|
date_html_text = format_keyword_string(td_date.text)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
my_css_selector = "td:nth-child(2)"
|
|
|
|
|
td_area = row.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
if td_area is not None:
|
|
|
|
|
#print("area:", td_area.text)
|
2023-01-04 12:02:55 +00:00
|
|
|
|
area_html_text = format_keyword_string(td_area.text)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
row_text = row.text
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("get row text fail")
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if row_text is None:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
row_text = ""
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
# check date.
|
|
|
|
|
is_match_date = False
|
|
|
|
|
if len(date_keyword) > 0:
|
|
|
|
|
if date_keyword in date_html_text:
|
|
|
|
|
#print("is_match_date")
|
2021-12-24 10:52:37 +00:00
|
|
|
|
is_match_date = True
|
2023-01-04 12:02:55 +00:00
|
|
|
|
else:
|
|
|
|
|
is_match_date = True
|
2021-12-24 10:52:37 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
# check area.
|
|
|
|
|
is_match_area = False
|
|
|
|
|
if len(area_keyword_1) > 0:
|
|
|
|
|
if area_keyword_1 in area_html_text:
|
|
|
|
|
#print("is_match_area area_keyword_1")
|
|
|
|
|
is_match_area = True
|
|
|
|
|
|
|
|
|
|
# check keyword 2
|
|
|
|
|
if len(area_keyword_2) > 0:
|
|
|
|
|
if area_keyword_2 in area_html_text:
|
|
|
|
|
#print("is_match_area area_keyword_2")
|
2021-12-24 10:52:37 +00:00
|
|
|
|
is_match_area = True
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
# check keyword 3
|
|
|
|
|
if len(area_keyword_3) > 0:
|
|
|
|
|
if area_keyword_3 in area_html_text:
|
|
|
|
|
#print("is_match_area area_keyword_3")
|
|
|
|
|
is_match_area = True
|
2022-11-09 17:56:12 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
# check keyword 4
|
|
|
|
|
if len(area_keyword_4) > 0:
|
|
|
|
|
if area_keyword_4 in area_html_text:
|
|
|
|
|
#print("is_match_area area_keyword_4")
|
|
|
|
|
is_match_area = True
|
|
|
|
|
else:
|
|
|
|
|
is_match_area = True
|
2022-11-09 17:56:12 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if is_match_date and is_match_area:
|
|
|
|
|
matched_blocks.append(row)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
print("only need first item, break area list loop.")
|
|
|
|
|
break
|
2021-12-24 10:52:37 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
return_row_count = 0
|
|
|
|
|
if not matched_blocks is None:
|
|
|
|
|
return_row_count = len(matched_blocks)
|
|
|
|
|
if return_row_count==0:
|
|
|
|
|
matched_blocks = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("return_row_count:", return_row_count)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
return matched_blocks
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def fami_activity(driver):
|
2021-12-24 10:52:37 +00:00
|
|
|
|
#print("fami_activity bingo")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
#---------------------------
|
|
|
|
|
# part 1: press "buy" button.
|
|
|
|
|
#---------------------------
|
|
|
|
|
fami_start_to_buy_button = None
|
2022-11-16 15:43:53 +00:00
|
|
|
|
try:
|
|
|
|
|
fami_start_to_buy_button = driver.find_element(By.ID, 'buyWaiting')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
is_visible = False
|
2022-09-19 16:20:51 +00:00
|
|
|
|
if fami_start_to_buy_button is not None:
|
2022-11-09 18:36:17 +00:00
|
|
|
|
try:
|
|
|
|
|
if fami_start_to_buy_button.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if is_visible:
|
|
|
|
|
try:
|
|
|
|
|
fami_start_to_buy_button.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click buyWaiting button fail...")
|
|
|
|
|
#print(exc)
|
|
|
|
|
#pass
|
2022-09-19 16:20:51 +00:00
|
|
|
|
try:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
driver.execute_script("arguments[0].click();", fami_start_to_buy_button)
|
2022-09-19 16:20:51 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
def fami_home(driver, url, config_dict):
|
|
|
|
|
#print("fami_home bingo")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = False
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
|
|
|
|
ticket_number = str(config_dict["ticket_number"])
|
|
|
|
|
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
|
|
|
|
|
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"]
|
|
|
|
|
area_keyword_1 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_1"].strip()
|
|
|
|
|
area_keyword_2 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_2"].strip()
|
|
|
|
|
area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip()
|
|
|
|
|
area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip()
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
#---------------------------
|
|
|
|
|
# part 3: fill ticket number.
|
|
|
|
|
#---------------------------
|
|
|
|
|
ticket_el = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2021-12-24 10:52:37 +00:00
|
|
|
|
my_css_selector = "tr.ticket > td > select"
|
|
|
|
|
ticket_el = driver.find_element(By.CSS_SELECTOR, my_css_selector)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
print("click buyWaiting button fail")
|
|
|
|
|
#print(exc)
|
|
|
|
|
|
|
|
|
|
is_select_box_visible = False
|
|
|
|
|
if ticket_el is not None:
|
|
|
|
|
try:
|
2021-12-24 10:52:37 +00:00
|
|
|
|
if ticket_el.is_enabled():
|
|
|
|
|
is_select_box_visible = True
|
2022-11-16 15:43:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = False
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if is_select_box_visible:
|
|
|
|
|
ticket_number_select = None
|
|
|
|
|
try:
|
2021-12-24 10:52:37 +00:00
|
|
|
|
ticket_number_select = Select(ticket_el)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if ticket_number_select is not None:
|
|
|
|
|
try:
|
|
|
|
|
#print("get select ticket value:" + Select(ticket_number_select).first_selected_option.text)
|
|
|
|
|
if ticket_number_select.first_selected_option.text=="0" or ticket_number_select.first_selected_option.text=="選擇張數":
|
|
|
|
|
# target ticket number
|
|
|
|
|
ticket_number_select.select_by_visible_text(ticket_number)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2022-11-16 15:43:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("select_by_visible_text ticket_number fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
try:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
# try target ticket number twice
|
|
|
|
|
ticket_number_select.select_by_visible_text(ticket_number)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2021-12-24 10:52:37 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
print("select_by_visible_text ticket_number fail...2")
|
2021-12-24 10:52:37 +00:00
|
|
|
|
print(exc)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
# try buy one ticket
|
2021-12-24 10:52:37 +00:00
|
|
|
|
try:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
ticket_number_select.select_by_visible_text("1")
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2021-12-24 10:52:37 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
print("select_by_visible_text 1 fail")
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
#---------------------------
|
|
|
|
|
# part 4: press "next" button.
|
|
|
|
|
#---------------------------
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if is_ticket_number_assigned:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
fami_assign_site_button = None
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = "div.col > a.btn"
|
|
|
|
|
fami_assign_site_button = driver.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2022-09-19 16:20:51 +00:00
|
|
|
|
if fami_assign_site_button is not None:
|
2022-11-09 18:36:17 +00:00
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
|
|
|
|
if fami_assign_site_button.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
2022-09-19 16:20:51 +00:00
|
|
|
|
try:
|
2021-12-24 10:52:37 +00:00
|
|
|
|
fami_assign_site_button.click()
|
2022-09-19 16:20:51 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click buyWaiting button fail")
|
|
|
|
|
#print(exc)
|
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("arguments[0].click();", fami_assign_site_button)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
areas = None
|
|
|
|
|
if not is_select_box_visible:
|
|
|
|
|
#---------------------------
|
|
|
|
|
# part 2: select keywords
|
|
|
|
|
#---------------------------
|
2022-11-16 15:43:53 +00:00
|
|
|
|
areas = get_fami_target_area(driver, date_keyword, area_keyword_1, area_keyword_2, area_keyword_3, area_keyword_4, area_auto_select_mode)
|
2019-10-27 01:31:22 +00:00
|
|
|
|
|
2022-01-26 12:49:16 +00:00
|
|
|
|
area_target = None
|
|
|
|
|
if areas is not None:
|
|
|
|
|
#print("area_auto_select_mode", area_auto_select_mode)
|
|
|
|
|
#print("len(areas)", len(areas))
|
|
|
|
|
if len(areas) > 0:
|
|
|
|
|
target_row_index = 0
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-01-26 12:49:16 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-01-26 12:49:16 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(areas)-1
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-01-26 12:49:16 +00:00
|
|
|
|
if area_auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(areas)-1)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-01-26 12:49:16 +00:00
|
|
|
|
#print("target_row_index", target_row_index)
|
|
|
|
|
area_target = areas[target_row_index]
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-01-26 12:49:16 +00:00
|
|
|
|
if area_target is not None:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
el_btn = None
|
2022-11-09 18:36:17 +00:00
|
|
|
|
is_visible = False
|
|
|
|
|
try:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
my_css_selector = "button"
|
|
|
|
|
el_btn = area_target.find_element(By.TAG_NAME, my_css_selector)
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
is_visible = True
|
2022-11-09 18:36:17 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
2022-01-26 12:49:16 +00:00
|
|
|
|
try:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
el_btn.click()
|
2022-01-26 12:49:16 +00:00
|
|
|
|
except Exception as exc:
|
2022-09-19 16:20:51 +00:00
|
|
|
|
print("click buy button fail, start to retry...")
|
|
|
|
|
try:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
2022-09-19 16:20:51 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
# purpose: date auto select
|
2023-01-03 18:54:42 +00:00
|
|
|
|
def urbtix_date_auto_select(driver, auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable):
|
2023-01-02 06:53:28 +00:00
|
|
|
|
show_debug_message = True # debug.
|
2023-01-03 18:54:42 +00:00
|
|
|
|
show_debug_message = False # online
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = False
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
# clean stop word.
|
|
|
|
|
date_keyword = format_keyword_string(date_keyword)
|
|
|
|
|
date_keyword_and = ""
|
|
|
|
|
|
|
|
|
|
area_list = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
#print("try to find cityline area block")
|
2023-01-03 21:09:17 +00:00
|
|
|
|
my_css_selector = "div.conent-wrapper > div.list-wrapper > ul"
|
2023-01-02 06:53:28 +00:00
|
|
|
|
area_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find #date-time-position date list fail")
|
|
|
|
|
print(exc)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
#PS: some blocks are generate by ajax, not appear at first time.
|
|
|
|
|
formated_area_list = None
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_list is not None:
|
|
|
|
|
area_list_count = len(area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("date_list_count:", area_list_count)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_list_count > 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = []
|
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
# filter list.
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = "div.buy-icon"
|
|
|
|
|
el_btn = row.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
if el_btn is not None:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
button_class_string = str(el_btn.get_attribute('class'))
|
|
|
|
|
if len(button_class_string) > 1:
|
|
|
|
|
if 'disabled' in button_class_string:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("found disabled activity at row:", row_index)
|
|
|
|
|
row_is_enabled=False
|
2023-01-03 18:54:42 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
formated_area_list.append(row)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("formated_area_list count:", len(formated_area_list))
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
if len(date_keyword) == 0:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
matched_blocks = formated_area_list
|
2023-01-02 06:53:28 +00:00
|
|
|
|
else:
|
|
|
|
|
# match keyword.
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("start to match keyword:", date_keyword)
|
|
|
|
|
matched_blocks = []
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
row_index = 0
|
2023-01-03 18:54:42 +00:00
|
|
|
|
for row in formated_area_list:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
row_index += 1
|
|
|
|
|
#row_is_enabled=False
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
row_text = ""
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
row_text = row.text
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print("get text fail")
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if row_text is None:
|
|
|
|
|
row_text = ""
|
|
|
|
|
|
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
row_text = format_keyword_string(row_text)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("row_text:", row_text)
|
|
|
|
|
|
|
|
|
|
is_match_area = False
|
|
|
|
|
match_area_code = 0
|
|
|
|
|
|
|
|
|
|
if date_keyword in row_text:
|
|
|
|
|
if len(date_keyword_and) == 0:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('keyword_and # is empty, directly match.')
|
|
|
|
|
# keyword #2 is empty, direct append.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 2
|
|
|
|
|
else:
|
|
|
|
|
if date_keyword_and in row_text:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('match keyword_and')
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 3
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('not match keyword_and')
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_match_area:
|
|
|
|
|
matched_blocks.append(row)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if not matched_blocks is None:
|
|
|
|
|
print("after match keyword, found count:", len(matched_blocks))
|
2023-01-02 06:53:28 +00:00
|
|
|
|
else:
|
|
|
|
|
print("not found date-time-position")
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
print("date date-time-position is None")
|
2022-07-26 16:51:43 +00:00
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
target_area = None
|
|
|
|
|
if matched_blocks is not None:
|
|
|
|
|
if len(matched_blocks) > 0:
|
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(matched_blocks)-1
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(matched_blocks)-1)
|
|
|
|
|
|
|
|
|
|
target_area = matched_blocks[target_row_index]
|
|
|
|
|
|
|
|
|
|
if target_area is not None:
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
#print("target_area text", target_area.text)
|
|
|
|
|
my_css_selector = "div.buy-icon"
|
|
|
|
|
el_btn = target_area.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
if el_btn is not None:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
is_button_enable = True
|
2023-01-02 06:53:28 +00:00
|
|
|
|
try:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if not el_btn.is_enabled():
|
|
|
|
|
is_button_enable = False
|
|
|
|
|
else:
|
|
|
|
|
# button enable, but class disable.
|
|
|
|
|
button_class_string = str(el_btn.get_attribute('class'))
|
|
|
|
|
if len(button_class_string) > 1:
|
|
|
|
|
if 'disabled' in button_class_string:
|
|
|
|
|
is_button_enable = False
|
|
|
|
|
if is_button_enable:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
el_btn.click()
|
2023-01-03 18:54:42 +00:00
|
|
|
|
ret = True
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print("buy icon pressed.")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-03 18:54:42 +00:00
|
|
|
|
else:
|
|
|
|
|
# no target.
|
|
|
|
|
if auto_reload_coming_soon_page_enable:
|
|
|
|
|
# auto refresh for date list page.
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if not formated_area_list is None:
|
|
|
|
|
if len(formated_area_list) == 0:
|
|
|
|
|
try:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
time.sleep(1.0)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
def urbtix_purchase_ticket(driver, config_dict):
|
|
|
|
|
show_debug_message = True # debug.
|
2023-01-03 18:54:42 +00:00
|
|
|
|
show_debug_message = False # online
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
date_auto_select_mode = config_dict["tixcraft"]["date_auto_select"]["mode"]
|
|
|
|
|
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
|
2023-01-03 18:54:42 +00:00
|
|
|
|
auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("date_keyword:", date_keyword)
|
|
|
|
|
is_date_assign_by_bot = urbtix_date_auto_select(driver, date_auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
return is_date_assign_by_bot
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
# purpose: area auto select
|
2023-01-02 06:53:28 +00:00
|
|
|
|
def urbtix_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and):
|
|
|
|
|
show_debug_message = True # debug.
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = False # online
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = False
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = False
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks = None
|
|
|
|
|
|
|
|
|
|
# clean stop word.
|
|
|
|
|
area_keyword_1 = format_keyword_string(area_keyword_1)
|
|
|
|
|
area_keyword_1_and = format_keyword_string(area_keyword_1_and)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
area_list = None
|
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
#print("try to find cityline area block")
|
|
|
|
|
my_css_selector = "div.area-info"
|
2019-10-01 17:52:13 +00:00
|
|
|
|
area_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find #ticket-price-tbl date list fail")
|
|
|
|
|
print(exc)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = None
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_list is not None:
|
|
|
|
|
area_list_count = len(area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_list_count:", area_list_count)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_list_count > 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = []
|
|
|
|
|
# filter list.
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
try:
|
|
|
|
|
button_class_string = str(row.get_attribute('class'))
|
|
|
|
|
if len(button_class_string) > 1:
|
|
|
|
|
if 'disabled' in button_class_string:
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
if 'selected' in button_class_string:
|
|
|
|
|
# someone is selected. skip this process.
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
matched_blocks = []
|
|
|
|
|
ret = True
|
|
|
|
|
break
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
formated_area_list.append(row)
|
2023-01-11 00:40:31 +00:00
|
|
|
|
else:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
print("area_list_count is empty.")
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_list_count is None.")
|
|
|
|
|
pass
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if formated_area_list is not None:
|
|
|
|
|
area_list_count = len(formated_area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("formated_area_list count:", area_list_count)
|
|
|
|
|
|
|
|
|
|
if area_list_count > 0:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if len(area_keyword_1) == 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
matched_blocks = formated_area_list
|
2023-01-02 06:53:28 +00:00
|
|
|
|
else:
|
|
|
|
|
# match keyword.
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("start to match keyword:", area_keyword_1)
|
|
|
|
|
print("keyword and:", area_keyword_1_and)
|
|
|
|
|
matched_blocks = []
|
|
|
|
|
|
|
|
|
|
row_index = 0
|
2023-01-03 21:09:17 +00:00
|
|
|
|
for row in formated_area_list:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
row_index += 1
|
2023-01-02 20:37:54 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
row_is_enabled=True
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
row_text = ""
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
row_text = row.text
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print("get text fail")
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if row_text is None:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
row_text = ""
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
row_text = format_keyword_string(row_text)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("row_text:", row_text)
|
|
|
|
|
|
|
|
|
|
is_match_area = False
|
|
|
|
|
match_area_code = 0
|
|
|
|
|
|
|
|
|
|
if area_keyword_1 in row_text:
|
|
|
|
|
if len(area_keyword_1_and) == 0:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('keyword_and is empty, directly match.')
|
|
|
|
|
# keyword #2 is empty, direct append.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 2
|
|
|
|
|
else:
|
|
|
|
|
if area_keyword_1_and in row_text:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('match keyword_and')
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 3
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('not match keyword_and')
|
|
|
|
|
pass
|
2022-11-13 04:50:53 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if is_match_area:
|
|
|
|
|
matched_blocks.append(row)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
if not matched_blocks is None:
|
|
|
|
|
print("after match keyword, found count:", len(matched_blocks))
|
|
|
|
|
else:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = True
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
print("formated_area_list is empty.")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
target_area = None
|
|
|
|
|
if matched_blocks is not None:
|
|
|
|
|
if len(matched_blocks) > 0:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(matched_blocks)-1
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(matched_blocks)-1)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
target_area = matched_blocks[target_row_index]
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if target_area is not None:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if target_area.is_enabled():
|
|
|
|
|
target_area.click()
|
|
|
|
|
ret = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print("click target_area link fail")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
print(exc)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", target_area)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
return is_need_refresh, ret
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
def urbtix_ticket_number_auto_select(driver, ticket_number):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
#show_debug_message = False # online
|
|
|
|
|
|
|
|
|
|
is_ticket_number_assigned = False
|
|
|
|
|
ticket_number_str = str(ticket_number)
|
|
|
|
|
|
|
|
|
|
# check ticket input textbox.
|
|
|
|
|
ticket_price_input = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
ticket_price_input = driver.find_element(By.CSS_SELECTOR, "input.ticket-count")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if ticket_price_input is not None:
|
|
|
|
|
current_ticket_number = ""
|
|
|
|
|
is_visible = False
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
current_ticket_number = str(ticket_price_input.get_attribute('value')).strip()
|
|
|
|
|
is_visible = ticket_price_input.is_enabled()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if len(current_ticket_number) > 0:
|
|
|
|
|
if current_ticket_number == "0":
|
|
|
|
|
try:
|
|
|
|
|
print("asssign ticket number:%s" % ticket_number_str)
|
|
|
|
|
ticket_price_input.clear()
|
|
|
|
|
ticket_price_input.send_keys(ticket_number_str)
|
|
|
|
|
|
|
|
|
|
is_ticket_number_assigned = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("asssign ticket number to ticket-price field Exception:")
|
|
|
|
|
print(exc)
|
|
|
|
|
try:
|
|
|
|
|
ticket_price_input.clear()
|
|
|
|
|
ticket_price_input.send_keys("1")
|
|
|
|
|
is_ticket_number_assigned = True
|
|
|
|
|
except Exception as exc2:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
# already assigned.
|
|
|
|
|
is_ticket_number_assigned = True
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if is_ticket_number_assigned:
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = "div.footer > div > div"
|
|
|
|
|
el_btn = driver.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
try:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
el_btn.click()
|
|
|
|
|
print("varify site icon pressed.")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
2022-07-26 16:51:43 +00:00
|
|
|
|
ret = True
|
2023-01-02 06:53:28 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("varify site icon is None.")
|
|
|
|
|
|
|
|
|
|
if is_ticket_number_assigned:
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = "div.button-inner > div > div.button-text"
|
|
|
|
|
el_btn = driver.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
try:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
el_btn.click()
|
|
|
|
|
print("shopping-cart icon pressed.")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("shopping-cart site icon is None.")
|
|
|
|
|
|
|
|
|
|
return is_ticket_number_assigned
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
def urbtix_performance(driver, config_dict):
|
2023-01-02 06:53:28 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
ret = False
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_price_assign_by_bot = False
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = False
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
auto_fill_ticket_number = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
if auto_fill_ticket_number:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
# click price row.
|
|
|
|
|
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"]
|
|
|
|
|
area_keyword_1 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_1"].strip()
|
|
|
|
|
area_keyword_2 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_2"].strip()
|
|
|
|
|
area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip()
|
|
|
|
|
area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip()
|
|
|
|
|
area_keyword_1_and = ""
|
|
|
|
|
area_keyword_2_and = ""
|
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_keyword_1:", area_keyword_1)
|
|
|
|
|
#print("area_keyword_1_and:", area_keyword_1_and)
|
|
|
|
|
print("area_keyword_2:", area_keyword_2)
|
|
|
|
|
#print("area_keyword_2_and:", area_keyword_2_and)
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh, is_price_assign_by_bot = urbtix_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
# try keyword_2
|
|
|
|
|
if len(area_keyword_2) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = urbtix_area_auto_select(driver, area_auto_select_mode, area_keyword_2, area_keyword_2_and)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
if len(area_keyword_3) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = urbtix_area_auto_select(driver, area_auto_select_mode, area_keyword_3, "")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
if len(area_keyword_4) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = urbtix_area_auto_select(driver, area_auto_select_mode, area_keyword_4, "")
|
|
|
|
|
|
|
|
|
|
# un-tested. disable refresh for now.
|
|
|
|
|
is_need_refresh = False
|
|
|
|
|
if is_need_refresh:
|
|
|
|
|
try:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
# choose ticket.
|
|
|
|
|
ticket_number = str(config_dict["ticket_number"])
|
|
|
|
|
is_ticket_number_assigned = urbtix_ticket_number_auto_select(driver, ticket_number)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("ticket_number:", ticket_number)
|
|
|
|
|
print("is_ticket_number_assigned:", is_ticket_number_assigned)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# purpose: date auto select
|
2023-01-03 18:54:42 +00:00
|
|
|
|
def cityline_date_auto_select(driver, auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable):
|
2023-01-02 06:53:28 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
|
|
|
|
ret = False
|
|
|
|
|
matched_blocks = None
|
|
|
|
|
|
|
|
|
|
# clean stop word.
|
|
|
|
|
date_keyword = format_keyword_string(date_keyword)
|
|
|
|
|
date_keyword_and = ""
|
|
|
|
|
|
|
|
|
|
area_list = None
|
|
|
|
|
try:
|
|
|
|
|
#print("try to find cityline area block")
|
|
|
|
|
my_css_selector = "button.date-time-position"
|
|
|
|
|
area_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find #date-time-position date list fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
#PS: some blocks are generate by ajax, not appear at first time.
|
|
|
|
|
formated_area_list = None
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if area_list is not None:
|
|
|
|
|
area_list_count = len(area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("date_list_count:", area_list_count)
|
|
|
|
|
|
|
|
|
|
if area_list_count > 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = []
|
2023-01-03 18:54:42 +00:00
|
|
|
|
# filter list.
|
|
|
|
|
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
if not row.is_enabled():
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
formated_area_list.append(row)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("formated_area_list count:", len(formated_area_list))
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
if len(date_keyword) == 0:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
matched_blocks = formated_area_list
|
2023-01-02 06:53:28 +00:00
|
|
|
|
else:
|
|
|
|
|
# match keyword.
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("start to match keyword:", date_keyword)
|
|
|
|
|
matched_blocks = []
|
|
|
|
|
|
|
|
|
|
row_index = 0
|
2023-01-03 18:54:42 +00:00
|
|
|
|
for row in formated_area_list:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
row_index += 1
|
|
|
|
|
#row_is_enabled=False
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
row_text = ""
|
|
|
|
|
try:
|
|
|
|
|
row_text = row.text
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("get text fail")
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if row_text is None:
|
|
|
|
|
row_text = ""
|
|
|
|
|
|
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
row_text = format_keyword_string(row_text)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("row_text:", row_text)
|
|
|
|
|
|
|
|
|
|
is_match_area = False
|
|
|
|
|
match_area_code = 0
|
|
|
|
|
|
|
|
|
|
if date_keyword in row_text:
|
|
|
|
|
if len(date_keyword_and) == 0:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('keyword_and # is empty, directly match.')
|
|
|
|
|
# keyword #2 is empty, direct append.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 2
|
|
|
|
|
else:
|
|
|
|
|
if date_keyword_and in row_text:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('match keyword_and')
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 3
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('not match keyword_and')
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_match_area:
|
|
|
|
|
matched_blocks.append(row)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if not matched_blocks is None:
|
|
|
|
|
print("after match keyword, found count:", len(matched_blocks))
|
2023-01-02 06:53:28 +00:00
|
|
|
|
else:
|
|
|
|
|
print("not found date-time-position")
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
print("date date-time-position is None")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
target_area = None
|
|
|
|
|
if matched_blocks is not None:
|
|
|
|
|
if len(matched_blocks) > 0:
|
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(matched_blocks)-1
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(matched_blocks)-1)
|
|
|
|
|
|
|
|
|
|
target_area = matched_blocks[target_row_index]
|
|
|
|
|
|
|
|
|
|
if target_area is not None:
|
|
|
|
|
try:
|
|
|
|
|
if target_area.is_enabled():
|
|
|
|
|
target_area.click()
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", target_area)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
# no target.
|
|
|
|
|
if auto_reload_coming_soon_page_enable:
|
|
|
|
|
# auto refresh for date list page.
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if not formated_area_list is None:
|
|
|
|
|
if len(formated_area_list) == 0:
|
|
|
|
|
try:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
return ret
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
# purpose: area auto select
|
|
|
|
|
# return:
|
|
|
|
|
# True: area block appear.
|
|
|
|
|
# False: area block not appear.
|
2022-12-22 17:17:37 +00:00
|
|
|
|
# ps: return is successfully click on the price radio.
|
|
|
|
|
def cityline_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = False
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = False
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
# clean stop word.
|
|
|
|
|
area_keyword_1 = format_keyword_string(area_keyword_1)
|
|
|
|
|
area_keyword_1_and = format_keyword_string(area_keyword_1_and)
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
area_list = None
|
|
|
|
|
try:
|
|
|
|
|
#print("try to find cityline area block")
|
2022-12-22 17:17:37 +00:00
|
|
|
|
my_css_selector = ".form-check"
|
2019-10-01 17:52:13 +00:00
|
|
|
|
area_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
2022-12-22 17:17:37 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find #ticket-price-tbl date list fail")
|
|
|
|
|
print(exc)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = None
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if area_list is not None:
|
|
|
|
|
area_list_count = len(area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_list_count:", area_list_count)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if area_list_count > 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = []
|
|
|
|
|
# filter list.
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = "span.price-limited > span"
|
|
|
|
|
span_price_limited = row.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
if not span_price_limited is None:
|
|
|
|
|
#print("found span limited at idx:", row_index)
|
|
|
|
|
span_i18n_string = str(span_price_limited.get_attribute('data-i18n'))
|
|
|
|
|
if len(span_i18n_string) > 1:
|
|
|
|
|
if 'soldout' in span_i18n_string:
|
|
|
|
|
#print("found span limited soldout at idx:", row_index)
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
formated_area_list.append(row)
|
2023-01-11 00:40:31 +00:00
|
|
|
|
else:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
print("area_list_count is empty.")
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_list_count is None.")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if formated_area_list is not None:
|
|
|
|
|
area_list_count = len(formated_area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("formated_area_list count:", area_list_count)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if area_list_count > 0:
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if len(area_keyword_1) == 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
matched_blocks = formated_area_list
|
2022-12-22 17:17:37 +00:00
|
|
|
|
else:
|
|
|
|
|
# match keyword.
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("start to match keyword:", area_keyword_1)
|
|
|
|
|
print("keyword and:", area_keyword_1_and)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks = []
|
2022-12-22 17:17:37 +00:00
|
|
|
|
|
|
|
|
|
row_index = 0
|
2023-01-03 21:09:17 +00:00
|
|
|
|
for row in formated_area_list:
|
2022-12-22 17:17:37 +00:00
|
|
|
|
row_index += 1
|
|
|
|
|
#row_is_enabled=False
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
row_text = ""
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2022-12-22 17:17:37 +00:00
|
|
|
|
row_text = row.text
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2022-12-22 17:17:37 +00:00
|
|
|
|
print("get text fail")
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if row_text is None:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
row_text = ""
|
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
row_text = format_keyword_string(row_text)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("row_text:", row_text)
|
2022-11-13 04:50:53 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
is_match_area = False
|
|
|
|
|
match_area_code = 0
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if area_keyword_1 in row_text:
|
|
|
|
|
if len(area_keyword_1_and) == 0:
|
|
|
|
|
if show_debug_message:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print('keyword_and is empty, directly match.')
|
2022-12-22 17:17:37 +00:00
|
|
|
|
# keyword #2 is empty, direct append.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 2
|
|
|
|
|
else:
|
|
|
|
|
if area_keyword_1_and in row_text:
|
|
|
|
|
if show_debug_message:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print('match keyword_and')
|
2022-12-22 17:17:37 +00:00
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 3
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print('not match keyword_and')
|
2022-12-22 17:17:37 +00:00
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_match_area:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
matched_blocks.append(row)
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if not matched_blocks is None:
|
|
|
|
|
print("after match keyword, found count:", len(matched_blocks))
|
2019-10-01 17:52:13 +00:00
|
|
|
|
else:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = True
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
print("formated_area_list is empty.")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
target_area = None
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if matched_blocks is not None:
|
|
|
|
|
if len(matched_blocks) > 0:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
target_row_index = len(matched_blocks)-1
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if area_auto_select_mode == CONST_RANDOM:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
target_row_index = random.randint(0,len(matched_blocks)-1)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
target_area = matched_blocks[target_row_index]
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if target_area is not None:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
el_btn = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2022-12-22 17:17:37 +00:00
|
|
|
|
#print("target_area text", target_area.text)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
my_css_selector = "input[type=radio]"
|
2023-01-02 06:53:28 +00:00
|
|
|
|
el_btn = target_area.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
if not el_btn.is_selected():
|
|
|
|
|
el_btn.click()
|
2022-12-22 17:17:37 +00:00
|
|
|
|
ret = True
|
|
|
|
|
else:
|
|
|
|
|
ret = True
|
|
|
|
|
#print("bingo, click target_area radio")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2022-12-22 17:17:37 +00:00
|
|
|
|
print("click target_area radio a link fail")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
return is_need_refresh, ret
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
#[TODO]:
|
|
|
|
|
# double check selected radio matched by keyword/keyword_and.
|
2022-11-18 22:59:34 +00:00
|
|
|
|
def cityline_area_selected_text(driver):
|
2022-12-22 17:17:37 +00:00
|
|
|
|
ret = False
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
def cityline_ticket_number_auto_select(driver, ticket_number):
|
2023-01-03 18:54:42 +00:00
|
|
|
|
selector_string = 'select.select-num'
|
|
|
|
|
by_method = By.CSS_SELECTOR
|
|
|
|
|
return assign_ticket_number_by_select(driver, ticket_number, by_method, selector_string)
|
|
|
|
|
|
|
|
|
|
def ibon_ticket_number_auto_select(driver, ticket_number):
|
2023-01-03 21:09:17 +00:00
|
|
|
|
selector_string = 'table.table > tbody > tr > td > select'
|
2023-01-03 18:54:42 +00:00
|
|
|
|
by_method = By.CSS_SELECTOR
|
|
|
|
|
return assign_ticket_number_by_select(driver, ticket_number, by_method, selector_string)
|
|
|
|
|
|
|
|
|
|
def assign_ticket_number_by_select(driver, ticket_number, by_method, selector_string):
|
2022-11-20 07:57:16 +00:00
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
form_select = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
form_select = driver.find_element(by_method, selector_string)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("find ticket_number select fail")
|
|
|
|
|
print(exc)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
pass
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
select_obj = None
|
|
|
|
|
if form_select is not None:
|
|
|
|
|
is_visible = False
|
2022-11-18 22:59:34 +00:00
|
|
|
|
try:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
is_visible = form_select.is_enabled()
|
2022-11-18 22:59:34 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if is_visible:
|
2022-11-18 22:59:34 +00:00
|
|
|
|
try:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
select_obj = Select(form_select)
|
2022-11-18 22:59:34 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = False
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if not select_obj is None:
|
|
|
|
|
row_text = None
|
2022-11-18 22:59:34 +00:00
|
|
|
|
try:
|
2022-11-20 07:57:16 +00:00
|
|
|
|
row_text = select_obj.first_selected_option.text
|
2022-11-18 22:59:34 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if not row_text is None:
|
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
if row_text != "0":
|
|
|
|
|
# ticket assign.
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = True
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if not is_ticket_number_assigned:
|
|
|
|
|
is_ticket_number_assigned = tixcraft_ticket_number_auto_fill(driver, select_obj, ticket_number)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("ticket_number assigned by previous action.")
|
2022-11-18 22:59:34 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
return is_ticket_number_assigned
|
|
|
|
|
|
|
|
|
|
def cityline_purchase_button_press(driver, config_dict):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
ret = False
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
date_auto_select_mode = config_dict["tixcraft"]["date_auto_select"]["mode"]
|
|
|
|
|
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
|
2023-01-03 18:54:42 +00:00
|
|
|
|
auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("date_keyword:", date_keyword)
|
|
|
|
|
is_date_assign_by_bot = cityline_date_auto_select(driver, date_auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
el_btn = None
|
2022-12-22 17:17:37 +00:00
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
el_btn = driver.find_element(By.CSS_SELECTOR, 'button.purchase-btn')
|
2022-12-22 17:17:37 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find next button fail")
|
2023-01-03 18:54:42 +00:00
|
|
|
|
#print(exc)
|
|
|
|
|
pass
|
2022-12-22 17:17:37 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if el_btn is not None:
|
|
|
|
|
print("bingo, found next button")
|
|
|
|
|
try:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
el_btn.click()
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("press next button fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-18 22:59:34 +00:00
|
|
|
|
def cityline_next_button_press(driver):
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = False
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
el_nav = None
|
|
|
|
|
el_btn = None
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
el_nav = driver.find_element(By.CSS_SELECTOR, '.puchase-bottom')
|
|
|
|
|
el_btn = driver.find_element(By.CSS_SELECTOR, '#expressPurchaseBtn')
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print("find next button fail...")
|
2019-10-01 17:52:13 +00:00
|
|
|
|
print(exc)
|
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if el_btn is not None and el_nav is not None:
|
|
|
|
|
print("bingo, found next button, start to press")
|
|
|
|
|
try:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
#el_btn.click()
|
|
|
|
|
builder = ActionChains(driver)
|
|
|
|
|
builder.move_to_element(el_nav)
|
|
|
|
|
builder.click(el_btn)
|
|
|
|
|
builder.perform()
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click next button fail...")
|
|
|
|
|
print(exc)
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
def cityline_performance(driver, config_dict):
|
|
|
|
|
show_debug_message = True # debug.
|
2023-01-02 06:53:28 +00:00
|
|
|
|
show_debug_message = False # online
|
2022-11-23 04:39:46 +00:00
|
|
|
|
|
2022-12-22 17:17:37 +00:00
|
|
|
|
is_price_assign_by_bot = False
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = False
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
|
|
|
|
auto_fill_ticket_number = True
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if auto_fill_ticket_number:
|
|
|
|
|
# click price row.
|
2023-01-02 06:53:28 +00:00
|
|
|
|
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"]
|
|
|
|
|
area_keyword_1 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_1"].strip()
|
|
|
|
|
area_keyword_2 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_2"].strip()
|
|
|
|
|
area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip()
|
|
|
|
|
area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip()
|
|
|
|
|
area_keyword_1_and = ""
|
|
|
|
|
area_keyword_2_and = ""
|
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_keyword_1:", area_keyword_1)
|
|
|
|
|
#print("area_keyword_1_and:", area_keyword_1_and)
|
2023-01-04 12:02:55 +00:00
|
|
|
|
print("area_keyword_2:", area_keyword_2)
|
|
|
|
|
#print("area_keyword_2_and:", area_keyword_2_and)
|
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
# PS: cityline price default value is selected at the first option.
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh, is_price_assign_by_bot = cityline_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and)
|
2022-12-22 17:17:37 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
# try keyword_2
|
|
|
|
|
if len(area_keyword_2) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = cityline_area_auto_select(driver, area_auto_select_mode, area_keyword_2, area_keyword_2_and)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
if len(area_keyword_3) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = cityline_area_auto_select(driver, area_auto_select_mode, area_keyword_3, "")
|
2023-01-02 06:53:28 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
if len(area_keyword_4) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = cityline_area_auto_select(driver, area_auto_select_mode, area_keyword_4, "")
|
|
|
|
|
|
|
|
|
|
# un-tested. disable refresh for now.
|
|
|
|
|
is_need_refresh = False
|
|
|
|
|
if is_need_refresh:
|
|
|
|
|
try:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
# choose ticket.
|
2022-11-18 22:59:34 +00:00
|
|
|
|
ticket_number = str(config_dict["ticket_number"])
|
2023-01-02 06:53:28 +00:00
|
|
|
|
is_ticket_number_assigned = cityline_ticket_number_auto_select(driver, ticket_number)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("ticket_number:", ticket_number)
|
2023-01-02 06:53:28 +00:00
|
|
|
|
print("is_ticket_number_assigned:", is_ticket_number_assigned)
|
2022-11-20 07:57:16 +00:00
|
|
|
|
|
2023-01-02 06:53:28 +00:00
|
|
|
|
if is_ticket_number_assigned:
|
|
|
|
|
auto_press_next_step_button = True
|
2022-11-20 07:57:16 +00:00
|
|
|
|
if auto_press_next_step_button:
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
#[TODO]:
|
|
|
|
|
# double check selected radio matched by keyword/keyword_and.
|
|
|
|
|
# cityline_area_selected_text(driver)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_price_assign_by_bot:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
for i in range(2):
|
2022-12-22 17:17:37 +00:00
|
|
|
|
click_ret = cityline_next_button_press(driver)
|
|
|
|
|
if click_ret:
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
def ibon_date_auto_select(driver, auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
ret = False
|
2023-01-03 18:54:42 +00:00
|
|
|
|
matched_blocks = None
|
|
|
|
|
|
|
|
|
|
# clean stop word.
|
|
|
|
|
date_keyword = format_keyword_string(date_keyword)
|
|
|
|
|
date_keyword_and = ""
|
|
|
|
|
|
|
|
|
|
area_list = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
#print("try to find cityline area block")
|
|
|
|
|
my_css_selector = "div.grid-wrap.event.table-wrap > div > div > div.tr"
|
|
|
|
|
area_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
2022-12-27 15:38:13 +00:00
|
|
|
|
except Exception as exc:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
print("find #date-time-position date list fail")
|
|
|
|
|
print(exc)
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
#PS: some blocks are generate by ajax, not appear at first time.
|
|
|
|
|
formated_area_list = None
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if area_list is not None:
|
|
|
|
|
area_list_count = len(area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("date_list_count:", area_list_count)
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if area_list_count > 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = []
|
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
# filter list.
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
my_css_selector = "button"
|
|
|
|
|
el_btn = row.find_element(By.TAG_NAME, my_css_selector)
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
if not el_btn.is_enabled():
|
|
|
|
|
#print("row's button disabled!")
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print(exc)
|
|
|
|
|
pass
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if row_is_enabled:
|
|
|
|
|
formated_area_list.append(row)
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if len(date_keyword) == 0:
|
|
|
|
|
matched_blocks = formated_area_list
|
|
|
|
|
else:
|
|
|
|
|
# match keyword.
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("start to match keyword:", date_keyword)
|
|
|
|
|
matched_blocks = []
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
row_index = 0
|
|
|
|
|
for row in formated_area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
row_text = ""
|
|
|
|
|
try:
|
|
|
|
|
row_text = row.text
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("get text fail")
|
|
|
|
|
break
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if row_text is None:
|
|
|
|
|
row_text = ""
|
2022-12-27 15:38:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
row_text = format_keyword_string(row_text)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("row_text:", row_text)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
is_match_area = False
|
|
|
|
|
match_area_code = 0
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if date_keyword in row_text:
|
|
|
|
|
if len(date_keyword_and) == 0:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('keyword_and # is empty, directly match.')
|
|
|
|
|
# keyword #2 is empty, direct append.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 2
|
|
|
|
|
else:
|
|
|
|
|
if date_keyword_and in row_text:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('match keyword_and')
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 3
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('not match keyword_and')
|
|
|
|
|
pass
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if is_match_area:
|
|
|
|
|
matched_blocks.append(row)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if not matched_blocks is None:
|
|
|
|
|
print("after match keyword, found count:", len(matched_blocks))
|
2023-01-03 18:54:42 +00:00
|
|
|
|
else:
|
|
|
|
|
print("not found date-time-position")
|
2022-11-16 15:43:53 +00:00
|
|
|
|
pass
|
2023-01-03 18:54:42 +00:00
|
|
|
|
else:
|
|
|
|
|
print("date date-time-position is None")
|
|
|
|
|
pass
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
target_area = None
|
|
|
|
|
if matched_blocks is not None:
|
|
|
|
|
if len(matched_blocks) > 0:
|
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(matched_blocks)-1
|
|
|
|
|
|
|
|
|
|
if auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(matched_blocks)-1)
|
|
|
|
|
|
|
|
|
|
target_area = matched_blocks[target_row_index]
|
|
|
|
|
|
|
|
|
|
if target_area is not None:
|
|
|
|
|
el_btn = None
|
2022-11-16 15:43:53 +00:00
|
|
|
|
try:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
my_css_selector = "button.btn"
|
|
|
|
|
el_btn = target_area.find_element(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
try:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
el_btn.click()
|
|
|
|
|
print("buy icon pressed.")
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
# no target to click.
|
|
|
|
|
if auto_reload_coming_soon_page_enable:
|
|
|
|
|
# auto refresh for date list page.
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if not formated_area_list is None:
|
|
|
|
|
if len(formated_area_list) == 0:
|
|
|
|
|
try:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-03 18:54:42 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
def ibon_activity_info(driver, config_dict):
|
|
|
|
|
show_debug_message = True # debug.
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = False # online
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
date_auto_select_mode = config_dict["tixcraft"]["date_auto_select"]["mode"]
|
|
|
|
|
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
|
|
|
|
|
auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("date_keyword:", date_keyword)
|
|
|
|
|
print("auto_reload_coming_soon_page_enable:", auto_reload_coming_soon_page_enable)
|
|
|
|
|
is_date_assign_by_bot = ibon_date_auto_select(driver, date_auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable)
|
|
|
|
|
|
|
|
|
|
return is_date_assign_by_bot
|
|
|
|
|
|
|
|
|
|
def ibon_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and):
|
|
|
|
|
show_debug_message = True # debug.
|
|
|
|
|
show_debug_message = False # online
|
|
|
|
|
|
|
|
|
|
ret = False
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = False
|
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
matched_blocks = None
|
|
|
|
|
|
|
|
|
|
# clean stop word.
|
|
|
|
|
area_keyword_1 = format_keyword_string(area_keyword_1)
|
|
|
|
|
area_keyword_1_and = format_keyword_string(area_keyword_1_and)
|
|
|
|
|
|
|
|
|
|
area_list = None
|
|
|
|
|
try:
|
|
|
|
|
#print("try to find cityline area block")
|
|
|
|
|
my_css_selector = "div.col-md-5 > table > tbody > tr"
|
|
|
|
|
area_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find #ticket-price-tbl date list fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = None
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if area_list is not None:
|
|
|
|
|
area_list_count = len(area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_list_count:", area_list_count)
|
|
|
|
|
|
|
|
|
|
if area_list_count > 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
formated_area_list = []
|
|
|
|
|
# filter list.
|
|
|
|
|
row_index = 0
|
|
|
|
|
for row in area_list:
|
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
try:
|
|
|
|
|
button_class_string = str(row.get_attribute('class'))
|
|
|
|
|
if len(button_class_string) > 1:
|
|
|
|
|
if 'disabled' in button_class_string:
|
|
|
|
|
row_is_enabled=False
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if 'sold-out' in button_class_string:
|
|
|
|
|
row_is_enabled=False
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if 'selected' in button_class_string:
|
|
|
|
|
# someone is selected. skip this process.
|
|
|
|
|
row_is_enabled=False
|
|
|
|
|
matched_blocks = []
|
|
|
|
|
ret = True
|
|
|
|
|
break
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
formated_area_list.append(row)
|
2023-01-11 00:40:31 +00:00
|
|
|
|
else:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
print("area_list_count is empty.")
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_list_count is None.")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if formated_area_list is not None:
|
|
|
|
|
area_list_count = len(formated_area_list)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("formated_area_list count:", area_list_count)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if area_list_count > 0:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if len(area_keyword_1) == 0:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
matched_blocks = formated_area_list
|
2023-01-03 18:54:42 +00:00
|
|
|
|
else:
|
|
|
|
|
# match keyword.
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("start to match keyword:", area_keyword_1)
|
|
|
|
|
print("keyword and:", area_keyword_1_and)
|
|
|
|
|
matched_blocks = []
|
|
|
|
|
|
|
|
|
|
row_index = 0
|
2023-01-03 21:09:17 +00:00
|
|
|
|
for row in formated_area_list:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
row_index += 1
|
|
|
|
|
row_is_enabled=True
|
|
|
|
|
if row_is_enabled:
|
|
|
|
|
row_text = ""
|
|
|
|
|
try:
|
|
|
|
|
row_text = row.text
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("get text fail")
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if row_text is None:
|
|
|
|
|
row_text = ""
|
|
|
|
|
|
|
|
|
|
if len(row_text) > 0:
|
|
|
|
|
row_text = format_keyword_string(row_text)
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("row_text:", row_text)
|
|
|
|
|
|
|
|
|
|
is_match_area = False
|
|
|
|
|
match_area_code = 0
|
|
|
|
|
|
|
|
|
|
if area_keyword_1 in row_text:
|
|
|
|
|
if len(area_keyword_1_and) == 0:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('keyword_and is empty, directly match.')
|
|
|
|
|
# keyword #2 is empty, direct append.
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 2
|
|
|
|
|
else:
|
|
|
|
|
if area_keyword_1_and in row_text:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('match keyword_and')
|
|
|
|
|
is_match_area = True
|
|
|
|
|
match_area_code = 3
|
|
|
|
|
else:
|
|
|
|
|
if show_debug_message:
|
|
|
|
|
print('not match keyword_and')
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_match_area:
|
|
|
|
|
matched_blocks.append(row)
|
|
|
|
|
|
|
|
|
|
if show_debug_message:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if not matched_blocks is None:
|
|
|
|
|
print("after match keyword, found count:", len(matched_blocks))
|
2023-01-03 18:54:42 +00:00
|
|
|
|
else:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = True
|
2023-01-04 12:02:55 +00:00
|
|
|
|
if show_debug_message:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
print("formated_area_list is empty.")
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
target_area = None
|
|
|
|
|
if matched_blocks is not None:
|
|
|
|
|
if len(matched_blocks) > 0:
|
|
|
|
|
target_row_index = 0
|
|
|
|
|
|
|
|
|
|
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
|
|
|
|
|
target_row_index = len(matched_blocks)-1
|
|
|
|
|
|
|
|
|
|
if area_auto_select_mode == CONST_RANDOM:
|
|
|
|
|
target_row_index = random.randint(0,len(matched_blocks)-1)
|
|
|
|
|
|
|
|
|
|
target_area = matched_blocks[target_row_index]
|
|
|
|
|
|
|
|
|
|
if target_area is not None:
|
|
|
|
|
try:
|
|
|
|
|
if target_area.is_enabled():
|
|
|
|
|
target_area.click()
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click target_area link fail")
|
|
|
|
|
print(exc)
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", target_area)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
return is_need_refresh, ret
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ibon_performance(driver, config_dict):
|
|
|
|
|
show_debug_message = True # debug.
|
2023-01-04 12:02:55 +00:00
|
|
|
|
show_debug_message = False # online
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
is_price_assign_by_bot = False
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = False
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
auto_fill_ticket_number = True
|
|
|
|
|
if auto_fill_ticket_number:
|
|
|
|
|
# click price row.
|
|
|
|
|
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"]
|
|
|
|
|
area_keyword_1 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_1"].strip()
|
|
|
|
|
area_keyword_2 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_2"].strip()
|
|
|
|
|
area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip()
|
|
|
|
|
area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip()
|
|
|
|
|
area_keyword_1_and = ""
|
|
|
|
|
area_keyword_2_and = ""
|
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if show_debug_message:
|
|
|
|
|
print("area_keyword_1:", area_keyword_1)
|
|
|
|
|
#print("area_keyword_1_and:", area_keyword_1_and)
|
|
|
|
|
print("area_keyword_2:", area_keyword_2)
|
|
|
|
|
#print("area_keyword_2_and:", area_keyword_2_and)
|
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh = False
|
2023-01-03 21:09:17 +00:00
|
|
|
|
if not is_price_assign_by_bot:
|
2023-01-11 00:40:31 +00:00
|
|
|
|
is_need_refresh, is_price_assign_by_bot = ibon_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
# try keyword_2
|
|
|
|
|
if len(area_keyword_2) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = ibon_area_auto_select(driver, area_auto_select_mode, area_keyword_2, area_keyword_2_and)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
if len(area_keyword_3) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = ibon_area_auto_select(driver, area_auto_select_mode, area_keyword_3, "")
|
|
|
|
|
if not is_need_refresh:
|
|
|
|
|
if not is_price_assign_by_bot:
|
|
|
|
|
if len(area_keyword_4) > 0:
|
|
|
|
|
is_need_refresh, is_price_assign_by_bot = ibon_area_auto_select(driver, area_auto_select_mode, area_keyword_4, "")
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2023-01-11 00:40:31 +00:00
|
|
|
|
if is_need_refresh:
|
|
|
|
|
try:
|
|
|
|
|
driver.refresh()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2023-01-03 21:09:17 +00:00
|
|
|
|
return is_price_assign_by_bot
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
def ibon_purchase_button_press(driver):
|
|
|
|
|
ret = False
|
|
|
|
|
|
|
|
|
|
el_btn = None
|
|
|
|
|
try:
|
|
|
|
|
el_btn = driver.find_element(By.CSS_SELECTOR, '#ticket-wrap > a.btn')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("find next button fail...")
|
|
|
|
|
print(exc)
|
|
|
|
|
|
|
|
|
|
if el_btn is not None:
|
|
|
|
|
print("bingo, found next button, start to press")
|
|
|
|
|
try:
|
|
|
|
|
if el_btn.is_enabled():
|
|
|
|
|
el_btn.click()
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print("click next button fail...")
|
|
|
|
|
print(exc)
|
|
|
|
|
# use plan B
|
|
|
|
|
try:
|
|
|
|
|
print("force to click by js.")
|
|
|
|
|
driver.execute_script("arguments[0].click();", el_btn)
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
def facebook_login(driver, account):
|
|
|
|
|
ret = False
|
|
|
|
|
el_email = None
|
|
|
|
|
try:
|
|
|
|
|
el_email = driver.find_element(By.CSS_SELECTOR, '#email')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
is_visible = False
|
|
|
|
|
if el_email is not None:
|
|
|
|
|
try:
|
|
|
|
|
if el_email.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
is_email_sent = False
|
|
|
|
|
if is_visible:
|
|
|
|
|
try:
|
|
|
|
|
inputed_text = el_email.get_attribute('value')
|
|
|
|
|
if inputed_text is not None:
|
|
|
|
|
if len(inputed_text) == 0:
|
|
|
|
|
el_email.send_keys(account)
|
|
|
|
|
is_email_sent = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
el_pass = None
|
|
|
|
|
if is_email_sent:
|
|
|
|
|
try:
|
|
|
|
|
el_pass = driver.find_element(By.CSS_SELECTOR, '#pass')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
is_visible = False
|
|
|
|
|
if el_pass is not None:
|
|
|
|
|
try:
|
|
|
|
|
if el_pass.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
|
|
|
|
try:
|
|
|
|
|
el_pass.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
def kktix_login(driver, account):
|
|
|
|
|
ret = False
|
|
|
|
|
el_email = None
|
|
|
|
|
try:
|
|
|
|
|
el_email = driver.find_element(By.CSS_SELECTOR, '#user_login')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("find #email fail")
|
|
|
|
|
#print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
is_visible = False
|
|
|
|
|
if el_email is not None:
|
|
|
|
|
try:
|
|
|
|
|
if el_email.is_enabled():
|
|
|
|
|
is_visible = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
is_email_sent = False
|
|
|
|
|
if is_visible:
|
|
|
|
|
try:
|
|
|
|
|
inputed_text = el_email.get_attribute('value')
|
|
|
|
|
if inputed_text is not None:
|
|
|
|
|
if len(inputed_text) == 0:
|
|
|
|
|
el_email.send_keys(account)
|
|
|
|
|
is_email_sent = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
el_pass = None
|
|
|
|
|
if is_email_sent:
|
|
|
|
|
try:
|
|
|
|
|
el_pass = driver.find_element(By.CSS_SELECTOR, '#user_password')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
is_visible = False
|
|
|
|
|
if el_pass is not None:
|
|
|
|
|
try:
|
|
|
|
|
if el_pass.is_enabled():
|
|
|
|
|
is_visible = True
|
2022-11-16 15:43:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if is_visible:
|
|
|
|
|
try:
|
|
|
|
|
el_pass.click()
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
return ret
|
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
def check_and_play_sound_for_captcha(config_dict):
|
|
|
|
|
play_captcha_sound = config_dict["advanced"]["play_captcha_sound"]["enable"]
|
|
|
|
|
captcha_sound_filename = config_dict["advanced"]["play_captcha_sound"]["filename"].strip()
|
|
|
|
|
if play_captcha_sound:
|
|
|
|
|
app_root = get_app_root()
|
|
|
|
|
captcha_sound_filename = os.path.join(app_root, captcha_sound_filename)
|
|
|
|
|
play_mp3_async(captcha_sound_filename)
|
|
|
|
|
|
2022-11-17 18:17:19 +00:00
|
|
|
|
def play_mp3_async(sound_filename):
|
2022-11-16 15:43:53 +00:00
|
|
|
|
import threading
|
2022-11-17 18:17:19 +00:00
|
|
|
|
threading.Thread(target=play_mp3, args=(sound_filename,), daemon=True).start()
|
|
|
|
|
|
|
|
|
|
def play_mp3(sound_filename):
|
2022-11-16 15:43:53 +00:00
|
|
|
|
from playsound import playsound
|
|
|
|
|
try:
|
2022-11-17 18:17:19 +00:00
|
|
|
|
playsound(sound_filename)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
msg=str(exc)
|
|
|
|
|
print("play sound exeption:", msg)
|
2022-11-17 18:17:19 +00:00
|
|
|
|
if platform.system() == 'Windows':
|
|
|
|
|
import winsound
|
|
|
|
|
try:
|
|
|
|
|
winsound.PlaySound(sound_filename, winsound.SND_FILENAME)
|
|
|
|
|
except Exception as exc2:
|
|
|
|
|
pass
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
|
|
|
|
# purpose: check alert poped.
|
|
|
|
|
# PS: current version not enable...
|
|
|
|
|
def check_pop_alert(driver):
|
|
|
|
|
is_alert_popup = False
|
|
|
|
|
|
|
|
|
|
# https://stackoverflow.com/questions/57481723/is-there-a-change-in-the-handling-of-unhandled-alert-in-chromedriver-and-chrome
|
2023-01-07 21:43:30 +00:00
|
|
|
|
default_close_alert_text = [""]
|
2022-11-16 15:43:53 +00:00
|
|
|
|
if len(default_close_alert_text) > 0:
|
|
|
|
|
try:
|
|
|
|
|
alert = None
|
|
|
|
|
if not driver is None:
|
|
|
|
|
alert = driver.switch_to.alert
|
|
|
|
|
if not alert is None:
|
2023-01-07 21:43:30 +00:00
|
|
|
|
alert_text = str(alert.text)
|
|
|
|
|
if not alert_text is None:
|
2022-11-16 15:43:53 +00:00
|
|
|
|
is_match_auto_close_text = False
|
|
|
|
|
for txt in default_close_alert_text:
|
|
|
|
|
if len(txt) > 0:
|
|
|
|
|
if txt in alert.text:
|
|
|
|
|
is_match_auto_close_text = True
|
2023-01-07 21:43:30 +00:00
|
|
|
|
else:
|
|
|
|
|
is_match_auto_close_text = True
|
|
|
|
|
#print("is_match_auto_close_text:", is_match_auto_close_text)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
#print("alert3 text:", alert.text)
|
|
|
|
|
|
|
|
|
|
if is_match_auto_close_text:
|
|
|
|
|
alert.accept()
|
|
|
|
|
print("alert3 accepted")
|
|
|
|
|
|
|
|
|
|
is_alert_popup = True
|
|
|
|
|
else:
|
|
|
|
|
print("alert3 not detected")
|
|
|
|
|
except NoAlertPresentException as exc1:
|
|
|
|
|
#logger.error('NoAlertPresentException for alert')
|
|
|
|
|
pass
|
|
|
|
|
except NoSuchWindowException:
|
2023-01-07 21:43:30 +00:00
|
|
|
|
pass
|
2022-11-16 15:43:53 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
logger.error('Exception2 for alert')
|
|
|
|
|
logger.error(exc, exc_info=True)
|
|
|
|
|
|
|
|
|
|
return is_alert_popup
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-20 07:57:16 +00:00
|
|
|
|
def list_all_cookies(driver):
|
|
|
|
|
all_cookies=driver.get_cookies();
|
|
|
|
|
cookies_dict = {}
|
|
|
|
|
for cookie in all_cookies:
|
|
|
|
|
cookies_dict[cookie['name']] = cookie['value']
|
|
|
|
|
print(cookies_dict)
|
|
|
|
|
|
2023-01-13 19:01:47 +00:00
|
|
|
|
def tixcraft_main(driver, url, config_dict, is_verifyCode_editing, ocr, Captcha_Browser):
|
|
|
|
|
home_url_list = ['https://tixcraft.com/','https://www.tixcraft.com/','https://indievox.com/','https://www.indievox.com/']
|
|
|
|
|
for each_url in home_url_list:
|
|
|
|
|
if each_url == url:
|
|
|
|
|
tixcraft_home(driver)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2023-01-14 05:26:42 +00:00
|
|
|
|
if config_dict["ocr_captcha"]["enable"]:
|
|
|
|
|
domain_name = url.split('/')[2]
|
|
|
|
|
#PS: need set cookies once, if user change domain.
|
|
|
|
|
if not Captcha_Browser is None:
|
|
|
|
|
Captcha_Browser.Set_cookies(driver.get_cookies())
|
|
|
|
|
Captcha_Browser.Set_Domain(domain_name)
|
|
|
|
|
|
|
|
|
|
break
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
2023-01-11 13:58:55 +00:00
|
|
|
|
if "/activity/detail/" in url:
|
|
|
|
|
is_redirected = tixcraft_redirect(driver, url)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
is_date_selected = False
|
2023-01-11 13:58:55 +00:00
|
|
|
|
if "/activity/game/" in url:
|
|
|
|
|
date_auto_select_enable = config_dict["tixcraft"]["date_auto_select"]["enable"]
|
|
|
|
|
if date_auto_select_enable:
|
|
|
|
|
is_date_selected = tixcraft_date_auto_select(driver, url, config_dict)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
# choose area
|
2023-01-11 13:58:55 +00:00
|
|
|
|
if '/ticket/area/' in url:
|
|
|
|
|
area_auto_select_enable = config_dict["tixcraft"]["area_auto_select"]["enable"]
|
|
|
|
|
if area_auto_select_enable:
|
|
|
|
|
tixcraft_area_auto_select(driver, url, config_dict)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
if '/ticket/verify/' in url:
|
|
|
|
|
presale_code = config_dict["tixcraft"]["presale_code"]
|
|
|
|
|
tixcraft_verify(driver, presale_code)
|
|
|
|
|
|
|
|
|
|
# main app, to select ticket number.
|
|
|
|
|
if '/ticket/ticket/' in url:
|
|
|
|
|
if not is_verifyCode_editing:
|
2023-01-13 19:01:47 +00:00
|
|
|
|
domain_name = url.split('/')[2]
|
|
|
|
|
is_verifyCode_editing = tixcraft_ticket_main(driver, config_dict, ocr, Captcha_Browser, domain_name)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
else:
|
|
|
|
|
is_verifyCode_editing = False
|
|
|
|
|
|
|
|
|
|
return is_verifyCode_editing
|
|
|
|
|
|
|
|
|
|
def kktix_main(driver, url, config_dict, answer_index, kktix_register_status_last):
|
|
|
|
|
auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"]
|
|
|
|
|
kktix_account = config_dict["advanced"]["kktix_account"]
|
|
|
|
|
|
|
|
|
|
is_url_contain_sign_in = False
|
|
|
|
|
# fix https://kktix.com/users/sign_in?back_to=https://kktix.com/events/xxxx and registerStatus: SOLD_OUT cause page refresh.
|
|
|
|
|
if '/users/sign_in?' in url:
|
|
|
|
|
if len(kktix_account) > 4:
|
|
|
|
|
kktix_login(driver, kktix_account)
|
|
|
|
|
is_url_contain_sign_in = True
|
|
|
|
|
|
|
|
|
|
if not is_url_contain_sign_in:
|
|
|
|
|
if '/registrations/new' in url:
|
|
|
|
|
answer_index, kktix_register_status_last = kktix_reg_new(driver, url, answer_index, kktix_register_status_last, config_dict)
|
|
|
|
|
else:
|
|
|
|
|
is_event_page = False
|
|
|
|
|
if '/events/' in url:
|
|
|
|
|
# ex: https://xxx.kktix.cc/events/xxx-copy-1
|
|
|
|
|
if len(url.split('/'))<=5:
|
|
|
|
|
is_event_page = True
|
|
|
|
|
|
|
|
|
|
if is_event_page:
|
|
|
|
|
if auto_press_next_step_button:
|
|
|
|
|
# pass switch check.
|
|
|
|
|
#print("should press next here.")
|
|
|
|
|
kktix_events_press_next_button(driver)
|
|
|
|
|
|
|
|
|
|
answer_index = -1
|
|
|
|
|
kktix_register_status_last = None
|
|
|
|
|
return answer_index, kktix_register_status_last
|
|
|
|
|
|
|
|
|
|
def famiticket_main(driver, url, config_dict):
|
2023-01-04 12:02:55 +00:00
|
|
|
|
try:
|
|
|
|
|
window_handles_count = len(driver.window_handles)
|
|
|
|
|
if window_handles_count > 1:
|
|
|
|
|
driver.switch_to.window(driver.window_handles[0])
|
|
|
|
|
driver.close()
|
|
|
|
|
driver.switch_to.window(driver.window_handles[0])
|
|
|
|
|
except Exception as excSwithFail:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if '/Home/Activity/Info/' in url:
|
|
|
|
|
fami_activity(driver)
|
|
|
|
|
if '/Sales/Home/Index/' in url:
|
|
|
|
|
fami_home(driver, url, config_dict)
|
|
|
|
|
|
|
|
|
|
def urbtix_main(driver, url, config_dict):
|
|
|
|
|
# http://msg.urbtix.hk
|
2023-01-11 13:58:55 +00:00
|
|
|
|
waiting_for_access_url = ['/session/landing-timer/','msg.urbtix.hk','busy.urbtix.hk']
|
2023-01-11 00:40:31 +00:00
|
|
|
|
for waiting_url in waiting_for_access_url:
|
|
|
|
|
if waiting_url in url:
|
|
|
|
|
# delay to avoid ip block.
|
2023-01-11 17:41:53 +00:00
|
|
|
|
time.sleep(1.0)
|
2023-01-11 00:40:31 +00:00
|
|
|
|
try:
|
|
|
|
|
driver.get('https://www.urbtix.hk/')
|
|
|
|
|
except Exception as exec1:
|
|
|
|
|
pass
|
2023-01-03 18:54:42 +00:00
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if '/logout?' in url:
|
|
|
|
|
try:
|
|
|
|
|
driver.get('https://www.urbtix.hk/')
|
|
|
|
|
except Exception as exec1:
|
|
|
|
|
pass
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# https://www.urbtix.hk/event-detail/00000/
|
|
|
|
|
if '/event-detail/' in url:
|
|
|
|
|
date_auto_select_enable = config_dict["tixcraft"]["date_auto_select"]["enable"]
|
|
|
|
|
if date_auto_select_enable:
|
|
|
|
|
is_event_page = False
|
|
|
|
|
if len(url.split('/'))<=6:
|
|
|
|
|
is_event_page = True
|
|
|
|
|
urbtix_purchase_ticket(driver, config_dict)
|
|
|
|
|
|
|
|
|
|
# https://www.urbtix.hk/performance-detail/?eventId=00000&performanceId=00000
|
2023-01-04 12:02:55 +00:00
|
|
|
|
is_performace_page = False
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if '/performance-detail/?eventId=' in url:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
is_performace_page = True
|
|
|
|
|
|
|
|
|
|
if 'performance-detail?eventId' in url:
|
|
|
|
|
is_performace_page = True
|
|
|
|
|
|
|
|
|
|
if is_performace_page:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
area_auto_select_enable = config_dict["tixcraft"]["area_auto_select"]["enable"]
|
|
|
|
|
if area_auto_select_enable:
|
|
|
|
|
urbtix_performance(driver, config_dict)
|
|
|
|
|
|
2023-01-04 12:02:55 +00:00
|
|
|
|
def check_modal_dialog_popup(driver):
|
|
|
|
|
ret = False
|
|
|
|
|
|
|
|
|
|
el_div = None
|
|
|
|
|
try:
|
|
|
|
|
el_div = driver.find_element(By.CSS_SELECTOR, 'div.modal-dialog > div.modal-content')
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
#print("find modal-dialog fail")
|
|
|
|
|
#print(exc)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if el_div is not None:
|
|
|
|
|
#print("bingo, found modal-dialog")
|
|
|
|
|
try:
|
|
|
|
|
if el_div.is_enabled():
|
|
|
|
|
if el_div.is_displayed():
|
|
|
|
|
ret = True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
def cityline_main(driver, url, config_dict):
|
|
|
|
|
# https://www.cityline.com/Login.html?targetUrl=https%3A%2F%2F
|
|
|
|
|
# ignore url redirect
|
|
|
|
|
if '/Login.html' in url:
|
|
|
|
|
return
|
|
|
|
|
|
2023-01-05 06:44:45 +00:00
|
|
|
|
# https://msg.cityline.com/
|
|
|
|
|
if 'msg.cityline.com' in url:
|
|
|
|
|
try:
|
|
|
|
|
driver.execute_script("goEvent();")
|
|
|
|
|
except Exception as exec1:
|
|
|
|
|
pass
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
try:
|
|
|
|
|
window_handles_count = len(driver.window_handles)
|
|
|
|
|
if window_handles_count > 1:
|
|
|
|
|
driver.switch_to.window(driver.window_handles[0])
|
|
|
|
|
driver.close()
|
|
|
|
|
driver.switch_to.window(driver.window_handles[0])
|
|
|
|
|
except Exception as excSwithFail:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if '/eventDetail?' in url:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
is_modal_dialog_popup = check_modal_dialog_popup(driver)
|
|
|
|
|
if is_modal_dialog_popup:
|
|
|
|
|
print("is_modal_dialog_popup! skip...")
|
|
|
|
|
else:
|
|
|
|
|
date_auto_select_enable = config_dict["tixcraft"]["date_auto_select"]["enable"]
|
|
|
|
|
if date_auto_select_enable:
|
|
|
|
|
cityline_purchase_button_press(driver, config_dict)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
if '/performance?' in url:
|
2023-01-04 12:02:55 +00:00
|
|
|
|
is_modal_dialog_popup = check_modal_dialog_popup(driver)
|
|
|
|
|
if is_modal_dialog_popup:
|
|
|
|
|
print("is_modal_dialog_popup! skip...")
|
|
|
|
|
else:
|
|
|
|
|
area_auto_select_enable = config_dict["tixcraft"]["area_auto_select"]["enable"]
|
|
|
|
|
if area_auto_select_enable:
|
|
|
|
|
cityline_performance(driver, config_dict)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
|
|
|
|
|
def ibon_main(driver, url, config_dict):
|
|
|
|
|
#https://ticket.ibon.com.tw/ActivityInfo/Details/0000?pattern=entertainment
|
|
|
|
|
if '/ActivityInfo/Details/' in url:
|
|
|
|
|
is_event_page = False
|
|
|
|
|
if len(url.split('/'))<=6:
|
|
|
|
|
is_event_page = True
|
|
|
|
|
|
|
|
|
|
if is_event_page:
|
|
|
|
|
date_auto_select_enable = config_dict["tixcraft"]["date_auto_select"]["enable"]
|
|
|
|
|
if date_auto_select_enable:
|
|
|
|
|
ibon_activity_info(driver, config_dict)
|
|
|
|
|
|
|
|
|
|
# https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?PERFORMANCE_ID=0000
|
|
|
|
|
if '/application/UTK02/' in url and '.aspx?PERFORMANCE_ID=' in url:
|
|
|
|
|
is_event_page = False
|
|
|
|
|
if len(url.split('/'))<=6:
|
|
|
|
|
is_event_page = True
|
|
|
|
|
|
|
|
|
|
if is_event_page:
|
|
|
|
|
area_auto_select_enable = config_dict["tixcraft"]["area_auto_select"]["enable"]
|
|
|
|
|
if area_auto_select_enable:
|
|
|
|
|
if 'PERFORMANCE_PRICE_AREA_ID=' in url:
|
|
|
|
|
# step 2: assign ticket number.
|
|
|
|
|
ticket_number = str(config_dict["ticket_number"])
|
|
|
|
|
is_ticket_number_assigned = ibon_ticket_number_auto_select(driver, ticket_number)
|
|
|
|
|
if is_ticket_number_assigned:
|
2023-01-03 21:09:17 +00:00
|
|
|
|
click_ret = ibon_purchase_button_press(driver)
|
2023-01-03 18:54:42 +00:00
|
|
|
|
else:
|
|
|
|
|
# step 1: select area.
|
|
|
|
|
ibon_performance(driver, config_dict)
|
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
def main():
|
2022-11-16 15:43:53 +00:00
|
|
|
|
config_dict = get_config_dict()
|
|
|
|
|
|
|
|
|
|
driver_type = 'selenium'
|
|
|
|
|
#driver_type = 'stealth'
|
|
|
|
|
driver_type = 'undetected_chromedriver'
|
|
|
|
|
|
2022-11-23 04:39:46 +00:00
|
|
|
|
driver = None
|
|
|
|
|
if not config_dict is None:
|
|
|
|
|
driver = get_driver_by_config(config_dict, driver_type)
|
|
|
|
|
else:
|
2023-01-12 08:51:05 +00:00
|
|
|
|
print("Load config error!")
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# internal variable. 說明:這是一個內部變數,請略過。
|
|
|
|
|
url = ""
|
|
|
|
|
last_url = ""
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# for tixcraft
|
|
|
|
|
is_verifyCode_editing = False
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# for kktix
|
|
|
|
|
answer_index = -1
|
2019-12-14 19:13:20 +00:00
|
|
|
|
kktix_register_status_last = None
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-07 21:43:30 +00:00
|
|
|
|
DISCONNECTED_MSG = 'Unable to evaluate script: no such window: target window already closed'
|
|
|
|
|
|
2023-01-11 14:26:49 +00:00
|
|
|
|
ocr = None
|
2023-01-14 05:26:42 +00:00
|
|
|
|
Captcha_Browser = None
|
2023-01-11 14:26:49 +00:00
|
|
|
|
try:
|
2023-01-12 11:41:49 +00:00
|
|
|
|
if config_dict["ocr_captcha"]["enable"]:
|
2023-01-12 22:29:58 +00:00
|
|
|
|
ocr = ddddocr.DdddOcr(show_ad=False, beta=True)
|
2023-01-14 05:26:42 +00:00
|
|
|
|
Captcha_Browser = NonBrowser()
|
2023-01-11 14:26:49 +00:00
|
|
|
|
except Exception as exc:
|
|
|
|
|
pass
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
while True:
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
|
|
|
|
is_alert_popup = False
|
2022-02-18 18:53:55 +00:00
|
|
|
|
|
|
|
|
|
# pass if driver not loaded.
|
|
|
|
|
if driver is None:
|
2022-11-06 09:10:35 +00:00
|
|
|
|
print("web driver not accessible!")
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2023-01-07 21:43:30 +00:00
|
|
|
|
#is_alert_popup = check_pop_alert(driver)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
#MUST "do nothing: if alert popup.
|
|
|
|
|
#print("is_alert_popup:", is_alert_popup)
|
|
|
|
|
if is_alert_popup:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
url = ""
|
|
|
|
|
try:
|
|
|
|
|
url = driver.current_url
|
|
|
|
|
except NoSuchWindowException:
|
2023-01-07 21:43:30 +00:00
|
|
|
|
print('NoSuchWindowException at this url:', url )
|
2019-10-01 17:52:13 +00:00
|
|
|
|
#print("last_url:", last_url)
|
2023-01-07 21:43:30 +00:00
|
|
|
|
#print("get_log:", driver.get_log('driver'))
|
|
|
|
|
if DISCONNECTED_MSG in driver.get_log('driver')[-1]['message']:
|
|
|
|
|
print('quit bot by NoSuchWindowException')
|
|
|
|
|
driver.quit()
|
|
|
|
|
sys.exit()
|
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
try:
|
|
|
|
|
window_handles_count = len(driver.window_handles)
|
2022-12-22 17:17:37 +00:00
|
|
|
|
if window_handles_count > 1:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
driver.switch_to.window(driver.window_handles[0])
|
|
|
|
|
except Exception as excSwithFail:
|
|
|
|
|
pass
|
|
|
|
|
except UnexpectedAlertPresentException as exc1:
|
2022-11-17 18:17:19 +00:00
|
|
|
|
# PS: DON'T remove this line.
|
2022-11-16 17:52:38 +00:00
|
|
|
|
is_verifyCode_editing = False
|
2022-11-07 10:15:35 +00:00
|
|
|
|
print('UnexpectedAlertPresentException at this url:', url )
|
2022-11-20 07:57:16 +00:00
|
|
|
|
#time.sleep(3.5)
|
2022-11-07 10:15:35 +00:00
|
|
|
|
# PS: do nothing...
|
|
|
|
|
# PS: current chrome-driver + chrome call current_url cause alert/prompt dialog disappear!
|
2022-11-23 04:39:46 +00:00
|
|
|
|
# raise exception at selenium/webdriver/remote/errorhandler.py
|
2022-11-07 10:15:35 +00:00
|
|
|
|
# after dialog disappear new excpetion: unhandled inspector error: Not attached to an active page
|
2019-10-01 17:52:13 +00:00
|
|
|
|
is_pass_alert = False
|
2022-11-20 07:57:16 +00:00
|
|
|
|
is_pass_alert = True
|
2019-10-01 17:52:13 +00:00
|
|
|
|
if is_pass_alert:
|
|
|
|
|
try:
|
|
|
|
|
driver.switch_to.alert.accept()
|
2022-11-06 09:10:35 +00:00
|
|
|
|
except Exception as exc:
|
2019-10-01 17:52:13 +00:00
|
|
|
|
pass
|
2019-12-18 03:45:48 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
except Exception as exc:
|
2022-11-21 19:01:04 +00:00
|
|
|
|
is_verifyCode_editing = False
|
|
|
|
|
|
2022-11-07 10:15:35 +00:00
|
|
|
|
logger.error('Maxbot URL Exception')
|
2019-10-01 17:52:13 +00:00
|
|
|
|
logger.error(exc, exc_info=True)
|
|
|
|
|
|
|
|
|
|
#UnicodeEncodeError: 'ascii' codec can't encode characters in position 63-72: ordinal not in range(128)
|
|
|
|
|
str_exc = ""
|
|
|
|
|
try:
|
|
|
|
|
str_exc = str(exc)
|
|
|
|
|
except Exception as exc2:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if len(str_exc)==0:
|
|
|
|
|
str_exc = repr(exc)
|
2022-10-18 18:15:05 +00:00
|
|
|
|
|
2022-11-06 12:37:24 +00:00
|
|
|
|
exit_bot_error_strings = [u'Max retries exceeded'
|
|
|
|
|
, u'chrome not reachable'
|
|
|
|
|
, u'unable to connect to renderer'
|
|
|
|
|
, u'failed to check if window was closed'
|
|
|
|
|
, u'Failed to establish a new connection'
|
|
|
|
|
, u'Connection refused'
|
2022-11-09 17:56:12 +00:00
|
|
|
|
, u'disconnected'
|
2022-11-21 19:01:04 +00:00
|
|
|
|
, u'without establishing a connection'
|
|
|
|
|
, u'web view not found'
|
|
|
|
|
]
|
2022-11-07 10:15:35 +00:00
|
|
|
|
for each_error_string in exit_bot_error_strings:
|
2019-12-14 19:13:20 +00:00
|
|
|
|
# for python2
|
2022-11-06 12:37:24 +00:00
|
|
|
|
# say goodbye to python2
|
|
|
|
|
'''
|
2019-12-14 19:13:20 +00:00
|
|
|
|
try:
|
|
|
|
|
basestring
|
2022-11-07 10:15:35 +00:00
|
|
|
|
if isinstance(each_error_string, unicode):
|
|
|
|
|
each_error_string = str(each_error_string)
|
2019-12-14 19:13:20 +00:00
|
|
|
|
except NameError: # Python 3.x
|
|
|
|
|
basestring = str
|
2022-11-06 12:37:24 +00:00
|
|
|
|
'''
|
2019-12-14 19:13:20 +00:00
|
|
|
|
if isinstance(str_exc, str):
|
2022-11-07 10:15:35 +00:00
|
|
|
|
if each_error_string in str_exc:
|
2023-01-07 21:43:30 +00:00
|
|
|
|
print('quit bot by error:', each_error_string)
|
2019-12-14 19:13:20 +00:00
|
|
|
|
driver.quit()
|
|
|
|
|
sys.exit()
|
2022-11-06 09:10:35 +00:00
|
|
|
|
break
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
# not is above case, print exception.
|
2022-11-06 12:37:24 +00:00
|
|
|
|
print("Exception:", str_exc)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if url is None:
|
|
|
|
|
continue
|
|
|
|
|
else:
|
|
|
|
|
if len(url) == 0:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# 說明:輸出目前網址,覺得吵的話,請註解掉這行。
|
2023-01-13 19:01:47 +00:00
|
|
|
|
#print("url:", url)
|
2022-02-18 18:53:55 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
if len(url) > 0 :
|
|
|
|
|
if url != last_url:
|
|
|
|
|
print(url)
|
|
|
|
|
last_url = url
|
|
|
|
|
|
2022-11-16 15:43:53 +00:00
|
|
|
|
# for Max's manuall test.
|
2019-10-27 04:33:06 +00:00
|
|
|
|
if '/Downloads/varify.html' in url:
|
2023-01-07 21:43:30 +00:00
|
|
|
|
tixcraft_verify(driver, "")
|
2019-10-27 04:33:06 +00:00
|
|
|
|
|
2020-07-25 20:35:54 +00:00
|
|
|
|
tixcraft_family = False
|
2019-10-01 17:52:13 +00:00
|
|
|
|
if 'tixcraft.com' in url:
|
2020-07-25 20:35:54 +00:00
|
|
|
|
tixcraft_family = True
|
|
|
|
|
|
|
|
|
|
if 'indievox.com' in url:
|
|
|
|
|
tixcraft_family = True
|
|
|
|
|
|
|
|
|
|
if tixcraft_family:
|
2023-01-13 19:01:47 +00:00
|
|
|
|
is_verifyCode_editing = tixcraft_main(driver, url, config_dict, is_verifyCode_editing, ocr, Captcha_Browser)
|
2022-01-12 17:14:27 +00:00
|
|
|
|
|
2019-10-01 17:52:13 +00:00
|
|
|
|
# for kktix.cc and kktix.com
|
|
|
|
|
if 'kktix.c' in url:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
answer_index, kktix_register_status_last = kktix_main(driver, url, config_dict, answer_index, kktix_register_status_last)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
# for famiticket
|
|
|
|
|
if 'famiticket.com' in url:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
famiticket_main(driver, url, config_dict)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
# for urbtix
|
|
|
|
|
# https://ticket.urbtix.hk/internet/secure/event/37348/performanceDetail
|
|
|
|
|
if 'urbtix.hk' in url:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
urbtix_main(driver, url, config_dict)
|
2019-10-01 17:52:13 +00:00
|
|
|
|
|
|
|
|
|
if 'cityline.com' in url:
|
2023-01-03 18:54:42 +00:00
|
|
|
|
cityline_main(driver, url, config_dict)
|
2022-12-22 17:17:37 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if 'ibon.com' in url:
|
|
|
|
|
ibon_main(driver, url, config_dict)
|
2022-11-16 15:43:53 +00:00
|
|
|
|
|
|
|
|
|
# for facebook
|
|
|
|
|
facebook_login_url = 'https://www.facebook.com/login.php?'
|
|
|
|
|
if url[:len(facebook_login_url)]==facebook_login_url:
|
|
|
|
|
facebook_account = config_dict["advanced"]["facebook_account"].strip()
|
|
|
|
|
if len(facebook_account) > 4:
|
|
|
|
|
facebook_login(driver, facebook_account)
|
2022-11-06 09:10:35 +00:00
|
|
|
|
|
2021-12-24 10:52:37 +00:00
|
|
|
|
if __name__ == "__main__":
|
2023-01-03 18:54:42 +00:00
|
|
|
|
CONST_MODE_GUI = 0
|
|
|
|
|
CONST_MODE_CLI = 1
|
|
|
|
|
mode = CONST_MODE_GUI
|
|
|
|
|
#mode = CONST_MODE_CLI
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
2023-01-03 18:54:42 +00:00
|
|
|
|
if mode == CONST_MODE_GUI:
|
|
|
|
|
main()
|
|
|
|
|
else:
|
|
|
|
|
#for test kktix infer answer.
|
|
|
|
|
#captcha_text_div_text = u"請回答下列問題,請在下方空格輸入DELIGHT(請以半形輸入法作答,大小寫需要一模一樣)"
|
|
|
|
|
#captcha_text_div_text = u"請在下方空白處輸入引號內文字:「abc」"
|
|
|
|
|
#captcha_text_div_text = u"請在下方空白處輸入引號內文字:「0118eveconcert」(請以半形小寫作答。)"
|
|
|
|
|
#captcha_text_div_text = "在《DEEP AWAKENING見過深淵的人》專輯中,哪一首為合唱曲目? 【V6】深淵 、【Z5】浮木、【J8】無聲、【C1】以上皆非 (請以半形輸入法作答,大小寫/阿拉伯數字需要一模一樣,範例:A2)"
|
2023-01-11 13:58:55 +00:00
|
|
|
|
captcha_text_div_text = "Super Junior 的隊長是以下哪位? 【v】神童 【w】藝聲 【x】利特 【y】始源 若你覺得答案為 a,請輸入 a (英文為半形小寫)"
|
2023-01-03 18:54:42 +00:00
|
|
|
|
inferred_answer_string, answer_list = get_answer_list_from_question_string(None, captcha_text_div_text)
|
|
|
|
|
print("inferred_answer_string:", inferred_answer_string)
|
|
|
|
|
print("answer_list:", answer_list)
|
2023-01-11 13:58:55 +00:00
|
|
|
|
|
2023-01-12 22:29:58 +00:00
|
|
|
|
ocr = ddddocr.DdddOcr(show_ad=False, beta=True)
|
|
|
|
|
with open('captcha-xxxx.png', 'rb') as f:
|
2023-01-11 13:58:55 +00:00
|
|
|
|
image_bytes = f.read()
|
|
|
|
|
res = ocr.classification(image_bytes)
|
|
|
|
|
print(res)
|
|
|
|
|
|