“undefined is not a function” on page login under

2019-09-11 04:39发布

问题:

I'm trying to set up a crawler, using Selenium under Java.

When I use ChromeDriver it works fine. However, I get into a whole new bunch of problems if I try to use a headless browser like PhantomJS.

this is where problems happen:

     Capabilities caps = new DesiredCapabilities();
     ((DesiredCapabilities) caps).setJavascriptEnabled(true);
     ((DesiredCapabilities) caps).setCapability("takesScreenshot", false);
     ((DesiredCapabilities) caps).setCapability("locationContextEnabled", true);
     ((DesiredCapabilities) caps).setCapability("acceptSslCerts", true);


    PhantomJSDriver jsDriver = new PhantomJSDriver(caps);
    driver = jsDriver;
    System.out.println("driver is set...");
    driver.get("http://localhost/login");  //erorrs appears to be here
    System.out.println("gonna wait for page loading...");

    WebDriverWait wait = new WebDriverWait(driver, 40); 
    wait.until(ExpectedConditions.elementToBeClickable(By.id("emailAddr")));

    WebElement element_email = driver.findElement(By.id("emailAddr"));
    element_email.clear();
    element_email.sendKeys("example@example.com");

    WebElement element_password = driver.findElement(By.id("password"));
    element_password.clear();
    element_password.sendKeys("password");

    WebElement element_login = driver.findElement(By.xpath("//input[@type=\"submit\"]"));
    element_login.click();

the errors I get

driver is set...
[ERROR - 2015-08-27T11:45:32.378Z] Session [1c04b0e0-4cb1-11e5-aef3-a75ceb7c4223] - page.onError - msg: TypeError: undefined is not a function (evaluating '$("#location-search-box").geocomplete')

  :262 in error
[ERROR - 2015-08-27T11:45:32.379Z] Session [1c04b0e0-4cb1-11e5-aef3-a75ceb7c4223] - page.onError - stack:
  init (http://localhost/static/js/auto/537c5ede-d569-491d-bd95-4916c763f9cf.js:9407)
  (anonymous function) (http://localhost/static/js/auto/537c5ede-d569-491d-bd95-4916c763f9cf.js:11336)
  l (http://localhost/static/js/jquery.min.js:2)
  fireWith (http://localhost/static/js/jquery.min.js:2)
  ready (http://localhost/static/js/jquery.min.js:2)
  A (http://localhost/static/js/jquery.min.js:2)

  :262 in error
gonna wait for page loading...

NOTE:

Program is still running but because of this error I was unable to login into the page.

How to solve this?

Is there any alternative?

EDIT one:

After following @Alfonso Presa I tried this:

String polyfill = "" +
        "       if (!Function.prototype.bind) {" +
        "                     Function.prototype.bind = function(oThis) {" +
        "                       if (typeof this !== 'function') {" +
        "                         // closest thing possible to the ECMAScript 5" +
        "                         // internal IsCallable function" +
        "                         throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');" +
        "                       }" +
        "" +
        "                       var aArgs   = Array.prototype.slice.call(arguments, 1)," +
        "                           fToBind = this," +
        "                           fNOP    = function() {}," +
        "                           fBound  = function() {" +
        "                             return fToBind.apply(this instanceof fNOP && oThis" +
        "                                    ? this" +
        "                                    : oThis," +
        "                                    aArgs.concat(Array.prototype.slice.call(arguments)));" +
        "                           };" +
        "" +
        "                       fNOP.prototype = this.prototype;" +
        "                       fBound.prototype = new fNOP();" +
        "" +
        "                       return fBound;" +
        "                     };" +
        "                   }" ;

PhantomJSDriver jsDriver = new PhantomJSDriver(capabilities);
jsDriver.executeAsyncScript(polyfill);
driver = jsDriver;

unfortunately it throws this error now :

[ERROR - 2015-08-27T13:05:25.354Z] Session [482dc570-4cbc-11e5-960c-81dcdf4848bd] - page.onError - msg: SyntaxError: Unexpected token ')'

  :262 in error
[ERROR - 2015-08-27T13:05:25.354Z] Session [482dc570-4cbc-11e5-960c-81dcdf4848bd] - page.onError - stack:
  Function (undefined:2)
  Na (phantomjs://webpage.evaluate():14)
  (anonymous function) (phantomjs://webpage.evaluate():15)
  (anonymous function) (phantomjs://webpage.evaluate():15)
  (anonymous function) (phantomjs://webpage.evaluate():16)
  (anonymous function) (phantomjs://webpage.evaluate():16)

  :262 in error

EDIT TWO:

after many trial, I install phantomJS version 1.9.8 and my original code just worked fine.

so overall:

  1. phantomJS version 1.9.0 had many bugs (just take it as many bugs)
  2. phantomJS version 2.0 had the above problem
  3. phantomJS version 1.9.8 worked just fine. I will try to investigate what the problem might be.

回答1:

PhantomJS is known to have some incompatibilities with web standards. Specially for your case this one: https://github.com/ariya/phantomjs/issues/10522

The most probable cause for your problem is that the bind method is being used in the web you're trying to crawl. That method is included in almost all browsers but PhantomJS.

To solve your issue, if you have the chance to change the web page you're crawling try to insert a polifyll like this one: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Function/bind#Polyfill

If that's not possible you can try to inject it using executeScript method.

Note that this seems to have been solved for Phantom 2.0.