Selenium从WebDriver获取HTML(或JSON)响应

时间:2014-10-06 17:28:23

标签: java ajax json selenium selenium-webdriver

我有以下代码,但它不能正常工作

public static String getHTMLResponse(String url){
   String body = (String) js.executeScript("$.ajax({url:\""+ url + "\", success:function(result){ return result;}});");
    return body;
}

由于某种原因,这总是返回null。

有没有人试图从webdriver中的ajax获取CURL响应?我之前在java中这样做,但我不断得到证书错误,只是想要更可靠的东西。

提前致谢!

3 个答案:

答案 0 :(得分:3)

好的,所以Jason Smiley发布了一个解决方案,但没有解释问题是什么以及解决方案是如何运作的。

第一个问题是传递给executeScript的脚本没有返回任何内容。 executeScript做的是在function () { ... }中包装您传递给它的脚本。因此,$.ajax(...)形式的某些内容将在浏览器中执行:

function () {
    $.ajax(...);
}

这显然不会返回任何内容,如果脚本为2 + 2它不会返回4,因为它将执行为:

function () {
    2 + 2;
}

传递给executeScript的脚本必须是return 2 + 2

但是,在这里,只需添加此return即可解决问题。还有一个问题是$.ajax是异步函数。执行$.ajax时,会立即返回。传递给它的函数存储在 future 执行中。如果$.ajax立即返回,那么它返回的值不能可能是给它的任何函数的返回值,因为它们尚未执行 。相反,传递给$.ajax的函数会执行,无论它们提供给return的任何内容都无法通过您的代码检索。你唯一能做的就是在函数内部使用你关心的值,或者将它传递给另一个函数。

解决方案是使用专为异步执行而设计的executeAsyncScript。这个函数就像executeScript一样,但是添加了一个参数,它是一个回调函数,应该在脚本执行完毕后调用它,并且应该使用你希望executeAsyncScript返回的值调用它。

请注意,绝对没有必要放弃$.ajax。以下应该有效:

public static String getHTMLResponse(String url){
    String body = (String) js.executeAsyncScript(
        "var url = arguments[0];" + 
        "var callback = arguments[1];" +
        "$.ajax({url: url, success: callback});", 
        url);
    return body;
}

请注意,我已设置此代码,以便url作为参数传递,而不是连接到脚本中。我发现这比连接更干净。如果需要解释,arguments是JavaScript虚拟机自动提供的对象。它包含给函数的参数列表。

是否使用$.ajax或直接使用XMLHttpRequest原则是相同的。

答案 1 :(得分:1)

前端开发人员给了我脚本!

   public static String getHTMLResponse(String url){
      String body = (String) js.executeAsyncScript(
            "var callback = arguments[arguments.length - 1];" +
                    "var xhr = new XMLHttpRequest();" +
                    "xhr.open('GET', '"+ url + "', true);" +
                    "xhr.onreadystatechange = function() {" +
                    "  if (xhr.readyState == 4) {" +
                    "    callback(xhr.responseText);" +
                    "  }" +
                    "};" +
                    "xhr.send();");
      return body;
  }

答案 2 :(得分:-1)

从长远来看,上述代码并没有为我工作。我不记得为什么它不起作用(因为它已经有一段时间了)但是这是我的新答案:

/**
 * CURLs the page passed in for the HTML response. Uses AJAX so base domain must match the url.
 *
 * Special exception for MkItem requests
 *
 * @param url   - URL to CURL
 * @param debug - Pass in true for debug output.
 * @return HTML result as a string.
 * @throws IOException
 */
public static String getHTMLResponse(String url, boolean debug) throws IOException {
    if(debug){System.out.println("Making request to:\n\n" + url);}
    String body = "";

    try{
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }
        };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    }catch (Exception e){
        Assert.fail("Exception thrown trying to perform GET request. " + e.getMessage());
    }
    URLConnection con;

    //If not a secure page, use cURL
        /*if(!url.contains("https://")){*/
        try{
            URL temp = new URL(url);
            con = temp.openConnection();
            InputStream in = con.getInputStream();
            String encoding = con.getContentEncoding();
            encoding = encoding == null ? "UTF-8" : encoding;
            body = IOUtils.toString(in, encoding);
        } catch (MalformedURLException e){
            Assert.fail("URL wasn't passed in correctly - " + e.getMessage());
        } catch (IOException e){
            throw e;
        }

    if(debug){ System.out.println("Body:\n"+ body); }

    Assert.assertNotNull("Body returned null for " + url, body);

    return body;
}