2012-09-12 7 views
9

Sto tentando di automatizzare un'attività di amministrazione, finora ho fatto in modo che il selenio faccia clic su un elemento per mostrare un menu a discesa.Fare clic su un menu a tendina con Selenium Webdriver

enter image description here

Quando arriva il momento di fare clic su uno di questi elementi di menu ho un errore che dice che l'elemento deve essere visualizzato.

Codice:

driver = webdriver.Chrome() 
driver.implicitly_wait(10) 
driver.get(url) 
doc = driver.find_element_by_css_selector('td.ms-vb-title > table') 
try: 
    doc.click() 
    time.sleep(4) 
    menu = driver.find_element_by_xpath('//menu/span[5]') 
    time.sleep(4) 
    print dir(menu) 
    menu.click() 
except: 
    traceback.print_exc() 
    driver.quit() 

Errore:

Traceback (most recent call last): 
    File "aprobar_docs.py", line 22, in main 
    menu.click() 
    File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", 
line 52, in click 
    self._execute(Command.CLICK_ELEMENT) 
    File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", 
line 205, in _execute 
    return self._parent.execute(command, params) 
    File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", l 
ine 156, in execute 
    self.error_handler.check_response(response) 
    File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py" 
, line 147, in check_response 
    raise exception_class(message, screen, stacktrace) 
ElementNotVisibleException: Message: u'Element must be displayed to click' 

Come si può vedere il codice attende molto per ottenere l'elemento caricato. Ho anche provato a impostare la proprietà is_displayed dell'elemento su True ma non ha funzionato neanche.

Nota: l'elemento che non è visualizzato è quello sulla ricerca XPath, è presente perché ho collegato con dir (menu)

Edit:

La variabile menu non è il menu stesso è uno degli span che sono elementi del menu, doc è l'elemento html Perfil che viene cliccato per mostrare il menu a discesa.

Edit 2:

Ispezione del DOM su strumenti di cromo, quando si fa clic su un doc un nuovo menu viene creato sul legno della croce, non so se è a causa di una chiamata AJAX o js vaniglia, Non penso sia davvero così importante come sia stato creato. Non riesco a recuperarlo dalla pagina e creare un oggetto python da esso, non viene visualizzato almeno sul codice.

Edit finale:

ho finito per l'esecuzione di alcune Javascript per farlo funzionare. Apparentemente, quando il selenio trova la voce di menu, il primo elemento che attiva il menu a discesa perde la messa a fuoco e rende di nuovo il menu invisibile, se non selezioni una voce di menu e attendi per qualche istante che il menu a discesa sia ancora mostrato, se prova a selezionare un elemento dal menu, il menu scompare.

+1

Perché dormite su entrambi i lati dell'elemento di ricerca 'menu'?Se l'elemento non è visibile quando si recupera l'elemento della pagina, il webdriver non sarà in grado di fare clic su di esso, indipendentemente dalla durata dell'attesa. –

+0

@ sr2222 La pagina viene recuperata quando si chiama driver.get(), il menu a discesa viene visualizzato sullo schermo e presente nell'albero dei dom quando si fa doc.click(), ho appena eliminato la possibilità che il menu a discesa non venga caricato veloce come il codice viene eseguito. L'elemento del menu è presente e visibile, almeno per gli umani, posso garantirlo. – loki

+0

Prova a estrarre 'doc' nuovamente dopo aver fatto clic e attendi che il menu venga visualizzato, e confronta l'attributo' id' degli oggetti da prima e dopo. Ho un vago sospetto che il server di selenio stia effettivamente facendo riferimento a un oggetto webelement memorizzato nella cache sulla seconda estrazione di elementi (poiché l'azione di clic non attiva un evento di caricamento della pagina, l'oggetto della pagina non diventa obsoleto). –

risposta

8

Perché non selezionare un'opzione come questo

el = driver.find_element_by_id('id_of_select') 
for option in el.find_elements_by_tag_name('option'): 
    if option.text == 'The Options I Am Looking For': 
     option.click() # select() in earlier versions of webdriver 

Se il click non è sparare una chiamata AJAX per popolare la vostra lista, in realtà non c'è bisogno di eseguire il click.

+0

@Nllesh Sharma Ho usato questo approccio, ma ricevo un errore che l'oggetto web non è iterable. Come stai iterando su di esso nel ciclo for se non è iterable – abhi

+0

@abhi sei sicuro di utilizzare find_elementSSSSS_by_tag_name()? (solo per essere sicuro di aver visto che S hehe) –

0

È necessario trovare il collegamento del target. Non è davvero clic sugli elementi, si fa clic sui collegamenti ... (o meglio, si fa clic sugli elementi con i collegamenti al loro interno). Detto questo, il modo più sicuro per fare clic su un link è isolare l'elemento link.

frame = driver.find_element_by_id('this_is_your_frame_name') 
links = frame.find_elements_by_xpath('.//a') 
links[1].click() 

o, in alternativa,

for link in links: 
    if link.text() == "Administratar Permisos": 
     link.click()