วิธีรับรหัสตอบกลับ HTTP โดยใช้ Selenium WebDriver


109

ฉันได้เขียนการทดสอบด้วย Selenium2 / WebDriver และต้องการทดสอบว่า HTTP Request ส่งคืน HTTP 403 Forbidden หรือไม่

เป็นไปได้หรือไม่ที่จะรับรหัสสถานะการตอบกลับ HTTP ด้วย Selenium WebDriver



นี่จะไม่ซ้ำกันเพราะคำถามอื่นเน้นที่ Python แต่คำถามนี้อยู่ใน java
Ralph

1
ขอบคุณฉันเข้าใจแล้ว แต่ในที่สุดคำถามก็จบลงที่webdriverข้อ จำกัด และข้อ จำกัด เหล่านี้เหมือนกันสำหรับทั้ง Python และ Java;)
maxkoryukov

2
@maxkoryukov: แต่มีภาษาที่ใช้ในการแก้ไขปัญหา
Ralph

คำตอบ:



42

เป็นไปได้ที่จะรับรหัสตอบกลับของคำขอ http โดยใช้ Selenium และ Chrome หรือ Firefox สิ่งที่คุณต้องทำคือเริ่ม Chrome หรือ Firefox ในโหมดบันทึก ฉันจะแสดงตัวอย่างด้านล่าง

java + Selenium + Chrome นี่คือตัวอย่างของ java + Selenium + Chrome แต่ฉันเดาว่ามันสามารถทำได้ในทุกภาษา (python, c #, ... )

สิ่งที่คุณต้องทำคือบอกให้ chromedriver ทำ "Network.enable" สามารถทำได้โดยเปิดใช้งานการบันทึกประสิทธิภาพ

LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);

หลังจากการร้องขอเสร็จสิ้นสิ่งที่คุณต้องทำคือรับและทำซ้ำบันทึก Perfomance และค้นหา "Network.responseReceived" สำหรับ url ที่ร้องขอ:

LogEntries logs = driver.manage().logs().get("performance");

นี่คือรหัส:

import java.util.Iterator;
import java.util.logging.Level;

import org.json.JSONException;
import org.json.JSONObject;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;

public class TestResponseCode
{
    public static void main(String[] args)
    {
        // simple page (without many resources so that the output is
        // easy to understand
        String url = "http://www.york.ac.uk/teaching/cws/wws/webpage1.html";

        DownloadPage(url);
    }

    private static void DownloadPage(String url)
    {
        ChromeDriver driver = null;

        try
        {
            ChromeOptions options = new ChromeOptions();
            // add whatever extensions you need
            // for example I needed one of adding proxy, and one for blocking
            // images
            // options.addExtensions(new File(file, "proxy.zip"));
            // options.addExtensions(new File("extensions",
            // "Block-image_v1.1.crx"));

            DesiredCapabilities cap = DesiredCapabilities.chrome();
            cap.setCapability(ChromeOptions.CAPABILITY, options);

            // set performance logger
            // this sends Network.enable to chromedriver
            LoggingPreferences logPrefs = new LoggingPreferences();
            logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
            cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);

            driver = new ChromeDriver(cap);

            // navigate to the page
            System.out.println("Navigate to " + url);
            driver.navigate().to(url);

            // and capture the last recorded url (it may be a redirect, or the
            // original url)
            String currentURL = driver.getCurrentUrl();

            // then ask for all the performance logs from this request
            // one of them will contain the Network.responseReceived method
            // and we shall find the "last recorded url" response
            LogEntries logs = driver.manage().logs().get("performance");

            int status = -1;

            System.out.println("\nList of log entries:\n");

            for (Iterator<LogEntry> it = logs.iterator(); it.hasNext();)
            {
                LogEntry entry = it.next();

                try
                {
                    JSONObject json = new JSONObject(entry.getMessage());

                    System.out.println(json.toString());

                    JSONObject message = json.getJSONObject("message");
                    String method = message.getString("method");

                    if (method != null
                            && "Network.responseReceived".equals(method))
                    {
                        JSONObject params = message.getJSONObject("params");

                        JSONObject response = params.getJSONObject("response");
                        String messageUrl = response.getString("url");

                        if (currentURL.equals(messageUrl))
                        {
                            status = response.getInt("status");

                            System.out.println(
                                    "---------- bingo !!!!!!!!!!!!!! returned response for "
                                            + messageUrl + ": " + status);

                            System.out.println(
                                    "---------- bingo !!!!!!!!!!!!!! headers: "
                                            + response.get("headers"));
                        }
                    }
                } catch (JSONException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            System.out.println("\nstatus code: " + status);
        } finally
        {
            if (driver != null)
            {
                driver.quit();
            }
        }
    }
}

ผลลัพธ์มีลักษณะดังนี้:

