Як отримати код відповіді HTTP за допомогою Selenium WebDriver


109

Я написав тести з Selenium2 / WebDriver і хочу перевірити, чи запит HTTP повертає HTTP 403 Заборонено.

Чи можливо отримати код статусу відповіді HTTP за допомогою Selenium WebDriver?



Це не дублікат, тому що інше питання зосереджене на Python, але це питання в java,
Ральф

1
дякую, я зрозумів Але нарешті питання опинилося про webdriverобмеження 's, і ці обмеження однакові і для Python, і для Java;)
maxkoryukov

2
@maxkoryukov: але існують мови залежно від робочих обстановок,
Ральф

Відповіді:


66

Одним словом, ні. Використовувати API Selenium WebDriver неможливо. Це обговорювалося рекламною нудотою в трекері випусків проекту, і ця функція не буде додана в API.


42

Можна отримати код відповіді на запит http, використовуючи Selenium та Chrome або Firefox. Все, що вам потрібно зробити, це запустити Chrome або Firefox в режимі реєстрації. Я покажу вам кілька прикладів нижче.

java + Selenium + Chrome Ось приклад java + Selenium + Chrome, але я думаю, що це можна зробити будь-якою мовою (python, c #, ...).

Все, що вам потрібно зробити, це сказати Chromeedriver зробити "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]), потім на другому кроці знайдіть код відповіді для цього ідентифікатора запиту (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
Люди, які дивляться на це, пам’ятайте, що network.enable хрому вставляє додатковий заголовок у кожен запит HTTP, зроблений під час його ввімкнення.
Підроблене ім’я

2
Привіт, я можу отримати код відповіді, але як я можу отримати орган відповіді? Я не бачу цього у відповіді JSONObject.
ЛІНІ

@LINGS ви можете використовувати driver.getPageSource (), але будьте обережні, оскільки зазвичай є кілька запитів бічних javascript, які можуть змінити Dom. Ви можете зачекати, коли якийсь елемент вашої сторінки буде присутній у домі, а потім отримати джерело сторінки. Інший сценарій - з кадрами. Якщо у вас є кадри, вам потрібно перейти на кадр, то отримайте вихідний код цього кадру - driver.switchTo (). Frame ();
Стефан Матей

Я спробував реалізувати ваш код за допомогою RemoteWebDriver , оскільки мої методи написані з RemoteWebdriver. чи маєте ви якесь уявлення про те, як ним користуватися з RemoteWebDriver ?
M3trix

2
@IvayloSlavov Сценарій Chrome працює для мене з 4.0.0-alpha-4, ознайомтеся з цим прикладом github.com/smatei/SeleniumChromeHTTPResponse
Стефан Матей

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/…
Чарлі

1
Оригінальний проксі BrowserMob зараз не підтримується і трохи гниє. У нас є вилка з відкритим вихідним кодом проксі-сервера 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' об'єкт не має атрибуту" запити "" Це тому, що віддалений драйвер не підтримується селеном? Офіційної документації безнадійно бракує. Дякую!
Леннарт Ролланд

@LennartRolland одне з обмежень Selenium Wire полягає в тому, що він працюватиме лише на тій же машині, в якій працює браузер. Використання віддаленої установки наразі не підтримується.
Вілл Кілінг

1
@MohamedImran, якщо вас цікавить конкретна відповідь, тоді ви можете скористатися driver.wait_for_request()методом, щоб знайти запит, відповідь якого вас цікавить. Докладнішу інформацію див. У документах .
Буде Кілінг

1
@MohamedImran метод приймає регулярний вираз, тож ви можете передати лише частину URL-адреси, яка однозначно відповідає. Наприклад, на матч, http://myserver.com/some/path/12345/який можна пройтиdriver.wait_for_request(‘.*/12345/‘)
Буде Кілінг,

1
@MohamedImran вам не потрібна петля for
Will Keeling

10

У мене також виникли ті самі проблеми і затрималися протягом декількох днів, але після деяких досліджень я зрозумів, що ми можемо реально використовувати хромований "- remote-debugging-port" для перехоплення запитів спільно з веб-драйвером селену. Використовуйте наступний псевдокод як орієнтир: -

створити екземпляр драйвера хрому з віддаленою налагодженням

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 для прослуховування, ви можете побачити відповідь та зрозуміти, як витягнути

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/ Примітка: - використовуйте хромовідвід 2.39 або вище.

Я сподіваюся, що це комусь допоможе.

довідка: Використання протоколу віддаленої налагодження Google Chrome


Дивовижно, я радий, що є спосіб це зробити! Я просто хочу selenium-webdriver, щоб у моєму випадку існувала бібліотека (для Рубі , в моєму випадку), яка автоматично вмикала Network.enableта відкривала простий спосіб перевірити останню відповідь ... як driver.response.status_code. Можливо, коли-небудь я обійдусь, додавши, що ... :)
Тайлер Рік

Якщо будь-які інші програмісти Ruby стикаються з цим, я створив дорогоцінний камінь, github.com/TylerRick/capybara-chrome_response_headers , який дозволяє легко отримати код статусу HTTP з тесту Capybara / RSpec, просто зателефонувавши status_code. Він використовує протокол віддаленої налагодження Chrome, як у цьому прикладі.
Тайлер Рік

спасибі чувак! працює для мене хром 76 + селен 3.141
jessez

9

Отримайте код відповіді будь-якою мовою (за допомогою JavaScript):

Якщо ваші тести Selenium працюють у сучасному браузері, простим способом отримання коду відповіді є надсилання синхронного XMLHttpRequest* та перевірка statusвідповіді:

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

assert(200, xhr.status);

Ви можете використовувати цю техніку з будь-якою мовою програмування, вимагаючи, щоб Selenium виконав сценарій. Наприклад, на 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
Зручно для простих випадків, але у вас немає стану веб-переглядача, використовуючи цей метод (наприклад, вхід користувачів).
Роджер Кіз

Я вважаю, що ви можете надіслати облікові дані як частину запиту заголовка, я буду вдячний, якщо ви можете спробувати це.
Володимир Присяжнюк

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? Що робити, якщо є файли cookie?
нафг

1
Це просто надсилання HTTP-запиту поза селеном.
Маттіас Вінкельманн

2

Ви можете спробувати Mobilenium ( https://github.com/rafpyprog/Mobilenium ), пакет python, який пов'язує 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'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.