On m'a demandé d'écrire à un analyseur pour qu'il clique sur un bouton d'un site Web et je ne parviens pas à cliquer sur l'un des boutons. Le code suivant fonctionne sur tous les boutons sauf un.
Voici le code HTML: http://Pastebin.com/6dLF5ru8
voici le code source HTML: http://Pastebin.com/XhsedGLb
code python:
driver = webdriver.Firefox()
...
el = driver.find_element_by_id("-spel-nba")
actions.move_to_element(el)
actions.sleep(.1)
actions.click()
actions.perform()
Je reçois cette erreur.
ElementNotVisibleException: Message: Element is not currently visible and so may not be interacted with
selon Saifur, je viens d'essayer d'attendre avec le même élément exception non visible:
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.XPATH, "//input[contains(@id,'spsel')][@value='nba']"))).click()
Si vous regardez la source de la page, vous comprendrez que presque tous les éléments SELECT
, DIV
sont faked
et créés à partir de JavaScript, c'est pourquoi Webdriver ne peut pasNIleur.
Il existe cependant une solution de contournement, en utilisant ActionChains
pour ouvrir votre console de développeur et injecter un artificial CLICK sur l'élément souhaité, qui est en fait le Label qui déclenche leNBAdata loading ... voici un exemple de travail:
from Selenium import webdriver
from Selenium.webdriver.common import action_chains, keys
import time
driver = webdriver.Firefox()
driver.get('Your URL here...')
assert 'NBA' in driver.page_source
action = action_chains.ActionChains(driver)
# open up the developer console, mine on MAC, yours may be diff key combo
action.send_keys(keys.Keys.COMMAND+keys.Keys.ALT+'i')
action.perform()
time.sleep(3)
# this below ENTER is to rid of the above "i"
action.send_keys(keys.Keys.ENTER)
# inject the JavaScript...
action.send_keys("document.querySelectorAll('label.boxed')[1].click()"+keys.Keys.ENTER)
action.perform()
Alternativement, pour remplacer toutes les commandes ActionChains
, vous pouvez simplement exécuter execute_script
comme ceci:
driver.execute_script("document.querySelectorAll('label.boxed')[1].click()")
Voilà, au moins sur mon dossier local de toute façon ... J'espère que ça aide!
Ce qui a fonctionné pour moi a été de trouver l'élément juste avant l'élément problématique (c'est-à-dire juste en termes d'ordre de tabulation), puis d'appeler Tab sur cet élément.
from Selenium.webdriver.common.keys import Keys
elem = br.find_element_by_name("username")
elem.send_keys(Keys.TAB) # tab over to not-visible element
Après cela, j'ai pu envoyer des actions à l'élément.
La solution actuelle de ce fil n'a pas fonctionné pour moi.
cependant,
celui-ci a:
element = WebDriverWait(driver, 3).until(EC.visibility_of_element_located((By.XPATH, xpaths['your_xpath_path'])))
l'astuce consiste à utiliser:
EC.visibility_of_element_located
le WebDriverWait
WebDriverWait
à partir de cette importation:
depuis Selenium.webdriver.support
depuis Selenium.webdriver.support.ui importer WebDriverWait
Je vous suggère d'utiliser xpath
avec explicit
wait
//input[contains(@id,'spsel')][@value='nba']
si "L'élément n'est pas visible", alors rendez-leVISIBLE
f.e.
>>> before is hidden top is outside of page
<input type="file" style="position: absolute;top:-999999" name="file_u">
>>> after move top on in page area
DRIVER.execute_script("document.getElementByName('file_u').style.top = 0;")
time.sleep(1); # give some time to render
DRIVER.find_element_by_name("file_u").send_keys("/tmp/img.png")
J'ai fini par utiliser la solution de @ twasbrillig, mais au lieu de rechercher l'élément précédent et d'envoyer une touche TAB, je recherche l'élément souhaité, envoie une touche TAB avec cet élément, puis une touche MAJ + TAB au conducteur:
from Selenium import webdriver
from Selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
el = driver.find_element_by_id("-spel-nba")
el.send_keys(Keys.TAB)
webdriver.ActionChains(driver).key_down(Keys.SHIFT).send_keys(Keys.TAB).key_up(Keys.SHIFT)
J'ai essayé d'utiliser les autres méthodes, mais à la fin, j'ai trouvé que le moyen le plus simple consistait simplement à cliquer sur le bouton et à détecter l'erreur. Cela me permet d’effectuer d’autres actions selon que cela fonctionne (True) ou non (False).
def click_button(html_object):
try:
html_object.click()
except:
return False #most likely because it is NotVisible object and can be ignored
return True
...
...
click_button(actions)
Au lieu de get_element_by_id()
, vous pouvez essayer elem = browser.find_element_by_css_selector('#elemId')
(allez à la page Web et à l’élément, faites un clic droit dessus et Copy CSS Selector
, ou quelque chose du genre.) C’est ce que j’ai fait et cela fonctionne. Vous essayez également find_element_by_link_text(text)
, find_element_by_partial_link_text(text)
, find_element_by_tag_name(tagName_case_insensitive_here)
, find_element_by_name(name)
etc. Quelque chose fonctionnera. Après la id
, le CSS Selector
est votre meilleur choix.