    Navigate to http://www.york.ac.uk/teaching/cws/wws/webpage1.html

    List of log entries:

    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.frameAttached","params":{"parentFrameId":"172.1","frameId":"172.2"}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.frameStartedLoading","params":{"frameId":"172.2"}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.frameNavigated","params":{"frame":{"securityOrigin":"://","loaderId":"172.1","name":"chromedriver dummy frame","id":"172.2","mimeType":"text/html","parentId":"172.1","url":"about:blank"}}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.frameStoppedLoading","params":{"frameId":"172.2"}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.frameStartedLoading","params":{"frameId":"3928.1"}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Network.requestWillBeSent","params":{"request":{"headers":{"Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"},"initialPriority":"VeryHigh","method":"GET","mixedContentType":"none","url":"http://www.york.ac.uk/teaching/cws/wws/webpage1.html"},"frameId":"3928.1","requestId":"3928.1","documentURL":"http://www.york.ac.uk/teaching/cws/wws/webpage1.html","initiator":{"type":"other"},"loaderId":"3928.1","wallTime":1.47619492749007E9,"type":"Document","timestamp":20226.652971}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Network.responseReceived","params":{"frameId":"3928.1","requestId":"3928.1","response":{"headers":{"Accept-Ranges":"bytes","Keep-Alive":"timeout=4, max=100","Cache-Control":"max-age=300","Server":"Apache/2.2.22 (Ubuntu)","Connection":"Keep-Alive","Content-Encoding":"gzip","Vary":"Accept-Encoding","Expires":"Tue, 11 Oct 2016 14:13:47 GMT","Content-Length":"1957","Date":"Tue, 11 Oct 2016 14:08:47 GMT","Content-Type":"text/html"},"connectionReused":false,"timing":{"pushEnd":0,"workerStart":-1,"proxyEnd":-1,"workerReady":-1,"sslEnd":-1,"pushStart":0,"requestTime":20226.65335,"sslStart":-1,"dnsStart":0,"sendEnd":31.6569999995409,"connectEnd":31.4990000006219,"connectStart":0,"sendStart":31.5860000009707,"dnsEnd":0,"receiveHeadersEnd":115.645999998378,"proxyStart":-1},"encodedDataLength":-1,"remotePort":80,"mimeType":"text/html","headersText":"HTTP/1.1 200 OK\r\nDate: Tue, 11 Oct 2016 14:08:47 GMT\r\nServer: Apache/2.2.22 (Ubuntu)\r\nAccept-Ranges: bytes\r\nCache-Control: max-age=300\r\nExpires: Tue, 11 Oct 2016 14:13:47 GMT\r\nVary: Accept-Encoding\r\nContent-Encoding: gzip\r\nContent-Length: 1957\r\nKeep-Alive: timeout=4, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n","securityState":"neutral","requestHeadersText":"GET /teaching/cws/wws/webpage1.html HTTP/1.1\r\nHost: www.york.ac.uk\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n","url":"http://www.york.ac.uk/teaching/cws/wws/webpage1.html","protocol":"http/1.1","fromDiskCache":false,"fromServiceWorker":false,"requestHeaders":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Upgrade-Insecure-Requests":"1","Connection":"keep-alive","User-Agent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36","Host":"www.york.ac.uk","Accept-Encoding":"gzip, deflate, sdch","Accept-Language":"en-GB,en-US;q=0.8,en;q=0.6"},"remoteIPAddress":"144.32.128.84","statusText":"OK","connectionId":11,"status":200},"loaderId":"3928.1","type":"Document","timestamp":20226.770012}}}
    ---------- bingo !!!!!!!!!!!!!! returned response for http://www.york.ac.uk/teaching/cws/wws/webpage1.html: 200
    ---------- bingo !!!!!!!!!!!!!! headers: {"Accept-Ranges":"bytes","Keep-Alive":"timeout=4, max=100","Cache-Control":"max-age=300","Server":"Apache/2.2.22 (Ubuntu)","Connection":"Keep-Alive","Content-Encoding":"gzip","Vary":"Accept-Encoding","Expires":"Tue, 11 Oct 2016 14:13:47 GMT","Content-Length":"1957","Date":"Tue, 11 Oct 2016 14:08:47 GMT","Content-Type":"text/html"}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Network.dataReceived","params":{"dataLength":2111,"requestId":"3928.1","encodedDataLength":1460,"timestamp":20226.770425}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.frameNavigated","params":{"frame":{"securityOrigin":"http://www.york.ac.uk","loaderId":"3928.1","id":"3928.1","mimeType":"text/html","url":"http://www.york.ac.uk/teaching/cws/wws/webpage1.html"}}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Network.dataReceived","params":{"dataLength":1943,"requestId":"3928.1","encodedDataLength":825,"timestamp":20226.782673}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Network.loadingFinished","params":{"requestId":"3928.1","encodedDataLength":2285,"timestamp":20226.770199}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.loadEventFired","params":{"timestamp":20226.799391}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.frameStoppedLoading","params":{"frameId":"3928.1"}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Page.domContentEventFired","params":{"timestamp":20226.845769}}}
    {"webview":"3b8eaedb-bd0f-4baa-938d-4aee4039abfe","message":{"method":"Network.requestWillBeSent","params":{"request":{"headers":{"Referer":"http://www.york.ac.uk/teaching/cws/wws/webpage1.html","User-Agent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"},"initialPriority":"High","method":"GET","mixedContentType":"none","url":"http://www.york.ac.uk/favicon.ico"},"frameId":"3928.1","requestId":"3928.2","documentURL":"http://www.york.ac.uk/teaching/cws/wws/webpage1.html","initiator":{"type":"other"},"loaderId":"3928.1","wallTime":1.47619492768527E9,"type":"Other","timestamp":20226.848174}}}

