Когда я работаю внутри докера, я получаю сообщение об ошибке ниже.
Код: Выделить всё
ERROR:setup:Login attempt 3 failed: Message: element not interactable
Код: Выделить всё
from selenium.webdriver.common.by import By
import undetected_chromedriver as uc
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os
import logging
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
logger = logging.getLogger('setup')
def setup_driver(profile_id=None):
# Initialize Chrome options
options = uc.ChromeOptions()
# Optional: Set the binary location explicitly if required (uncomment and update this path as needed)
# options.binary_location = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" # For macOS
options.binary_location = "/usr/bin/google-chrome" # For Linux/Docker environments
# Set Chrome options for better automation experience
options.add_argument("--start-maximized") # Open the browser maximized
options.add_argument("--disable-popup-blocking") # Disable any popups that may interrupt
options.add_experimental_option("prefs", {
"profile.default_content_setting_values.popups": 1,
"profile.default_content_setting_values.notifications": 1
})
# Additional Chrome options to optimize performance and stability
options.add_argument("--disable-background-networking")
options.add_argument("--disable-background-timer-throttling")
options.add_argument("--disable-backgrounding-occluded-windows")
options.add_argument("--disable-breakpad")
options.add_argument("--disable-client-side-phishing-detection")
options.add_argument("--disable-default-apps")
options.add_argument("--disable-hang-monitor")
options.add_argument("--disable-prompt-on-repost")
options.add_argument("--disable-sync")
options.add_argument("--metrics-recording-only")
options.add_argument("--no-first-run")
options.add_argument("--safebrowsing-disable-auto-update")
options.add_argument("--password-store=basic")
options.add_argument("--use-mock-keychain")
options.add_argument("--disable-infobars") # Disable annoying info bars in Chrome
options.add_argument("--disable-blink-features=AutomationControlled") # Avoid detection as a bot
options.add_argument("--no-sandbox") # Fix issues in some environments
options.add_argument("--disable-dev-shm-usage") # Handle resource issues
options.add_argument("--disable-gpu") # Disable GPU acceleration
options.add_argument("--remote-debugging-port=9222") # Avoid port conflicts
# Uncomment this line to run in headless mode (for server or Docker environments)
options.add_argument("--headless")
try:
if profile_id:
base_profile_dir = os.path.join(os.getcwd(), "chrome_profiles")
profile_path = os.path.join(base_profile_dir, f"profile_{profile_id}")
# Check if profile already exists; if it exists, we load it, otherwise we create it
if not os.path.exists(profile_path):
logger.info(f"Profile directory for {profile_id} does not exist, creating...")
os.makedirs(profile_path, exist_ok=True)
else:
logger.info(f"Profile directory for {profile_id} already exists, loading...")
# Use specific Chrome profile
options.add_argument(f"--user-data-dir={profile_path}")
# Initialize the Chrome driver with the defined options
driver = uc.Chrome(service=Service(ChromeDriverManager().install()), options=options)
return driver
except Exception as e:
logger.error(f"Failed to set up Chrome driver: {e}")
print(f"Failed to set up Chrome driver: {e}", flush=True)
return None
def login_to_tiktok(driver, email, password, max_retries=3):
# Open TikTok Seller login page
driver.get("https://seller-us-accounts.tiktok.com/account/login")
# Wait for and click the 'Email' tab to switch to email login if not already selected
email_tab = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, 'tab')]//span[text()='Email']"))
)
if email_tab.is_selected():
print("Email tab already selected")
else:
email_tab.click()
logger.info("Logging in to TikTok Seller account...")
print("Logging in to TikTok Seller account...", flush=True)
# Wait for the email input field to be visible and interactable
email_input = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//input[@placeholder='Enter your email address']"))
)
email_input.clear()
email_input.send_keys(email)
logger.info("Email entered")
print("Email entered", flush=True)
# Wait for the password input field to be interactable
password_input = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//input[@placeholder='Enter your password']"))
)
password_input.clear()
password_input.send_keys(password)
logger.info("Password entered")
print("Password entered", flush=True)
# Click the login button
login_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Log in')]"))
)
login_button.click()
logger.info("Login button clicked")
print("Login button clicked", flush=True)
# Wait for the login process to complete by checking for a post-login element (like user dashboard)
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#dashboard_element_selector")) # Update this selector
)
logger.info("Logged in successfully")
return True # Login successful, exit the loop
def login_sellers_with_profile(self):
email = self.email
password = self.password
driver = setup_driver(profile_id=email)
# Check if the user is already logged in by visiting the homepage
if self.is_logged_in(driver):
logger.info(f"✋ ✋ ✋ {email} is already logged in, skipping login.")
print(f"✋ ✋ ✋ {email} is already logged in, skipping login.", flush=True)
return driver
logger.info(f"🧐 🧐 🧐 Logging in {email}...")
print(f"🧐 🧐 🧐 Logging in {email}...", flush=True)
# If not logged in, perform the login process
login_response = login_to_tiktok(driver, email, password)
print(f"🔑 🔑 🔑 Login response: {login_response}", flush=True)
if login_response:
logger.info(f"✔ ✔ ✔ Logged in successfully to {email}")
print(f"✔ ✔ ✔ Logged in successfully to {email}", flush=True)
else:
logger.info(f"✘ ✘ ✘ Login failed for {email}")
print(f"✘ ✘ ✘ Login failed for {email}", flush=True)
driver.quit()
return None
return driver
Я также поделился кодом установки драйвера.
Дайте мне знать, если потребуется что-нибудь еще.
Подробнее здесь: https://stackoverflow.com/questions/789 ... g-selenium