Selenium - текстовое свойство становится доступным только после проверки отладчиком - PullRequest
1 голос
/ 21 июня 2019

Я борюсь с неожиданным поведением в веб-скребке Python 3 на основе Selenium и хочу понять, что происходит:

Я анализирую сайты с предложениями работы. После первоначального поиска я получаю от 1 до n сайтов результатов. Это количество сайтов показано на самой первой странице в виде текстовой части элемента "m-pagination__meta" и отображается на немецком языке, например, «1 фон 48». Мне нужна эта строка для дальнейшей обработки. Он находится на сайте, он НЕ является частью iframe.

Пример ссылки на сайте вакансий

HTML:

<div class="m-pagination">
  <div class="m-pagination__inner m-pagination__inner--borderBottom">
    <button class="m-pagination__button m-pagination__button--disabled" data-page="" data-event-action="click: pagination-first">
      <svg viewBox="0 0 17 17" width="0" height="0" class="m-icon m-icon--large ">
        <g fill="none" stroke="currentColor" stroke-width=".7" stroke-linecap="round" stroke-linejoin="round">
          <path d="M9 13.2L4.2 8.5 9 3.8"></path>
          <path d="M12.8 13.2L8 8.5l4.7-4.7"></path>
        </g>
      </svg>
    </button>
    <button class="m-pagination__button m-pagination__button--previous m-pagination__button--disabled" data-page="false" data-event-action="click: pagination-previous">
      <svg viewBox="0 0 17 17" width="0" height="0" class="m-icon m-icon--large ">
        <path fill="none" stroke="currentColor" stroke-width=".8" stroke-linecap="round" stroke-linejoin="round" d="M10.9 3.8L6 8.6l4.7 4.6"></path>
      </svg>
    </button>
    <span class="m-pagination__meta" data-number="1"> 1 von 43 </span> 
    <button class="m-pagination__button m-pagination__button--next m-pagination__button--available" data-page="2" data-event-action="click: pagination-next">
      <svg viewBox="0 0 17 17" width="0" height="0" class="m-icon m-icon--large ">
        <path fill="none" stroke="currentColor" stroke-width=".7" stroke-linecap="round" stroke-linejoin="round" d="M6.1 3.8L11 8.6l-4.7 4.6"></path>
      </svg>
    </button>
  </div>
</div>

Теперь начинается странная часть: Когда я отлаживаю программу и пытаюсь получить доступ к строковому элементу напрямую с помощью "m-pagination__meta" .text, он возвращает пустую строку.

Тем не менее, когда я обращаюсь к объекту материнского элемента m-pagination__meta и проверяю его с помощью отладчика, прокручивая до свойства text ожидаемую строку «1 von 48», она находится там. После этой проверки я могу получить доступ к "m-pagination__meta" .text с ожидаемыми результатами.

Это поведение, похоже, не зависит от времени. Я пытался дождаться наличия необходимого элемента с кодом типа

wait = WebDriverWait(self.driver, 10)
wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME,"m-pagination__meta"), "1 von 48"))
pagesTotal = int(self.driver.find_element_by_class_name("m-pagination__meta").text.split(" ")[2])

безрезультатно (конечно, я понял, что глупо искать определенную строку, когда я не знаю, какую именно она выдаст, но я не знал, как еще ее кодировать).

Я также пробовал "нормальное" ожидание с использованием режима сна, но, похоже, ничего не работает, только упомянутая проверка в отладчике, которая бесполезна для производственных целей.

Мне бы очень хотелось понять, что здесь происходит.

Ответы [ 3 ]

3 голосов
/ 21 июня 2019

Имеется vertical scroll bar подарок, который разделяет страницу на две части. Однако, когда вам нужно сначала найти элемент левой полосы прокрутки, а затем выполните location_once_scrolled_into_view. Как только вы достигнете, вы сможете определить элемент, который вам нужен.

Попробуйте следующий код.

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

driver=webdriver.Chrome()
driver.get('https://www.karriere.at/jobs/programmierer/wien')
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='c-jobsSearch__listing']"))).location_once_scrolled_into_view
print(driver.find_element_by_xpath("//span[@class='m-pagination__meta']").get_attribute('innerText'))
1 голос
/ 21 июня 2019

Возможно, проблема связана с тем, что элемент появляется в источнике HTML при загрузке страницы, но JavaScript заполняет значение за кулисами.

Вы можете использовать регулярное выражение в XPath для сопоставления текста на основе шаблона:

xpath = '//*[contains(@class, "m-pagination__meta") and matches(normalize-space(text()), "\d+ von \d+")]'
wait = WebDriverWait(self.driver, 30)
wait.until(EC.element_to_be_present(By.XPATH, xpath))

Примечание. Может быть, увеличьте период ожидания до 30 секунд, просто для безопасности.

0 голосов
/ 21 июня 2019

Вы, кажется, довольно близки с WebDriverWait .Но, к сожалению, элемент расположен далеко вниз по дереву DOM и отсутствует в Окно просмотра .Следовательно, возвращается пустая строка .


Решение

Решением будет scroll() элемент в Окно просмотра после элемента видимый в HTML DOM , используя EC в качестве visibility_of_element_located(), а затем вы можете попытаться извлечь нужный текст, и вы можете использовать любой из следующих Стратегии локатора :

  • Использование CSS_SELECTOR:

    driver.execute_script("return arguments[0].scrollIntoView(true);", WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "span.m-pagination__meta"))))
    print(driver.find_element_by_css_selector("span.m-pagination__meta").get_attribute("innerHTML"))
    
  • Использование XPATH:

    driver.execute_script("return arguments[0].scrollIntoView(true);", WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//span[@class='m-pagination__meta']"))))
    print(driver.find_element_by_xpath("//span[@class='m-pagination__meta']").get_attribute("innerHTML"))
    
  • Примечание : необходимо добавить следующие операции импорта:

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...