    status code: 200

java + Selenium + Firefox ในที่สุดฉันก็พบเคล็ดลับสำหรับ Firefox เช่นกัน คุณจำเป็นต้องเริ่ม Firefox ใช้MOZ_LOGและMOZ_LOG_FILEตัวแปรสภาพแวดล้อมและเข้าสู่ระบบ http (4 = PR_LOG_DEBUG) - map.put("MOZ_LOG", "timestamp,sync,nsHttp:4")การร้องขอในระดับการแก้ปัญหา บันทึกบันทึกในไฟล์ชั่วคราว หลังจากนั้นรับเนื้อหาของไฟล์บันทึกที่บันทึกไว้และแยกวิเคราะห์สำหรับรหัสตอบกลับ (โดยใช้นิพจน์ทั่วไปง่ายๆ) ขั้นแรกให้ตรวจหาจุดเริ่มต้นของคำขอระบุรหัส(nsHttpChannel::BeginConnect [this=000000CED8094000])จากนั้นในขั้นตอนที่สองค้นหารหัสตอบกลับสำหรับ ID คำขอ(nsHttpChannel::ProcessResponse [this=000000CED8094000 httpStatus=200])นั้น

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.GeckoDriverService;

public class TestFirefoxResponse
{
  public static void main(String[] args)
      throws InterruptedException, IOException
  {
    GeckoDriverService service = null;

    // tell firefox to log http requests
    // at level 4 = PR_LOG_DEBUG: debug messages, notices
    // you could log everything at level 5, but the log file will 
    // be larger. 
    // create a temporary log file that will be parsed for
    // response code
    Map<String, String> map = new HashMap<String, String>();
    map.put("MOZ_LOG", "timestamp,sync,nsHttp:4");
    File tempFile = File.createTempFile("mozLog", ".txt");    
    map.put("MOZ_LOG_FILE", tempFile.getAbsolutePath());      

    GeckoDriverService.Builder builder = new GeckoDriverService.Builder();
    service = builder.usingAnyFreePort()
      .withEnvironment(map)
      .build();

    service.start();      

    WebDriver driver = new FirefoxDriver(service);

    // test 200
     String url = "https://api.ipify.org/?format=text";
    // test 404
    // String url = "https://www.advancedwebranking.com/lsdkjflksdjfldksfj";
    driver.get(url);

    driver.quit();

    String logContent = FileUtils.readFileToString(tempFile);

    ParseLog(logContent, url);
  }

