import os
import subprocess
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.remote.webelement import WebElement
import undetected_chromedriver
from selenium.webdriver.common.by import By
import pickle
UNDETECTED_CHROMEDRIVER: str = '1-1'
REAL_CHROMEDRIVER: str = '1-2'
DEFAULT_CHROMEDRIVER: str = '1-3'
AUTOMATION: str = '2-1'
MANUAL: str = '2-2'
PROFILED: str = '3-1'
NON_PROFILED: str = '3-2'
HEADLESS: str = '4-1'
NON_HEADLESS: str = '4-2'
driver: webdriver.Chrome
options: Options
profile: str = ''
test_case: str
username: str
password: str
test_no: int
picture_log_no: int = 0
article_no: int = 0
like_no: int = 0
# 1-1
def set_undetected_chromedriver_options():
global options
options = undetected_chromedriver.ChromeOptions()
def open_undetected_chromedriver():
global options, driver, profile
if profile == '':
driver = undetected_chromedriver.Chrome(options=options)
else:
driver = undetected_chromedriver.Chrome(options=options, user_data_dir=profile)
# 1-2
def set_real_chromedriver_options():
global options
options = webdriver.ChromeOptions()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
def open_real_chromedriver():
global options, driver, profile
cmd = [r'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '--remote-debugging-port=9222',
'--no-first-run', '--no-default-browser-check']
if profile != '':
cmd.append(f'--user-data-dir={profile}')
cmd.append(f'--profile-directory=default')
subprocess.Popen(cmd)
driver = webdriver.Chrome(options=options)
# 1-3
def set_default_chromedriver_options():
global options
options = webdriver.ChromeOptions()
def open_default_chromedriver():
global options, driver
driver = webdriver.Chrome(options=options)
# 2-1 (first time when no cookie)
def automated_login():
def login():
driver.find_element(By.XPATH, "//span[text()='로그인']").click()
capture_picture_log()
driver.find_element(By.XPATH, "//input[@autocomplete='username']").send_keys(username)
capture_picture_log()
driver.find_element(By.XPATH, "//span[text()='다음']").click()
capture_picture_log()
driver.find_element(By.XPATH, "//input[@name='password']").send_keys(password)
capture_picture_log()
driver.find_element(By.XPATH, "//span[text()='로그인하기']").click()
capture_picture_log()
automation_retry(function=login, pass_if_fail=True)
# 2-1
def automated_likes():
def click_close_popup():
close_buttons = driver_find_multiple_query_elements(["//div[@aria-label='닫기']", "//div[@aria-label='Close']"])
if len(close_buttons) > 0:
close_buttons[0].click()
capture_picture_log()
def click_next_article():
global article_no
articles = driver.find_elements(By.XPATH, "//article")
article = articles[article_no]
article_no = article_no + 1
article.click()
capture_picture_log()
def click_people_who_like_button():
people_who_like_button = driver_find_multiple_query_elements(
["//span[text()='마음에 들어요']", "//span[text()='Likes']"])
# if no people_who_like_button
if len(people_who_like_button) == 0:
# go back
driver.back()
capture_picture_log()
# retry
return
else:
people_who_like_button[0].click()
def follow_article_liked():
global like_no
follow_buttons = driver_find_multiple_query_elements(["//span[text()='팔로우']", "//span[text()='Follow']"])
capture_picture_log()
for i in range(len(follow_buttons)):
follow_buttons[i].click()
capture_picture_log()
like_no = like_no + 1
if like_no == 10:
break
def click_home_button():
home_buttons = driver.find_elements(By.XPATH, "//a[@href='/home']")
if len(home_buttons) > 0:
home_buttons[0].click()
print('click_next_article')
automation_retry(function=click_close_popup)
automation_retry(function=click_next_article)
print('click_people_who_like_button')
automation_retry(function=click_close_popup)
automation_retry(function=click_people_who_like_button)
print('follow_article_liked')
automation_retry(function=follow_article_liked)
print('click_home_button')
automation_retry(function=click_close_popup)
automation_retry(function=click_home_button)
global like_no
if like_no < 10:
automated_likes()
def driver_find_multiple_query_elements(querys: list[str], by: By = By.XPATH) -> list[WebElement]:
elements = []
for query in querys:
elements.extend(driver.find_elements(by, query))
return elements
# 2-1
def automation_retry(function: callable, pass_if_fail: bool = False, retry: int = 5):
for i in range(retry):
try:
function()
return
except:
time.sleep(1)
pass
if not pass_if_fail:
function()
# 2-2 (first time when no cookie)
def manual_login():
print(f'username: {username}')
print(f'password: {password}')
input("manually login.\n")
print('good job!')
# 2-2
def manual_likes():
input("manually like people.\n")
print('good job!')
# 3-1
def profiled():
global profile, test_case, options
profile = f'./profiles/{test_case}'
options.add_argument(f'--user-data-dir={profile}')
options.add_argument(f'--profile-directory=default')
# 3-2
def non_profiled():
global profile
profile = ''
# 4-1
def headless():
global options
options.add_argument('--headless')
# 4-2
def non_headless():
return
# common
def open_twitter():
global driver
driver.get('https://www.twitter.com')
# common
def save_cookies():
global test_case, driver
pickle.dump(driver.get_cookies(), open(f"./cookies/{test_case}_cookie.pkl", "wb"))
# common
def load_cookies():
global profile, driver
cookies = pickle.load(open(f"./cookies/{test_case}_cookie.pkl", "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
# common
def cookie_exists():
return os.path.isfile(f"./cookies/{test_case}_cookie.pkl")
# common
def reset_4g_proxy():
input("reset your 4g proxy ip.\n")
print('good job!')
# common
def common_setup():
global picture_log_no, article_no, like_no
picture_log_no = 0
article_no = 0
like_no = 0
if not os.path.isdir(f"./cookies"):
os.mkdir(f"./cookies")
if not os.path.isdir(f"./profiles"):
os.mkdir(f"./profiles")
if not os.path.isdir(f"./log"):
os.mkdir(f"./log")
if not os.path.isdir(f"./log/{test_no}"):
os.mkdir(f"./log/{test_no}")
if not os.path.isdir(f"./log/{test_no}/{test_case}"):
os.mkdir(f"./log/{test_no}/{test_case}")
# common
def capture_picture_log():
global picture_log_no
time.sleep(5)
driver.save_screenshot(f'./log/{test_no}/{test_case}/{picture_log_no}.png')
picture_log_no = picture_log_no + 1
def get_test_case_arguments(input_test_case: str):
test_arguments = input_test_case.split('_')
argument_1 = test_arguments[0]
argument_2 = test_arguments[1]
argument_3 = test_arguments[2]
argument_4 = test_arguments[3]
return argument_1, argument_2, argument_3, argument_4
def test(input_test_case: str, input_username: str, input_password: str):
global test_case, username, password
test_case = input_test_case
username = input_username
password = input_password
driver_type, action_type, profile_type, headless_type = get_test_case_arguments(input_test_case)
if headless_type == HEADLESS and action_type == MANUAL:
raise 'HEADLESS cannot be MANUAL'
# setup
common_setup()
# set chromedriver options
if driver_type == UNDETECTED_CHROMEDRIVER:
set_undetected_chromedriver_options()
elif driver_type == REAL_CHROMEDRIVER:
set_real_chromedriver_options()
elif driver_type == DEFAULT_CHROMEDRIVER:
set_default_chromedriver_options()
# set profile
if profile_type == PROFILED:
profiled()
elif profile_type == NON_PROFILED:
non_profiled()
# set headless
if headless_type == HEADLESS:
headless()
elif headless_type == NON_HEADLESS:
non_headless()
# open chromedriver
if driver_type == UNDETECTED_CHROMEDRIVER:
open_undetected_chromedriver()
elif driver_type == REAL_CHROMEDRIVER:
open_real_chromedriver()
elif driver_type == DEFAULT_CHROMEDRIVER:
open_default_chromedriver()
open_twitter()
# load cookie
if cookie_exists():
load_cookies()
open_twitter()
# login, like
if action_type == AUTOMATION:
automated_login()
automated_likes()
if action_type == MANUAL:
manual_login()
manual_likes()
# save cookie
save_cookies()
print('SUCCESS')
test_no = int(input("test No. is?\n"))
print(f'test No. {test_no}')
test(
input_test_case=f'{REAL_CHROMEDRIVER}_{AUTOMATION}_{NON_PROFILED}_{NON_HEADLESS}',
input_username='',
input_password=''
)