选择同一节点上的元素

时间:2018-12-20 23:04:30

标签: python css selenium selenium-webdriver xpath

我正在用Python编写Selenium自动化脚本。作为一个过程,我需要收集一些元素。以下是示例html(我编辑看起来很简单)。当我执行搜索时,我得到的搜索结果与下面类似。

现在,我需要Restaurants中的元素列表并执行一些操作。酒吧,购物,咖啡也是如此。

问题是lh和li在同一节点级别。

我尝试了以下xpath,但是它仅选择lh元素

//ul[@id='searchresults']//ancestor::lh

我也经历了有用的Concept XML XLST preceding-sibling and ancestor。但是,还没有找到解决方案

示例html代码:

<ul id="searchresults">
    <lh style="">Restaurants</lh>
    <li title="Chamber"><span>Chamber</span></li>
    <li title="Chillies"><span>Chillies</span></li>
    <li title="Sushi Ville"><span>Sushi Ville</span></li>
    <li title="Toasters"><span>Toasters</span></li>
    <li title="Joe Grills"><span>Joe Grills</span></li>
    <lh style="">Bars</lh>
    <li title="Y Cocktails"><span>Y Cocktails</span></li>
    <li title="Z Brewery"><span>Z Brewery</span></li>
    <li title="X Drinks"><span>X Drinks</span></li>
    <lh style="">Shopping</lh>
    <li title="Pacific"><span>Pacific</span></li>
    <li title="Spencers"><span>Spencers</span></li>
    <li title="Hays"><span>Hays</span></li>
    <lh style="">Coffee</lh>
    <li title="Roasters"><span>Roasters</span></li>
    <li title="Coffee Beans"><span>Coffee Beans</span></li>
    <li title="Coffee Cafe"><span>Coffee Cafe</span></li>
</ul>

非常感谢您的帮助,请让我知道我缺少或需要的任何信息,这些信息将有助于解决此问题。

2 个答案:

答案 0 :(得分:1)

您可以执行以下操作:

  • 遍历“列表标题”元素
  • 对于每个“列表标题”,​​获取以下兄弟姐妹,并收集“标签”(将这些li元素文本命名为“标签”),直到lh兄弟姐妹被满足

遵循以下原则:

for lh in driver.find_elements_by_xpath("//ul[@id='searchresults']//lh"):
    restaurant = lh.text

    tags = []
    for element in lh.find_elements_by_xpath("./following-sibling::*"):
        if element.tag_name == 'lh':
            break

        tags.append(element.text)

    print(restaurant, tags)

答案 1 :(得分:1)

我想出了一些简单的方法,即在会话中运行一些javascript,这会将具有列表标题(LH)名称的自定义属性添加到以下每个列表项(LI)中,您需要更改自定义属性名称满足您的需求而又不与当前属性冲突。

my_js = """let currentLh;
document.querySelectorAll(arguments[0]).forEach(function (elem) {
    if (elem.tagName === "LH") {
        currentLh = elem.textContent.toLowerCase();
    } else {
        elem.setAttribute("my-custom-attr", currentLh);
    }
"""

driver.execute_script(my_js, 'ul#searchresults > *')
my_restaurant_list = driver.find_elemets_by_css_selector('li[my-custom-attr="restaurant"]')
my_bar_list = driver.find_elemets_by_css_selector('li[my-custom-attr="bars"]')
my_shopping_list = driver.find_elemets_by_css_selector('li[my-custom-attr="shopping"]')
my_coffee_list = driver.find_elemets_by_css_selector('li[my-custom-attr="coffee"]')

这使用了JS NodeList.forEach函数,该函数可能并非在所有浏览器中都可用,如果发现问题,则必须为无序列表中的所有元素找到一种更具移植性的循环解决方案。