  private static void ParseLog(String logContent, String url) throws MalformedURLException
  {
    // this is how the log looks like when the request starts
    // I have to get the id of the request using a regular expression
    // and use that id later to get the response
    //
    //    2017-11-02 14:14:01.170000 UTC - [Main Thread]: D/nsHttp nsHttpChannel::BeginConnect [this=000000BFF27A5000]
    //    2017-11-02 14:14:01.170000 UTC - [Main Thread]: D/nsHttp host=api.ipify.org port=-1
    //    2017-11-02 14:14:01.170000 UTC - [Main Thread]: D/nsHttp uri=https://api.ipify.org/?format=text
    String pattern = "BeginConnect \\[this=(.*?)\\](?:.*?)uri=(.*?)\\s";

    Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Matcher m = p.matcher(logContent);

    String urlID = null;
    while (m.find())
    {
      String id = m.group(1);
      String uri = m.group(2);

      if (uri.equals(url))
      {
        urlID = id;
        break;
      }      
    }

    System.out.println("request id = " + urlID);

    // this is how the response looks like in the log file
    // ProcessResponse [this=000000CED8094000 httpStatus=200]
    // I will use another regular espression to get the httpStatus
    //
    //    2017-11-02 14:45:39.296000 UTC - [Main Thread]: D/nsHttp nsHttpChannel::OnStartRequest [this=000000CED8094000 request=000000CED8014BB0 status=0]
    //    2017-11-02 14:45:39.296000 UTC - [Main Thread]: D/nsHttp nsHttpChannel::ProcessResponse [this=000000CED8094000 httpStatus=200]    

    pattern = "ProcessResponse \\[this=" + urlID + " httpStatus=(.*?)\\]";

    p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    m = p.matcher(logContent);

    if (m.find())
    {
      String responseCode = m.group(1);
      System.out.println("response code found " + responseCode);
    }
    else
    {
      System.out.println("response code not found");
    }
  }
}

ผลลัพธ์สำหรับสิ่งนี้จะเป็น

รหัสคำขอ = 0000007653D67000 พบรหัสการตอบกลับ 200

นอกจากนี้ยังสามารถพบส่วนหัวการตอบกลับได้ในล็อกไฟล์ คุณสามารถรับได้หากต้องการ

    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp http response [
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   HTTP/1.1 404 Not Found
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Accept-Ranges: bytes
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Cache-control: no-cache="set-cookie"
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Content-Type: text/html; charset=utf-8
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Date: Thu, 02 Nov 2017 14:54:36 GMT
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   ETag: "7969-55bc076a61e80"
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Last-Modified: Tue, 17 Oct 2017 16:17:46 GMT
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Server: Apache/2.4.23 (Amazon) PHP/5.6.24
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Set-Cookie: AWSELB=5F256FFA816C8E72E13AE0B12A17A3D540582F804C87C5FEE323AF3C9B638FD6260FF473FF64E44926DD26221AAD2E9727FD739483E7E4C31784C7A495796B416146EE83;PATH=/
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Content-Length: 31081
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Connection: keep-alive
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp     OriginalHeaders
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Accept-Ranges: bytes
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Cache-control: no-cache="set-cookie"
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Content-Type: text/html; charset=utf-8
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Date: Thu, 02 Nov 2017 14:54:36 GMT
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   ETag: "7969-55bc076a61e80"
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Last-Modified: Tue, 17 Oct 2017 16:17:46 GMT
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Server: Apache/2.4.23 (Amazon) PHP/5.6.24
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Set-Cookie: AWSELB=5F256FFA816C8E72E13AE0B12A17A3D540582F804C87C5FEE323AF3C9B638FD6260FF473FF64E44926DD26221AAD2E9727FD739483E7E4C31784C7A495796B416146EE83;PATH=/
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Content-Length: 31081
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp   Connection: keep-alive
    2017-11-02 14:54:36.775000 UTC - [Socket Thread]: I/nsHttp ]
    2017-11-02 14:54:36.775000 UTC - [Main Thread]: D/nsHttp nsHttpChannel::OnStartRequest [this=0000008A65D85000 request=0000008A65D1F900 status=0]
    2017-11-02 14:54:36.775000 UTC - [Main Thread]: D/nsHttp nsHttpChannel::ProcessResponse [this=0000008A65D85000 httpStatus=404]

2
สำหรับผู้ที่กำลังมองหาสิ่งนี้โปรดทราบว่าเครือข่ายของโครเมียมเปิดใช้งานแทรกส่วนหัวพิเศษในคำขอ HTTP ทุกรายการที่ทำในขณะที่เปิดใช้งาน
ชื่อปลอม

2
สวัสดีฉันสามารถรับรหัสตอบกลับได้ แต่ฉันจะรับเนื้อหาตอบกลับได้อย่างไร ฉันไม่เห็นในการตอบสนอง JSONObject
LINGS

@LINGS คุณสามารถใช้ driver.getPageSource () ได้ แต่โปรดใช้ความระมัดระวังเนื่องจากโดยปกติแล้วจะมีคำขอจาวาสคริปต์หลายด้านที่สามารถเปลี่ยน Dom คุณสามารถรอให้องค์ประกอบบางส่วนของเพจของคุณปรากฏในโดมจากนั้นรับแหล่งที่มาของเพจ อีกสถานการณ์หนึ่งคือเฟรม หากคุณมีเฟรมคุณต้องเปลี่ยนเป็นเฟรมจากนั้นรับซอร์สโค้ดของเฟรมนั้น - driver.switchTo (). frame ();
Stefan Matei

ฉันพยายามติดตั้งโค้ดของคุณด้วยRemoteWebDriverเนื่องจากวิธีการของฉันเขียนด้วย RemoteWebdriver คุณมีความคิดเกี่ยวกับวิธีการใช้งานกับRemoteWebDriverหรือไม่?
M3trix

2
@IvayloSlavov สคริปต์ Chrome ทำงานให้ฉันด้วย 4.0.0-alpha-4 โปรดดูตัวอย่างนี้github.com/smatei/SeleniumChromeHTTPResponse
Stefan Matei

16

คุณสามารถใช้พร็อกซี BrowserMob เพื่อบันทึกคำขอและการตอบกลับด้วยไฟล์HttpRequestInterceptor. นี่คือตัวอย่างใน Java:

// Start the BrowserMob proxy
ProxyServer server = new ProxyServer(9978);
server.start();

server.addResponseInterceptor(new HttpResponseInterceptor()
{
    @Override
    public void process(HttpResponse response, HttpContext context)
        throws HttpException, IOException
    {
        System.out.println(response.getStatusLine());
    }
});

// Get selenium proxy
Proxy proxy = server.seleniumProxy();

// Configure desired capability for using proxy server with WebDriver
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, proxy);

