如何在 PhantomJS 和 CasperJS 中设置 sessionStorage?

How to set sessionStorage in PhantomJS and CasperJS?

使用以下脚本未正确设置 sessionStorage。我试图在 page.evaluate 回调中设置存储,但我没有任何运气,我的 "complete" 检查无限循环。我遇到了与 casper 完全相同的问题,尝试了类似的评估和重新加载模式。我无法测试,因为所有 ajax 请求都使用 sessionStorage 来获取授权 JWT。我知道我应该在评估中访问 window,所以我不确定为什么这不起作用。

var page = require("webpage").create();
var url = "http://xxxxxxxx.com";
var t0 = Date.now;
function onPageReady() {
    var t1 = Date.now;
    var elapsed = t1 - t0; 
    var htmlContent = page.evaluate(function () {
        return document.documentElement.outerHTML;
    }); 
    console.log(htmlContent);
    console.log("ELAPSED TIME: " , elapsed + "\n") ;
    phantom.exit(0);
}

page.open(url, function (status) {
    var sessionStorage = page.evaluate(function(){
      sessionStorage.setItem('authorization','xxxxxxxxxxxxxxxxx');
      //window.sessionStorage.setItem('authorization','xxxxxxxxxx');
      window.sessionStorage.setItem('_USER','value');
      window.sessionStorage.setItem('USERNAME','value');
      window.sessionStorage.setItem('INTERNAL','value');
      console.log(window.sessionStorage);
      return sessionStorage;
    }); 
    t0 = Date.now;
    console.log(JSON.stringify(sessionStorage));
    console.log(JSON.stringify(window.sessionStorage));
    function checkReadyState() {
        setTimeout(function () {
            var readyState = page.evaluate(function () {
                return document.readyState;
            }); 

            if ("complete" === readyState) {
              // checking if my ng-repeat has loaded
              if (document.getElementsByClassName('quoteTr').length > 1){ 
                  console.log("ready!")
                  onPageReady();
              } else {
                  console.log("script not complete")
                  checkReadyState();
              }   
            } else {
                checkReadyState();
            }   
        }); 
    }   

    checkReadyState();
});

如果您在页面上下文中设置 sessionStorage(在 page.evaluate() 中),那么您需要在页面上下文中检索它。尽管 sessionStorage 存在于页面上下文之外,但它是一些无法访问页面 sessionStorage.

的虚拟对象
page.evaluate(function(){
    sessionStorage.setItem('authorization','xxxxxxxxxxxxxxxxx');
});
var authorization = page.evaluate(function(){
    sessionStorage.getItem('authorization');
});
console.log("authorization: " + authorization);

由于 sessionStorage 是一个非原始对象,您不能将它传递到页面上下文之外。您只能传递它的表示形式,例如它的键值对。对于 docs:

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!

CasperJS中也是如此。


关于“循环”的主题。我发现您的代码存在三个问题。

首先Date.now是对一个函数的引用。如果你想要当前时间,那么你必须将它称为 Date.now().

你没有给 PhantomJS 太多时间来做任何工作。您基本上使用 setTimeout() 没有第二个参数,默认为 0,这意味着立即调用回调。尝试使用较小的超时时间,例如 50:setTimeout(function(){...}, 50).

您正在尝试在页面上下文之外访问 document.getElementsByClassName('quoteTr'),但 document 只是一个虚拟对象,因此无论发生什么情况,它总是 return 一个空数组在页面上。你必须使用 page.evaluate()。 CasperJS 为这种情况提供 casper.exists() 函数。


我不是很明白为什么你需要设置一些sessionStorage值,但如果你需要为页面尽快设置它们,那么你可以尝试采用两种不同的策略:

  • 正常打开页面,将值设置为 sessionStorage,然后再次加载页面,以便页面的 JavaScript 获取值。

  • 您可以尝试注册page.onLoadStartedpage.onNavigationRequestedpage.onUrlChanged活动,以便尽快设置会话值。