使用PhantomJS评估JavaScript代码

时间:2016-08-16 14:47:09

标签: javascript phantomjs

我尝试使用PhantomJS从广告服务器运行一些JavaScript并解析响应对象,以获取有关所投放广告的信息。这可以从Firefox / Chrome Dev Tools中获得,但我需要从服务器访问相同的信息。我可以让Phantom运行,但是一旦我尝试包含外部JS page.includeJs("http://www.someadserver.com/config.js?nwid=1909"并访问通过外部JS someadserver.setup({ domain: 'http://www.someadserver.com'});设置的变量,它就会失败。任何帮助将不胜感激。

"use strict";

var page = require('webpage').create();

page.content = `    
  <html>    
    <head>    
        <script>    
            someadserver.setup({ domain: 'http://www.someadserver.com'});    
        </script>    
       <title>The title of the web page.</title>    
    </head>    
    <body>    
    <div class="ads_leaderboard">    
        <!-- position: leaderboard -->    
        <script>    
            someadserver.call( "std" , {    
                siteId: 100806,    
                pageId: 656377,    
                target: ""
            });    
        </script>    
    </div>    
    <div id="foo">this is foo</div>    
    </body>    
  </html>`;

var title = page.evaluate(function (s) {
    page.includeJs(
      "http://www.someadserver.com/config.js?nwid=1909",
      function() {
        return document.querySelector(s).innerText;
    }, 'title');
});

console.log(title);

phantom.exit(1);

编辑1:

我简化了我的剧本(下方),我明显遗漏了一些东西。当我使用bin/phantomjs /srv/phantom_test.js运行下面的脚本时,我得到的唯一输出是end page。为什么还没有执行console.log语句的其余部分?

"use strict";

var page = require('webpage').create();

page.content = "<html>" +
"<head>" +
"   <title>The title of the web page.</title>" +
"</head>" +
"<body>" +
"<div id=\"foo\">this is foo</div>" +
"</body>" +
"</html>";

page.includeJs("http://www.someadserver.com/config.js?nwid=1909", function() {
    console.log('start function');
    var title = page.evaluate(function(s){
        return document.querySelector(s).innerText;
    }, 'title');
    console.log(title);
    console.log('end function');
});

console.log('end page');

phantom.exit();

2 个答案:

答案 0 :(得分:0)

page.evaluate内的内容在目标网页的上下文中执行,就好像该代码> 一样。

page.includeJS(...)不会是someadserver.com上的有效代码。

正确的方法反之亦然:

page.includeJs("http://www.someadserver.com/config.js?nwid=1909", function() {
    var title = page.evaluate(function(s){
        return document.querySelector(s).innerText;
    }, 'title');
});

答案 1 :(得分:0)

您的第一个代码段不起作用,因为为page.content分配值会立即执行它。因此,someadserver.setup(...)会立即执行,就好像页面实际已加载一样,但此时page.includeJs(...)来电尚未发生。
您应该能够实际包含要在页面源中运行的脚本:

var content = `    
  <html>    
    <head>
        <script src="http://www.someadserver.com/config.js?nwid=1909"></script>
        <script>    
            someadserver.setup({ domain: 'http://www.someadserver.com'});    
        </script>    
       <title>The title of the web page.</title>    
    </head>    
    <body>    
    <div class="ads_leaderboard">    
        <!-- position: leaderboard -->    
        <script>    
            someadserver.call( "std" , {    
                siteId: 100806,    
                pageId: 656377,    
                target: ""
            });    
        </script>    
    </div>    
    <div id="foo">this is foo</div>    
    </body>    
  </html>`;

page.setContent(content, "http://www.someadserver.com/");
var title = page.evaluate(function (s) {
    return document.querySelector(s).innerText;
}, 'title');

console.log(title);

phantom.exit();

我还使用page.setContent来设置域名,以便不会破坏进一步的脚本加载。将网页来源分配到page.content时,默认网址实际上是:空白,您不需要。

第一个代码段的其他问题:

  • page.evaluatepage.includeJs的开头和结尾不匹配!
  • page内没有page.evaluate,因为页面上下文是沙箱化的!

您的第二个代码段不起作用,因为page.includeJs(...)是一个异步函数(它有一个回调!),所以您过早退出脚本。