// Set up driver
WebDriver driver = new FirefoxDriver(capabilities);

driver.get("http://stackoverflow.com/questions/6509628/webdriver-get-http-response-code");

// Close the browser
driver.quit();

ฉันใช้โซลูชันของคุณ แต่ด้วยพร็อกซีการโหลดหน้าเว็บช้ามาก มีความคิดอย่างไร? ดูคำถามของฉันด้วย: stackoverflow.com/questions/21043928/…
Charlie

1
ขณะนี้พร็อกซี BrowserMob ดั้งเดิมไม่ได้รับการสนับสนุนและบิตเน่า เรามีทางแยกโอเพ่นซอร์สของพร็อกซีเบราว์เซอร์ที่มีการยืนยันประสิทธิภาพเพจและเครือข่ายในตัว github.com/browserup/browserup-proxy
ebeland

13

สำหรับคนที่ใช้ Python คุณอาจพิจารณาSelenium Wireซึ่งเป็นไลบรารีที่ฉันพัฒนาขึ้นเพื่อตรวจสอบคำขอของเบราว์เซอร์ระหว่างการทดสอบ

คุณสามารถเข้าถึงคำขอผ่านdriver.requestsแอตทริบิวต์:

from seleniumwire import webdriver  # Import from seleniumwire

# Create a new instance of the Firefox driver
driver = webdriver.Firefox()

