Tracking with JavaScript if Ajax request is going on in a webpage or Intercept XMLHttpRequest through Selenium Web driver

后端 未结 3 400
灰色年华
灰色年华 2021-02-01 20:32

I am using Selenium WebDriver for crawling a web site(only for example, I will be crawling other web sites too!) which has infinite scroll.

Problem statement:

3条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-01 21:15

    For web pages with Ajax Response during the infinite scroll and using jQuery API(or other actions), before starting to opening the web page.

        //Inject the pooling status variable
        js.executeScript("window.status = 'fail';");
    
        //Attach the Ajax call back method
        js.executeScript( "$(document).ajaxComplete(function() {" +
        "status = 'success';});");
    

    Step 1: will remain the same as in the original question

    Step 2 Pooling the following script(This is the one which removes the need of Thread.Sleep() and makes the logic more dynamic)

    String aStatus = (String)js.executeScript("return status;");
    
                            if(aStatus!=null && aStatus.equalsIgnoreCase("success")){
                                js.executeScript("status = 'fail';");
                                break poolingLoop;
                            }
    

    Step 3: No need now!

    Conclusion: No need to give blunt Thread.sleep(); again and again while using Selenium WebDriver!!

    This approach works good only if there's jQuery api being used in the web application.

    EDIT: As per the the link given by @jayati i injected the javascript-

    Javascript one:

    //XMLHttpRequest instrumentation/wrapping
    var startTracing = function (onnew) {
        var OldXHR = window.XMLHttpRequest;
    
        // create a wrapper object that has the same interfaces as a regular XMLHttpRequest object
        // see http://www.xulplanet.com/references/objref/XMLHttpRequest.html for reference on XHR object
        var NewXHR = function() {
            var self = this;
            var actualXHR = new OldXHR();
    
            // private callbacks (for UI):
            // onopen, onsend, onsetrequestheader, onupdate, ...
            this.requestHeaders = "";
            this.requestBody = "";
    
            // emulate methods from regular XMLHttpRequest object
            this.open = function(a, b, c, d, e) { 
                self.openMethod = a.toUpperCase();
                self.openURL = b;
                ajaxRequestStarted = 'open';
    
                if (self.onopen != null && typeof(self.onopen) == "function") { 
                    self.onopen(a,b,c,d,e); } 
                return actualXHR.open(a,b,c,d,e); 
            }
            this.send = function(a) {
                ajaxRequestStarted = 'send';
    
                if (self.onsend != null && typeof(this.onsend) == "function") { 
                    self.onsend(a); } 
                self.requestBody += a;
                return actualXHR.send(a); 
            }
            this.setRequestHeader = function(a, b) {
                if (self.onsetrequestheader != null && typeof(self.onsetrequestheader) == "function") { self.onsetrequestheader(a, b); } 
                self.requestHeaders += a + ":" + b + "\r\n";
                return actualXHR.setRequestHeader(a, b); 
            }
            this.getRequestHeader = function() {
                return actualXHR.getRequestHeader(); 
            }
            this.getResponseHeader = function(a) { return actualXHR.getResponseHeader(a); }
            this.getAllResponseHeaders = function() { return actualXHR.getAllResponseHeaders(); }
            this.abort = function() { return actualXHR.abort(); }
            this.addEventListener = function(a, b, c) { return actualXHR.addEventListener(a, b, c); }
            this.dispatchEvent = function(e) { return actualXHR.dispatchEvent(e); }
            this.openRequest = function(a, b, c, d, e) { return actualXHR.openRequest(a, b, c, d, e); }
            this.overrideMimeType = function(e) { return actualXHR.overrideMimeType(e); }
            this.removeEventListener = function(a, b, c) { return actualXHR.removeEventListener(a, b, c); }
    
            // copy the values from actualXHR back onto self
            function copyState() {
                // copy properties back from the actual XHR to the wrapper
                try {
                    self.readyState = actualXHR.readyState;
                } catch (e) {}
                try {
                    self.status = actualXHR.status;
                } catch (e) {}
                try {
                    self.responseText = actualXHR.responseText;
                } catch (e) {}
                try {
                    self.statusText = actualXHR.statusText;
                } catch (e) {}
                try {
                    self.responseXML = actualXHR.responseXML;
                } catch (e) {}
            }
    
            // emulate callbacks from regular XMLHttpRequest object
            actualXHR.onreadystatechange = function() {
                copyState();
    
                try {
                    if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); } 
                } catch (e) {}
    
                // onreadystatechange callback            
                if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") { return self.onreadystatechange(); } 
            }
            actualXHR.onerror = function(e) {
    
                ajaxRequestComplete = 'err';
                copyState();
    
                try {
                    if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); } 
                } catch (e) {}
    
                if (self.onerror != null && typeof(self.onerror) == "function") { 
                    return self.onerror(e); 
                } else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") { 
                    return self.onreadystatechange(); 
                }
            }
            actualXHR.onload = function(e) {
    
                ajaxRequestComplete = 'loaded';
                copyState();
    
                try {
                    if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); } 
                } catch (e) {}
    
                if (self.onload != null && typeof(self.onload) == "function") { 
                    return self.onload(e); 
                } else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") { 
                    return self.onreadystatechange(); 
                }
            }
            actualXHR.onprogress = function(e) {
                copyState();
    
                try {
                    if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); } 
                } catch (e) {}
    
                if (self.onprogress != null && typeof(self.onprogress) == "function") { 
                    return self.onprogress(e);
                } else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") { 
                    return self.onreadystatechange(); 
                }
            }
    
            if (onnew && typeof(onnew) == "function") { onnew(this); }
        }
    
        window.XMLHttpRequest = NewXHR;
    
    }
    window.ajaxRequestComplete = 'no';//Make as a global javascript variable
    window.ajaxRequestStarted = 'no';
    startTracing();
    

    Or Javascript Two:

    var startTracing = function (onnew) {
        window.ajaxRequestComplete = 'no';//Make as a global javascript variable
        window.ajaxRequestStarted = 'no';
    
        XMLHttpRequest.prototype.uniqueID = function() {
            if (!this.uniqueIDMemo) {
                this.uniqueIDMemo = Math.floor(Math.random() * 1000);
            }
            return this.uniqueIDMemo;
        }
    
        XMLHttpRequest.prototype.oldOpen = XMLHttpRequest.prototype.open;
    
        var newOpen = function(method, url, async, user, password) {
    
            ajaxRequestStarted = 'open';
            /*alert(ajaxRequestStarted);*/
            this.oldOpen(method, url, async, user, password);
        }
    
        XMLHttpRequest.prototype.open = newOpen;
    
        XMLHttpRequest.prototype.oldSend = XMLHttpRequest.prototype.send;
    
        var newSend = function(a) {
            var xhr = this;
    
            var onload = function() {
                ajaxRequestComplete = 'loaded';
                /*alert(ajaxRequestComplete);*/
            };
    
            var onerror = function( ) {
                ajaxRequestComplete = 'Err';
                /*alert(ajaxRequestComplete);*/
            };
    
            xhr.addEventListener("load", onload, false);
            xhr.addEventListener("error", onerror, false);
    
            xhr.oldSend(a);
        }
    
        XMLHttpRequest.prototype.send = newSend;
    }
    startTracing();
    

    And checking the status of the status vars ajaxRequestStarted, ajaxRequestComplete in the java code, one can determine if the ajax was started or completed.

    Now I have a way to wait till an Ajax is complete, I can also find if the Ajax was triggered on some action

提交回复
热议问题