2016-12-14 7 views
0

У меня возник вопрос относительно того, как неявное ожидание работает в селене. Насколько я понимаю, подразумеваемые ожидания ждут, пока элемент не окажется/видимым/присутствующим, с заданным максимумом. Например:Вопрос: о неявных ожиданиях в python + selenium

wait = WebDriverWait(driver, 
10).until(EC.presence_of_element_located((By.CLASSNAME,'classname'))) 

Это заявление делает селен ждать, пока присутствие элемента с именем класса «Classname» не найдено, или пока не более десяти секунд времени ожидания выполняются, не так ли?

Теперь, я написал скрипт, который получает данные с веб-сайта и использует неявные ожидания, как это:

def move_to_next_page(): 
    (this function loads the next page) 

def get_page_data(): 
    wait = WebDriverWait(driver, 
    10).until(EC.presence_of_element_located((By.CLASS_NAME, 'class'))) 
    items = driver.find_elements_by_class_name('class') 
    for item in items: 
     itemList.append(item.text) 
    return itemList 

move_to_next_page() 
get_page_data() 

Вчера, я побежал этот сценарий успешно несколько раз; неявные ожидания приостановили мою программу на срок до пяти секунд, чтобы все прошло правильно. Тем не менее, я пытаюсь запустить скрипт прямо сейчас, и около 70% от времени я получаю сообщение об ошибке, говорящее:

selenium.common.exceptions.StaleElementReferenceException: Message: 
stale element reference: element is not attached to the page document 

Подразумевая, что браузер по-прежнему загружается? Странно то, что я получаю это сообщение до того, как будет достигнут предел в 10 секунд. Я даже пробовал 20 и 30 секунд, но селен все еще вылетает много раз. Почему селен не будет ждать по крайней мере 10/20/30 секунд?

Я уверен, что неявные ждет вызвать сбой, поскольку, когда я использую явные ожидания, как:

time.sleep(4) 

Программа запускается каждый раз.

У меня есть данные, которые я ищу, поэтому мне больше не нужен этот скрипт. Это просто разочарование, когда вы не можете написать что-то, что будет работать независимо от времени загрузки браузера.

Заранее благодарен!

+0

Вы имеете в виду явное ожидание ('WebDriverWait' +' ExpectedConditions') или неявное ('webdriver.implicitly_wait()')? – Andersson

+0

WebDriverWait + ExpectedConditions! – titusAdam

ответ

1

Прежде всего, WebDriverWait и ExpectedConditions - явное ожидание, а не неявное ожидание. Вы можете узнать больше о разнице here, но длинный рассказ explicit wait ждет выполнения определенного условия и implicit wait ждет, пока элемент не будет существовать в DOM.

Что касается исключения, StaleElementReferenceException не означает, что страница не загружена, это означает, что DOM изменился или перезагрузился между моментом нахождения элемента и временем, когда вы пытались что-то с ним сделать. Вы можете увидеть его в сообщении об ошибке

несвежих опорный элемент: элемент не привязан к странице документу

Вы можете попробовать presence_of_all_elements_located вместо

items = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'class'))) 
for item in items: 
    itemList.append(item.text) 

WebDriverWait.until вернет элементы ExpectedConditions был проверка.

+0

Спасибо за ваш ответ! Еще один быстрый вопрос: когда меняется дом? после того, как вы нажмете на «следующую страницу» или когда новая страница будет полностью загружена? – titusAdam

+1

@titusAdam Нажатие «следующей страницы», безусловно, изменит DOM. На некоторых сайтах может быть процесс JavaScript, который будет продолжать изменять страницу после ее загрузки, – Guy

+0

@titusAdam Я не могу точно знать, не работая с сайтом, но возможно, что процесс JavaScript меняет сайт, а иногда и раньше а иногда и после выполнения условия. Вот почему он работал некоторое время. 'time.sleep (3)' дал процессу достаточно времени для завершения. – Guy

2

Я написал общий метод решения проблемы ожидания в селене, я протестировал его, и он отлично работает.

таймаут = это общее время ожидания вы хотите дать

значение = является идентификатором

ключ = значение ключа посыла. Оставьте это поле пустым, если вы хотите, чтобы нажать

вход = "C" = нажмите "S" = SendKey

def wait_and_send(timeout,value,key,byWhat="By.ID",input=""): 

     try: 
      el = WebDriverWait(browser,time).until(
      EC.presence_of_element_located((eval(byWhat),value)) 
      ) 
      if input == "C": 
       el.click() 
      if input == "S": 
       el.send_keys(key) 
     except: 
      print EC.NoSuchElementException 

Eg. wait_and_send(10,"identifier","[email protected]","By.NAME","S")