# Go to the Google home page
driver.get('https://www.google.com')

# Access requests via the `requests` attribute
for request in driver.requests:
    if request.response:
        print(
            request.url,
            request.response.status_code,
            request.response.headers['Content-Type']
        )

พิมพ์:

https://www.google.com/ 200 text/html; charset=UTF-8
https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png 200 image/png
https://consent.google.com/status?continue=https://www.google.com&pc=s&timestamp=1531511954&gl=GB 204 text/html; charset=utf-8
https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png 200 image/png
https://ssl.gstatic.com/gb/images/i2_2ec824b0.png 200 image/png
https://www.google.com/gen_204?s=webaft&t=aft&atyp=csi&ei=kgRJW7DBONKTlwTK77wQ&rt=wsrt.366,aft.58,prt.58 204 text/html; charset=UTF-8
...

ไลบรารีช่วยให้คุณสามารถเข้าถึงส่วนหัวรหัสสถานะเนื้อหาเนื้อหาตลอดจนความสามารถในการแก้ไขส่วนหัวและเขียน URL ใหม่


ฉันกำลังพยายามใช้สิ่งนี้กับ webdriver.Remote แต่ฉันได้รับ "AttributeError: วัตถุ 'WebDriver' ไม่มีแอตทริบิวต์ 'การร้องขอ'" เป็นเพราะซีลีเนียมลวดไม่รองรับไดรเวอร์ระยะไกลหรือไม่ เอกสารทางการขาดความสิ้นหวัง ขอบคุณ!
Lennart Rolland

@LennartRolland หนึ่งในข้อ จำกัดของ Selenium Wire คือมันจะทำงานบนเครื่องเดียวกันที่ใช้เบราว์เซอร์เท่านั้น ไม่รองรับการใช้การตั้งค่าระยะไกลในปัจจุบัน
Will Keeling

1
@MohamedImran หากคุณสนใจคำตอบที่เฉพาะเจาะจงคุณสามารถใช้driver.wait_for_request()วิธีการค้นหาคำขอที่คุณสนใจคำตอบดูเอกสารสำหรับข้อมูลเพิ่มเติม
Will Keeling

1
@MohamedImran วิธีนี้ใช้ regex ดังนั้นคุณสามารถส่งผ่านเพียงบางส่วนของ URL ที่ไม่ซ้ำกัน เช่นเพื่อให้ตรงกับhttp://myserver.com/some/path/12345/คุณสามารถผ่านdriver.wait_for_request(‘.*/12345/‘)
Will Keeling

1
@MohamedImran คุณไม่จำเป็นต้องวนซ้ำ
Will Keeling

10

ฉันก็ประสบปัญหาเดียวกันและติดอยู่เป็นเวลาหลายวัน แต่หลังจากการวิจัยบางอย่างฉันพบว่าเราสามารถใช้ "--remote-debugging-port" ของ Chrome เพื่อสกัดกั้นคำขอร่วมกับโปรแกรมควบคุมเว็บซีลีเนียมได้ ใช้ Pseudocode ต่อไปนี้เป็นข้อมูลอ้างอิง: -

สร้างอินสแตนซ์ของไดรเวอร์โครเมี่ยมพร้อมการดีบักระยะไกล

int freePort = findFreePort();

chromeOptions.addArguments("--remote-debugging-port=" + freePort);

