将Jsoup“元素”转换为WebDriver“WebElement”?

时间:2016-03-17 20:04:44

标签: java selenium webdriver jsoup

所以我发现如果你使用WebDriver获取页面源,你实际上得到了整个DOM的生成源(而不仅仅是加载页面的HTML源代码)。然后,您可以使用此String生成Jsoup文档。这很酷,因为在搜索元素时Jsoup比WebDriver快得多,它也有更好的API。

那么,无论如何将Jsoup元素转换为WebDriver WebElement?我在stackoverflow上看到另一篇关于使用方法从Jsoup文档生成xpath的帖子,但这不是我正在寻找的,因为WebDriver仍然需要解析页面并使用Xpath来查找元素,从而破坏了目的(除非你的porpuse纯粹使用Jsoup作为其卓越的Selector方法)。

我想尝试使用Jsoup为WebDriver找到WebElements的原因是因为在某些网站上,WebDriver非常慢(我为自动化数百个第三方网站的公司工作,我们无法控制这些网站)

2 个答案:

答案 0 :(得分:2)

这里的交互式和非交互式工具之间似乎存在混淆。

WebDriver测试通常很慢(根据我的经验)由于不必要和防御性的等待和延迟,使用不正确理解的框架,并且通常由初级或外包开发人员编写 - 但从根本上也是因为WebDriver模仿真实用户的行为在真实浏览器上“实时”,并使用API​​(基于specification)和协议与浏览器应用进行通信。这是互动的。

(对HtmlUnit,PhantomJS等不太重要)

相比之下,Jsoup只是一个美化的HTTP客户端,具有额外的解析功能。它是非交互式的,最终可以处理快照数据字符串。我们预计它的特定用例会更快

显然两者都是某种类型的HTTP客户端,并且可以共享静态Web内容,这就是为什么WebDriver可以将数据传递给Jsoup进行处理(尽管我之前从未听说过这种用例)。

然而,Jsoup永远不会将其Element之一(包含某些属性的Java快照对象)转换为WebDriver WebElement,这更像是一个真实的“实时”代理。 Firefox或Chrome等程序中的交互式对象。 (再说一次,HtmlUnit,PhantomJS等等)。

因此,您需要确定交互性是否对您很重要。如果模仿真实用户至关重要,那么WebDriver必须使用真实的浏览器“驱动”这个过程。

如果不是,那么你可以考虑像HtmlUnit和(特别是)PhantomJS这样的无头浏览器,因为他们将能够以HTTP库和Jsoup不能的方式执行JavaScript并更新DOM。然后,您可以将输出传递给Jsoup等。

潜在地,如果您沿着PhantomJS路线走下去,您可以使用JavaScript API在那里进行所有解析。请参阅:Use PhantomJS to extract html and text等。

对于很多人而言,交互性并不重要,而且完全放弃WebDriver并依赖库来更快。

答案 1 :(得分:0)

我知道这个问题太老了,但是只要有人看到这个问题,就可以找到这个答案。这将从您的Jsoup元素返回一个xpath。我将其翻译成Java,但是我从中复制代码的原始来源是https://stackoverflow.com/a/48376038/13274510

然后可以将xpath与WebDriver一起使用

编辑:代码现在可以使用

public static String jsoupToXpath(Element element) {
    String xpath = "/";
    List<String> components = new ArrayList<>();

    Element child = element.tagName().isEmpty() ? element.parent() : element;
    System.out.println(child.tag());
    while (child.parent() != null){
        Element parent = child.parent();
        Elements siblings = parent.children();
        String componentToAdd = null;

        if (siblings.size() == 1) {
            componentToAdd = child.tagName();
        } else {
            int x = 1;
            for(Element sibling: siblings){
                if (child.tagName().equals(sibling.tagName())){
                    if (child == sibling){
                        break;
                    } else {
                        x++;
                    }
                }
            }
            componentToAdd = String.format("%s[%d]", child.tagName(), x);
        }
        components.add(componentToAdd);
        child = parent;
    }

    List<String> reversedComponents = new ArrayList<>();
    for (int i = components.size()-1; i > 0; i--){
        reversedComponents.add(components.get(i));
    }
    xpath = xpath + String.join("/", reversedComponents);

    return xpath;
}