【问题标题】:Xpath How to check if a child element exist given the parent node?Xpath如何检查给定父节点是否存在子元素?
【发布时间】:2021-09-19 10:32:30
【问题描述】:

我想遍历父节点并检查父节点是否有某个子节点并从中提取数据。

网站的脚本是这样的:

<div @class="reviews">
  <div @id = "user1">
    <div @class="name"> Will </div>
    <div @class="weight"> 50kg </div>
    <div @class="height"> 160cm </div>
  </div>
  <div @id = "user2">
    <div @class="weight"> 55kg </div>
    <div @class="height"> 170cm </div>
  </div>
  <div @id = "user3">
    <div @class="name"> Ben </div>
    <div @class="height"> 180cm </div>
  </div>
</div>

到目前为止,我的代码如下所示:

import csv
import os
import pandas as pd
from selenium import webdriver

chromedriver = "path to chromedriver"
driver = webdriver.Chrome(chromedriver)
driver.get( 'url of a website')

name_row = []
weight_row = []
height_row = []
for i in range(len(driver.find_element_by_xpath('//div[@class="reviews"/div'):
    # Get the first parent (user1)
    driver.find_element_by_xpath('(//div[@class="reviews"/div)' + '[' + str(i + 1) + ']')
    
    # Check if it has elements like name, weight, and height and add it to appropriate list. 
    # For example, name_row.append(driver.find_element_by_xpath("xpath to name if it exists")
    # If missing any element return "None"
    # Then move on to the second parent (user2) and so on

df = pd.DataFrame({'Names': name_row, 'Weight': weight_row, 'Height': height_row})

我希望我的最终结果看起来像

Name Weight Height
Will 50kg 160cm
None 55kg 170cm
Ben None 180cm

我也看过其他帖子,但似乎找不到我正在寻找的答案。

我尝试只做 find_elements_by_xpath 并将每个名称、重量和高度值放在它们各自的列表中,但这不会在这些列表中的任何一个中包含“无”值,最终给我错误的数组长度不一样等等。

【问题讨论】:

    标签: python css selenium web-scraping xpath


    【解决方案1】:

    我会建议这样的事情:

    import csv
    import os
    import pandas as pd
    from selenium import webdriver
    
    chromedriver = "path to chromedriver"
    driver = webdriver.Chrome(chromedriver)
    driver.get( 'url of a website')
    
    names = []
    weights = []
    heights = []
    #wait for first parent element to be visible
    wait.until(EC.visibility_of_element_located((By.XPATH, "//div[@class='reviews']")))
    #let all the elements loaded
    time.sleep(0.5)
    #get all the reviews list
    reviews = driver.find_elements_by_xpath("//div[@class='reviews']")
    #iterate over reviews and get each inner element per each review
    for i in range(len(reviews)):
        #get name element for current review. This returns list of web elements
        name = review[i].find_elements_by_xpath(".//div[@class='name']")
        #in case the element exists the list is non-empty so it is interpreted as Boolean True
        if(name):
            #extract actual element value and append it to the list of names
            names.append(name[0].text)
        #otherwise append "None"
        else:
            names.append("None")
        #the same for other parameters
        weight = review[i].find_elements_by_xpath(".//div[@class='weight']")
        if(weight):
            weights.append(weight[0].text)
        else:
            weights.append("None")
        height = review[i].find_elements_by_xpath(".//div[@class='height']")
        if(height):
            heights.append(height[0].text)
        else:
            heights.append("None")
    
    

    【讨论】:

      【解决方案2】:

      现在你得到了父元素,你现在可以再次为父元素中的子元素像你一样

      parents=driver.find_element_by_xpath('(//div[@class="reviews"/div).find_elements_by_tag_name("div")
      

      使用父元素进行循环,并检查内部是否存在其他元素。

      for parent in parents:
          parent.find_element_by_class_name('name')
          ....weight 
          Height
      

      Here's 文档

      当你想通过类名定位一个元素时使用这个。使用此策略,将返回具有匹配类名称属性的第一个元素。如果没有元素具有匹配的类名属性,则会引发 NoSuchElementException。

      所以,现在您可以在检查名称、重量时执行try except .. 如果不写无则获取数据

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-16
        • 1970-01-01
        • 1970-01-01
        • 2012-08-30
        • 1970-01-01
        • 2017-04-04
        相关资源
        最近更新 更多