нет такого элемента: невозможно найти элемент с помощью chromedriver и Selenium в производственной среде

у меня проблема с селеном chromedriver, который я не могу понять, что его вызывает. Несколько недель назад все работало нормально, и вдруг эта ошибка начала появляться. Проблема исходит из следующей функции.

 def login_(browser):
    try:
        browser.get("some_url")
        # user credentials
        user = browser.find_element_by_xpath('//*[@id="username"]')
        user.send_keys(config('user'))
        password = browser.find_element_by_xpath('//*[@id="password"]')
        password.send_keys(config('pass'))
        login = browser.find_element_by_xpath('/html/body/div[1]/div/button')
        login.send_keys("n")
        time.sleep(1)
        sidebar = browser.find_element_by_xpath('//*[@id="sidebar"]/ul/li[1]/a')
        sidebar.send_keys("n")
        app_submit = browser.find_element_by_xpath('//*[@id="sidebar"]/ul/li[1]/ul/li[1]/a')
        app_submit.send_keys("n")
    except TimeoutException or NoSuchElementException:
        raise LoginException

эта функция работает без проблем в среде разработки (macOS 10.11), но выдает следующую ошибку в рабочей среде:

Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="sidebar"]/ul/li[1]/a"}
(Session info: headless chrome=67.0.3396.79)
(Driver info: chromedriver=2.40.565383 (76257d1ab79276b2d53ee97XXX),platform=Linux 4.4.0-116-generic x86_64)

Я уже обновил Chrome и chromedriver (v67 & 2.40, соответственно) в каждой среде. Я также дал ему еще time.sleep(15). Но проблема сохраняется. Мое последнее предположение заключается в том, что, возможно, инициализация webdriver работает неправильно:

def initiate_webdriver():
   option = webdriver.ChromeOptions()
   option.binary_location = config('GOOGLE_CHROME_BIN')
   option.add_argument('--disable-gpu')
   option.add_argument('window-size=1600,900')
   option.add_argument('--no-sandbox')
   if not config('DEBUG', cast=bool):
       display = Display(visible=0, size=(1600, 900))
       display.start()
       option.add_argument("--headless")
   else:
       option.add_argument("--incognito")
   return webdriver.Chrome(executable_path=config('CHROMEDRIVER_PATH'), chrome_options=option)

потому что, если Display не работает, тогда не может быть упомянутого sidebar но какая-то другая кнопка.

Итак, мои вопросы: у кого-нибудь была аналогичная проблема? Есть ли способ узнать, что показывает страница в то время, когда водитель ищет такой элемент?

4 ответов


пару вещей согласно login_(browser) способ:

  • как вы определили логин через:

    login = browser.find_element_by_xpath('/html/body/div[1]/div/button')
    

    Я бы предложил вместо вызова send_keys("\n") принять помощь onclick () событие через login.click() глумиться над нажатие кнопки входа следующим образом:

    login = browser.find_element_by_xpath('/html/body/div[1]/div/button')
    login.click()
    
  • далее, когда вы определите боковая панель вызывать WebDriverWait на элемент для кликабельности следующим образом:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="sidebar"]/ul/li[1]/a'))).click()
    
  • как вы упомянули ваш блок кода кода работает идеально в macOS 10.11 среда, но выдает следующую ошибку в рабочей среде (Linux) весьма возможно, что различные браузеры отображают HTML DOM по-разному в разной архитектуре ОС. Так что вместо абсолютный xpath вы должны использовать относительный xpath следующим образом:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[@attribute='value']"))).click()
    

пару вещей согласно initiate_webdriver() способ:

  • по состоянию на начало работы с безголовым Chrome аргумент --disable-gpu применимо только для Windows но не допустимая конфигурация для ОС Linux. Так нужна удалить:

    option.add_argument('--disable-gpu')
    

Примечание : вы должны добавить следующий импорт:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

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

driver.save_screenshot("path to save screen.jpeg")

также вы можете сохранить исходный html-код и проверить ту же страницу.

Скриншот Webdriver

использование Selenium в Python для сохранения веб-страницы в Firefox


всякий раз, когда я сталкиваюсь со странными проблемами в селене, как это, я предпочитаю пытаться найти конкретный элемент, который вызывает прерывистые проблемы. Один из способов-обернуть его вокруг блока try-except:

try:
   sidebar = browser.find_element_by_xpath('//*[@id="sidebar"]/ul/li[1]/a')
except NoSuchElementException:
   time.sleep(10)
   print("Unable to find element in first time, trying it again")
   sidebar = browser.find_element_by_xpath('//*[@id="sidebar"]/ul/li[1]/a')

вы также можете поставить try код в цикле с подходящей переменной count для работы кода автоматизации. (Проверка этой). По моему опыту работы с JAVA эта идея решила несколько проблем.


нужно подождать, пока элемент не виден, иначе вы получите эту ошибку. Попробуйте что-то вроде этого:

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.expected_conditions import visibility_of_element_located
from selenium.webdriver.common.by import By
TIMEOUT = 5

...
xpath = '//*[@id="sidebar"]/ul/li[1]/a'
WebDriverWait(self.selenium, TIMEOUT).until(visibility_of_element_located((By.XPATH, xpath)))
browser.find_element_by_xpath(xpath)
...