我正在基于Selenium的Python 3网络抓取工具中应对意外行为,并想了解发生了什么事情:
我正在解析具有工作机会的网站。初步搜索后,我得到1到n个结果位点。这个网站的数量在第一页上显示为“ m-pagination__meta”元素的文本部分,并以德语显示。 “ 1 von 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”直接访问字符串元素时,它会返回一个空字符串。
但是,当我访问母元素对象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])
无济于事(当然,当我不知道会产生哪个字符串,但又不知道如何编码时,我意识到搜索特定字符串是愚蠢的。)
我还尝试了使用睡眠的“正常”等待,但似乎没有任何效果,只有调试器中提到的检查才对生产有用。
我真的很想了解这里发生的事情。
答案 0 :(得分:3)
存在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 :(得分:1)
问题可能是由于页面加载时元素出现在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秒。
答案 2 :(得分:0)
您似乎与 WebDriverWait 非常接近。但不幸的是,该元素位于DOM Tree的下方,而不位于Viewport中。因此,将返回空字符串。
解决方案是使用 EC <在HTML DOM中可见元素,在视口中scroll()
元素/ em>作为visibility_of_element_located()
,然后您可以尝试提取所需的文本,并且可以使用以下任一Locator Strategies:
使用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