ChromeDriver driver = new ChromeDriver(chromeOptions);`

โทรไปที่http://127.0.0.1:freePort

String response = makeGetCall( "http://127.0.0.1" + freePort  + "/json" );

แยก URL ของ webSocket ของ Chrome เพื่อฟังคุณสามารถดูการตอบสนองและดูวิธีดึงข้อมูลได้

String webSocketUrl = response.substring(response.indexOf("ws://127.0.0.1"), response.length() - 4);

เชื่อมต่อกับซ็อกเก็ตนี้คุณสามารถใช้ asyncHttp

socket = maketSocketConnection( webSocketUrl );

เปิดใช้งานการจับภาพเครือข่าย

socket.send( { "id" : 1, "method" : "Network.enable" } );

ตอนนี้ chrome จะส่งเหตุการณ์ที่เกี่ยวข้องกับเครือข่ายทั้งหมดและจับภาพดังต่อไปนี้

socket.onMessageReceived( String message ){

    Json responseJson = toJson(message);
    if( responseJson.method == "Network.responseReceived" ){
       //extract status code
    }
}

driver.get("http://stackoverflow.com");

คุณสามารถทำทุกอย่างที่กล่าวถึงในไซต์เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ ดูhttps://chromedevtools.github.io/devtools-protocol/ หมายเหตุ: - ใช้ chromedriver 2.39 ขึ้นไป

ฉันหวังว่ามันจะช่วยใครสักคน

การอ้างอิง: การใช้โปรโตคอลการดีบักระยะไกลของ Google Chrome


เยี่ยมมากฉันดีใจที่มีวิธีการนี้! ฉันเพียงแค่ต้องการมีห้องสมุด (สำหรับ Ruby selenium-webdriverในกรณีของฉัน) ที่ใช้งานโดยอัตโนมัติNetwork.enableและสัมผัสวิธีง่ายๆในการตรวจสอบการตอบสนองที่ผ่านมา ... driver.response.status_codeเหมือน บางทีสักวันฉันจะไปเพิ่มว่า ... :)
Tyler Rick

ในกรณีโปรแกรมเมอร์ทับทิมอื่น ๆ ที่เจอนี้ผมสร้างอัญมณีgithub.com/TylerRick/capybara-chrome_response_headersที่ช่วยให้คุณได้รับรหัสสถานะ HTTP จากการทดสอบ Capybara / RSpec status_codeโดยเพียงแค่การเรียกร้อง ใช้โปรโตคอลการดีบักระยะไกลของ Chrome ดังในตัวอย่างนี้
Tyler Rick

ขอบคุณเพื่อน! ใช้ได้กับฉัน chrome 76 + selenium 3.141
jessez

9

รับรหัสตอบกลับในภาษาใดก็ได้ (โดยใช้ JavaScript):

หากการทดสอบซีลีเนียมของคุณทำงานในเบราว์เซอร์รุ่นใหม่วิธีง่ายๆในการรับรหัสตอบกลับคือส่งซิงโครนัสXMLHttpRequest* และตรวจสอบstatusการตอบกลับ:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://exampleurl.ex', false);
xhr.send(null);

assert(200, xhr.status);

คุณสามารถใช้เทคนิคนี้กับภาษาโปรแกรมใดก็ได้โดยขอให้ซีลีเนียมรันสคริปต์ ตัวอย่างเช่นใน Java คุณสามารถใช้JavascriptExecutor.executeScript()เพื่อส่งXMLHttpRequest:

final String GET_RESPONSE_CODE_SCRIPT =
    "var xhr = new XMLHttpRequest();" +
    "xhr.open('GET', arguments[0], false);" +
    "xhr.send(null);" +
    "return xhr.status";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver;
Assert.assertEquals(200,
    javascriptExecutor.executeScript(GET_RESPONSE_CODE_SCRIPT, "http://exampleurl.ex"));

* คุณสามารถส่งแบบอะซิงโครนัสXMLHttpRequestแทนได้ แต่คุณจะต้องรอให้เสร็จสิ้นก่อนดำเนินการทดสอบต่อไป

รับรหัสตอบกลับใน Java:

คุณสามารถรับโค้ดตอบกลับใน Java โดยใช้URL.openConnection()และHttpURLConnection.getResponseCode():

URL url = new URL("http://exampleurl.ex");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");

// You may need to copy over the cookies that Selenium has in order
// to imitate the Selenium user (for example if you are testing a
// website that requires a sign-in).
Set<Cookie> cookies = webDriver.manage().getCookies();
String cookieString = "";

for (Cookie cookie : cookies) {
    cookieString += cookie.getName() + "=" + cookie.getValue() + ";";
}

httpURLConnection.addRequestProperty("Cookie", cookieString);
Assert.assertEquals(200, httpURLConnection.getResponseCode());

วิธีนี้อาจนำไปใช้กับภาษาอื่น ๆ ได้เช่นกัน แต่จะต้องมีการแก้ไขเพื่อให้พอดีกับ API ของภาษา (หรือไลบรารี)


8

ไม่แน่ใจว่านี่คือสิ่งที่คุณกำลังมองหา แต่ฉันมีเป้าหมายที่แตกต่างออกไปเล็กน้อยคือการตรวจสอบว่ามีภาพระยะไกลหรือไม่และฉันจะไม่มีข้อผิดพลาด 403 ดังนั้นคุณสามารถใช้สิ่งต่อไปนี้:

public static boolean linkExists(String URLName){
    try {
        HttpURLConnection.setFollowRedirects(false);
        HttpURLConnection con = (HttpURLConnection) new URL(URLName).openConnection();
        con.setRequestMethod("HEAD");
        return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
    }
    catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

4
มีประโยชน์สำหรับกรณีทั่วไป แต่คุณไม่มีสถานะเบราว์เซอร์ใด ๆ โดยใช้วิธีนี้ (เช่นการเข้าสู่ระบบของผู้ใช้)
Roger Keays

ฉันเชื่อว่าคุณสามารถส่งข้อมูลรับรองเป็นส่วนหนึ่งของคำขอส่วนหัวได้ฉันจะยินดีมากหากคุณสามารถลองได้
Volodymyr Prysiazhniuk

4

ไม่สามารถรับรหัสตอบกลับ HTTP โดยใช้ Selenium WebDriver โดยตรง โค้ดสามารถรับได้โดยใช้โค้ด Java และสามารถใช้ใน Selenium WebDriver

ในการรับรหัสตอบกลับ HTTP โดย java:

public static int getResponseCode(String urlString) throws MalformedURLException, IOException{
    URL url = new URL(urlString);
    HttpURLConnection huc = (HttpURLConnection)url.openConnection();
    huc.setRequestMethod("GET");
    huc.connect();
    return huc.getResponseCode();
}

ตอนนี้คุณสามารถเขียนโค้ด Selenium WebDriver ได้ดังนี้:

private static int statusCode;
public static void main(String... args) throws IOException{
    WebDriver driver = new FirefoxDriver();
    driver.manage().window().maximize();
    driver.get("https://www.google.com/");
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

    List<WebElement> links = driver.findElements(By.tagName("a"));
    for(int i = 0; i < links.size(); i++){
        if(!(links.get(i).getAttribute("href") == null) && !(links.get(i).getAttribute("href").equals(""))){
            if(links.get(i).getAttribute("href").contains("http")){
                statusCode= getResponseCode(links.get(i).getAttribute("href").trim());
                if(statusCode == 403){
                    System.out.println("HTTP 403 Forbidden # " + i + " " + links.get(i).getAttribute("href"));
                }
            }
        }   
    }   
}

1
จะเกิดอะไรขึ้นถ้าเป็นการส่งแบบฟอร์ม POST? จะเกิดอะไรขึ้นถ้ามีคุกกี้?
nafg

1
นี่เป็นเพียงการส่งคำขอ HTTP ภายนอกซีลีเนียม
Matthias Winkelmann

2

คุณสามารถลองใช้ Mobilenium ( https://github.com/rafpyprog/Mobilenium ) ซึ่งเป็นแพ็คเกจหลามที่เชื่อมโยง BrowserMob Proxy และ Selenium

ตัวอย่างการใช้งาน:

>>> from mobilenium import mobidriver
>>>
>>> browsermob_path = 'path/to/browsermob-proxy'
>>> mob = mobidriver.Firefox(browsermob_binary=browsermob_path)
>>> mob.get('http://python-requests.org')
301
>>> mob.response['redirectURL']
'http://docs.python-requests.org'
>>> mob.headers['Content-Type']
'application/json; charset=utf8'
>>> mob.title
'Requests: HTTP for Humans \u2014 Requests 2.13.0 documentation'
>>> mob.find_elements_by_tag_name('strong')[1].text
'Behold, the power of Requests'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.