【问题标题】:Is there a way to reverse look up element's XPath usig selenium有没有办法使用 selenium 反向查找元素的 XPath
【发布时间】:2019-09-09 22:49:11
【问题描述】:

这么多听起来很愚蠢,但我需要在通过 Selenium 找到一个元素后知道它的 XPath。原因是当我查找该元素时,我使用了文本搜索,因此我不知道确切的 XPath,我可以使用它来获取上述元素的兄弟姐妹。即使不使用 Selenium,如果有办法通过 BeautifulSoup 等间接实现这一点,那就太好了。

我的程序的当前输出是这样的:

(Pdb) browser.find_elements_by_xpath('//*[contains(text(), "5StarMAX")]')

[<selenium.webdriver.remote.webelement.WebElement (session="8994add1f6f087a917bbb33f69f15f7c", element="7bad823c-1f3
e-445b-9a47-6d934fcacb8a")>, <selenium.webdriver.remote.webelement.WebElement (session="8994add1f6f087a917bbb33f69f1
5f7c", element="551df9b7-d2cb-4021-bb30-a2723c835adf")>, <selenium.webdriver.remote.webelement.WebElement (session="
8994add1f6f087a917bbb33f69f15f7c", element="b864c44b-8220-4010-843c-fbf0cfa1ba13")>, <selenium.webdriver.remote.webe
lement.WebElement (session="8994add1f6f087a917bbb33f69f15f7c", element="59d9f40d-d318-4e0d-9ab1-aa9df42d037c")>, <se
lenium.webdriver.remote.webelement.WebElement (session="8994add1f6f087a917bbb33f69f15f7c", element="260795bd-e7c6-43
b1-a8f0-10b36eb69787")>, <selenium.webdriver.remote.webelement.WebElement (session="8994add1f6f087a917bbb33f69f15f7c
", element="4e46be00-4578-4741-adc9-a5b6fc67a3e9")>, <selenium.webdriver.remote.webelement.WebElement (session="8994
add1f6f087a917bbb33f69f15f7c", element="df66abcb-bd99-4670-af07-404c085afb28")>]

如您所见,我找到了该元素,但我想以编程方式(使用 Python)搜索其兄弟元素。没有办法——至少我知道(在尝试使用页面上各处的开发人员工具定位它之后)——知道元素本身的 XPath。

【问题讨论】:

    标签: python selenium selenium-webdriver web-scraping


    【解决方案1】:

    尝试同时使用BeautifulSoupSelenium

    您可以尝试使用this solution 使用xpath_soup()

    选项-A

    import re
    import itertools
    from bs4 import BeautifulSoup
    html = '<html><body><div><p>Hello World</p></div></body></html>'
    soup = BeautifulSoup(html, 'lxml')
    elem = soup.find(string=re.compile('Hello World'))
    xpath_soup(elem)
    

    输出

    '/html/body/div/p'
    

    选项-B

    引用as-is。您可能需要在这里和那里更改一些东西才能使其适合您。 source

    import re, itertools
    from selenium import webdriver
    from bs4 import BeautifulSoup as BS
    
    def xpath_soup(element):
        components = []
        child = element if element.name else element.parent
        for parent in child.parents:
            siblings = parent.find_all(child.name, recursive=False)
            components.append(
                child.name
                if siblings == [child] else
                '%s[%d]' % (child.name, 1 + siblings.index(child))
                )
            child = parent
        components.reverse()
        return '/%s' % '/'.join(components)
    
    def main():
        driver = webdriver.PhantomJS(executable_path='phantomjs.exe')
        driver.set_window_size(1400,1000)
        driver.get("https://www.pinterest.com/search/pins/?q=old")
    
        buttons = driver.find_elements_by_xpath('//button[@data-test-id="seemoretoggle"]');
        for btn in buttons:
            btn.click()
    
        html = driver.page_source
        soup = BS(html, 'html.parser')
        elem = soup.find(string=re.compile('Tiny House interior'))
        print(elem)
        xpath_soup(elem)
        print(xpath_soup(elem))
    
    if __name__ == '__main__':
        main()
    

    也检查一下:

    1. https://qxf2.com/blog/auto-generate-xpaths-using-python/
    2. https://gist.github.com/ergoithz/6cf043e3fdedd1b94fcf

    【讨论】:

    • 谢谢。这很酷!我会在绝望的时候使用这种方法。目前,我还发现在 XPaths 中使用 following-sibling 至少可以解决我需要遍历兄弟姐妹的问题(如果您愿意查看,我已经在这里提出了一个问题:stackoverflow.com/q/57862253/1330974)。如果在接下来的几天内没有人提出更好的建议,将接受您上面的答案。再次感谢!
    【解决方案2】:

    一旦找到父元素的 XPath,就不需要它了。您可以链接.find_element_*() 电话。例如,下面的代码会找到包含文本“5StarMAX”的元素,然后第二个 find 调用会找到第一个元素的子 DIV。

    请注意,第二个 XPath 以 . 开头。这意味着从第一个元素 element 开始搜索。

    element = browser.find_element_by_xpath('//*[contains(text(), "5StarMAX")]')
    element.find_element_by_xpath('./div')
    

    如果有帮助...使用单个 XPath 来表示将两个结果结合起来会是这样的

    //*[contains(text(), "5StarMAX")]/div
    

    【讨论】:

    • 感谢您的建议!我从你那里了解到'./div' 允许从被调用的父元素缩小搜索范围。话虽如此,我正在寻找更多包含 '5StarMax' 的标签的兄弟姐妹,我相信(如果我错了,请纠正我)你的建议只会让我更深入地挖掘 below(不是平行于) 包含'5StarMax' 的标签。再次感谢您的帮助!
    • 使用 XPath,您可以从要搜索的元素开始在 DOM 中向上、向下或横向移动。看看一些XPath documentation,尤其是 Axes。您可以使用following-siblingpreceding-sibling 来查找您拥有的元素的兄弟姐妹。如果您发布一些 HTML 并指出您找到的元素,然后根据找到的元素指出您想要找到的兄弟元素,我们可以计算出所需的 XPath。
    • 非常感谢!我能够使用following-sibling 来获取我需要的元素。这是一个非常有用的提示,再次感谢! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 2015-11-10
    • 1970-01-01
    • 2021-10-11
    • 2015-03-29
    • 1970-01-01
    • 2021-01-11
    相关资源
    最近更新 更多