Lee Huat Chong
Lee Huat Chong

Reputation: 45

Selenium no need to wait page load completely (Undetected Chrome Driver)

im using undetect_chromedriver along with Selenium for a website scraping task that involves uploading a file. However, I've noticed that the process waits for the page to fully load before allowing the file upload action. I want to upload the file as soon as the file input element becomes available, without waiting for the entire page to load.

I attempted to set pageload = eager, but it didn't produce the desired result. How can I achieve this file upload without waiting for the complete page load?

My code:

import os
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import undetected_chromedriver as uc
import time
import datetime
#Server
from flask import Flask, request, jsonify
from . import app

UPLOAD_DIR = 'upload/'  # Specify the upload directory here

@app.route('/', methods=['POST'])
def handle_audio_blob():
    audio_blob = request.data

    current_datetime = datetime.datetime.now()
    formatted_datetime = current_datetime.strftime("%Y-%m-%d-%H-%M-%S")

    # Save the audio_blob to the upload directory 
    file_name = f'audio_capture_{formatted_datetime}.wav'
    file_path = os.path.join(UPLOAD_DIR, file_name)

    with open(file_path, 'wb') as f:
        f.write(audio_blob)
        
        options = uc.ChromeOptions()
        options.headless = False
        driver = uc.Chrome(driver_executable_path=ChromeDriverManager().install(), options=options)

        # Open the URL
        driver.get("https://tunebat.com/Analyzer")
        time.sleep(1)

        absolute_file_path = os.path.abspath(file_path)
        print(absolute_file_path)

        # Locate and interact with the file input element
        file_input = driver.find_element(By.XPATH, "//input[@type='file']")
        file_input.send_keys(absolute_file_path)
            
        wait = WebDriverWait(driver, 30)  # Wait up to 30 seconds
        wait.until(EC.presence_of_element_located((By.XPATH, "//main/div/div[3]/div/div[2]/div")))
        time.sleep(1)

        key = driver.find_element(By.XPATH, "//main/div/div[3]/div/div[2]/div/div[2]/div/div[1]/div/span[2]/div")
        bpm = driver.find_element(By.XPATH, "//main/div/div[3]/div/div[2]/div/div[2]/div/div[1]/div/span[4]/div")
        result = {
            "key": key.text,
            "bpm": bpm.text
        }

        print(result)
        # Close the browser
        driver.quit()

    if os.path.exists(file_path):
        os.remove(file_path)

    return jsonify(result)

Upvotes: 0

Views: 803

Answers (2)

Try to use two waits, because what we see is element is displaying, but it is not ready to be clickable, so...

try:
    WebDriverWait(driver,30).until(EC.visibility_of_element_located((By.XPATH, "//main/div/div[3]/div/div[2]/div")))
    WebDriverWait(driver,30).until(EC.element_to_be_clickable((By.XPATH, "//main/div/div[3]/div/div[2]/div")))
except TimeoutException:
         Handle...

Upvotes: 0

SuccoDiMora
SuccoDiMora

Reputation: 69

Had the same issue months ago, solved with Expected Conditions has you.

try:
 WebDriverWait(driver,30).until(EC.visibility_of_element_located((By.XPATH, "//main/div/div[3]/div/div[2]/div")))
except TimeoutException:
 # Handle...

Handled with a try catch, just in case the element doesn't exists and in case notice it.

I also prefer to go for visibility_of_element_located insted of presence_of_element_located

Upvotes: 0

Related Questions