kaliiiiiiiiii / Selenium-Profiles

undetected Selenium using chromedriver and emulation / device profiles
Other
255 stars 29 forks source link

Click on button not working on android #5

Closed SamPse closed 1 year ago

SamPse commented 1 year ago

I try to click on a button but I can t. I manage to find the button with XPATH but the click does not work. I think it s a bug in the selenium driver

mydriver = mydriver() driver = mydriver.start(profiles.Android(), uc_driver=True) # or .Android

element = WebDriverWait(driver,40).until(EC.presence_of_element_located((By.XPATH, '//*[@id="skip-button:6"]/span/button'))) element.click()

kaliiiiiiiiii commented 1 year ago

I checked element.click() using profiles.Android() as profile on Windows with the script:

# selenium_profiles imports
from selenium_profiles import driver as mydriver
from selenium_profiles.profiles import profiles

# selenium imports
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

mydriver = mydriver()
driver = mydriver.start(profiles.Android(), uc_driver=True)

# get url
driver.get('https://www.w3schools.com/tags/tag_button.asp')

# click Log-in Element, note that it waits up to 40 sec. till your element is located
element = WebDriverWait(driver, 40).until(EC.presence_of_element_located((By.XPATH, '//*[@id="w3loginbtn"]')))
element.click()
# login page should popup

# input("Press ENTER to exit: ")
driver.quit()  # Execute on the End!

For me, the script worked as expected. You could check, if it also works for you? Did you also try with uc_driver = False?

Could you give some more information for reproducing?

  1. Platform (Windows, Google-Colab, Linux, something else?)
  2. HTML to reproduce or the URL of the site
  3. What you expect to happen when you click the button
  4. Assuming you used the original profiles.Android() profile and didn't modify it?
  5. What Version of selenium-profiles you're working with

Also make shure:

kaliiiiiiiiii commented 1 year ago
from selenium_profiles.driver import driver as mydriver
from selenium_profiles.profiles import profiles
from selenium.webdriver.common.by import By # locate elements
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

mydriver = mydriver()
driver = mydriver.start(profiles.Android(), uc_driver=False) # or .Android
driver.get('https://www.youtube.com/watch?v=JYeX4jCBh10') # test client hints

after requesting the url, you need to accept or reject the cookies. I assume you did that?

image

After that, you want to click on the Skip-Ad button, right? image

You're right, doesn't work with element.click(). Also manual skipping with mouse doesn't work.

That's because YouTube assumes you're using a touch-screen (Mobile) and only listens on touch events.

You can bypass that using:

profile = profiles.Android()
profile["browser"]["pointer_as_touch"] = True  # enable pointer_as_touch
driver = mydriver.start(profile, uc_driver=False) # or .Android

Works, but after the action, the code hungs. see #1

Maybe possible Solutions:

execute touchevent using javascript-executor ( driver.execute_script("my_js_script"))

or try based on that example:

from selenium.webdriver import TouchActions
touch_actions = TouchActions(driver)

# get your element here

touch_actions.tap(element).perform()

Never really worked with Javascript, but if you find a solution, please keep me updated.

SamPse commented 1 year ago

I tried with driver.execute_script and touch_actions it's the same thing once click on the button the code remains blocked.

kaliiiiiiiiii commented 1 year ago

Got a possible solution, please close your issue if it solves the problem.

from selenium_profiles.driver import driver as mydriver
from selenium_profiles.profiles import profiles
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

# My Functions
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.actions import interaction
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.pointer_input import PointerInput

def touch_action_chain(driver):
    """

    credits: https://www.reddit.com/r/Appium/comments/rbx1r2/touchaction_deprecated_please_use_w3c_i_stead/

    EXAMPLE:

    actions = touch_action_chain(driver)
    actions.pointer_action.move_to_location(mid_location['x'],mid_location['y'])
    actions.pointer_action.click()
    actions.perform()
    """
    actions = ActionChains(driver)
    actions.w3c_actions = ActionBuilder(driver, mouse=PointerInput(interaction.POINTER_TOUCH, "touch"))
    return actions.w3c_actions

def mid_location(element):  # middle location of an element
    return {'x': element.location_once_scrolled_into_view['x'] + (element.rect["width"] / 2),
     'y': element.location_once_scrolled_into_view['y'] + (element.rect["height"] / 2)}

# Start Driver
mydriver = mydriver()
profile = profiles.Android()
driver = mydriver.start(profile, uc_driver=False) # or .Android
driver.get('https://www.youtube.com/watch?v=JYeX4jCBh10') # test client hints

# reject all cookies
driver.find_element(By.XPATH, '//*[@class ="eom-reject"]/button').click()

# wait 2 min. till element visible
element = WebDriverWait(driver,120).until(EC.visibility_of_element_located((By.XPATH, "//*[starts-with(@id,'skip-button:')]/span/button")))

# NAVIGATE: video and pause when skip option is visible

time.sleep(3) # wait for skip-button loaded

# setup action chain
location = mid_location(element)
actions = touch_action_chain(driver)

actions.pointer_action.move_to_location(location['x'],location['y'])
actions.pointer_action.click()

# perform action
actions.perform()

# quit driver
input('Press ENTER to quit Driver\n')
driver.quit()

inspired by https://www.reddit.com/r/Appium/comments/rbx1r2/touchaction_deprecated_please_use_w3c_i_stead/

future import for touch_action_chain intended for selenium_profiles

note: touch_actions are deprecated since https://github.com/SeleniumHQ/selenium/commit/816ad6ebb5353431c37f160b2b9b0056b6efdb4e, that's probably why it didn't work in your case.

SamPse commented 1 year ago

Great it works. Thanks :)