Python Selenium Scraping Javascript - 找不到元素

时间:2018-02-14 13:48:53

标签: javascript python selenium xpath web-scraping

我正在尝试抓取以下Javascript前端网站来练习我的Javascript抓取技巧: https://www.oplaadpalen.nl/laadpaal/112618

我试图通过xPath找到两个不同的元素。第一个是标题,它确实找到了。第二个是实际的文本本身,它以某种方式无法找到。这很奇怪,因为我刚从Chrome浏览器中复制了xPath。

from selenium import webdriver

link = 'https://www.oplaadpalen.nl/laadpaal/112618'
driver = webdriver.PhantomJS()
driver.get(link)

#It could find the right element
xpath_attribute_title = '//*[@id="main-sidebar-container"]/div/div[1]/div[2]/div/div[' + str(3) + ']/label'
next_page_elem_title = driver.find_element_by_xpath(xpath_attribute_title)
print(next_page_elem_title.text)

#It fails to find the right element
xpath_attribute_value = '//*[@id="main-sidebar-container"]/div/div[1]/div[2]/div/div[' + str(3) + ']/text()'
next_page_elem_value = driver.find_element_by_xpath(xpath_attribute_value)
print(next_page_elem_value.text)

我尝试了几件事:将“text()”改为“text”,“(text)”,但它们似乎都没有用。

我有两个问题:

  • 为什么找不到正确的元素?
  • 我们可以做些什么来让它找到正确的元素?

5 个答案:

答案 0 :(得分:2)

Selenium的find_element_by_xpath()方法返回与给定XPath查询匹配的第一个元素节点(如果有)。但是,XPath的text()函数返回文本节点 - 而不是包含它的元素节点。

要使用Selenium的finder方法提取文本,您需要找到包含元素,然后从返回的对象中提取文本。

答案 1 :(得分:1)

我建议采用略有不同的方法。我会抓取整个文字,然后在:上抓取split one time。这将获得标题和价值。下面的代码将通过openstijden标签获得Paalcode。

for x in range(2, 8):
    s = driver.find_element_by_css_selector("div.leftblock > div.labels > div")[x].text
    t = s.split(":", 1)
    print(t[0]) # title
    print(t[1]) # value

您不希望多次拆分,因为状态包含更多分号。

答案 2 :(得分:1)

使用@ JeffC的方法,如果你想首先使用xpath而不是css选择器选择所有这些元素,你可以使用这个代码:

xpath_title_value = "//div[@class='labels']//div[label[contains(text(),':')] and not(div) and not(contains(@class,'toolbox'))]"
title_and_value_elements = driver.find_elements_by_xpath(xpath_title_value)

注意 find_elements_by_xpath 方法中的复数元素。上面的xpath选择div元素作为div元素的后代,div元素的类属性为"标签"。每个选定div的嵌套标签必须包含冒号。此外,div本身可能没有一类"工具箱" (页面上某些其他div具有的东西),也不必包含任何其他嵌套的div。

然后,您可以在单个div元素(也包含嵌套标签元素中的文本)中提取文本,然后使用":\ n"它将原始文本字符串中的标题和值分开。

for element in title_and_value_elements:
    element = element.text
    title,value = element.split(":\n")
    print(title)
    print(value,"\n")

答案 3 :(得分:1)

保持您自己的逻辑完整,您可以按如下方式提取标签和关联

for x in range(3, 8):
    label = driver.find_element_by_xpath("//div[@class='labels']//following::div[%s]/label" %x).get_attribute("innerHTML")
    value = driver.find_element_by_xpath("//div[@class='labels']//following::div[%s]" %x).get_attribute("innerHTML").split(">")[2]
    print("Label is %s and value is %s" % (label, value))

控制台输出:

Label is Paalcode: and value is NewMotion 04001157
Label is Adres: and value is Deventerstraat 130
Label is pc/plaats: and value is 7321cd Apeldoorn

答案 4 :(得分:1)

由于你想练习JS技能,你也可以在JS中做到这一点,实际上所有div包含更多数据,你可以看看你是否将它粘贴在浏览器控制台中:

labels = document.querySelectorAll(".labels");
divs = labels[0].querySelectorAll("div");
for (div of divs) console.log(div.firstChild, div.textContent); 

你可以push到一个数组并只检查div并且有label并在python变量中返回结果数组:

labels_value_pair.driver.execute_script('''
scrap = [];
labels = document.querySelectorAll(".labels");
divs = labels[0].querySelectorAll("div");
for (div of divs) if (div.firstChild.tagName==="LABEL") scrap.push(div.firstChild.textContent, div.textContent); 
return scrap;
''')