【问题标题】:PhantomJS how to render javascript in html stringPhantomJS如何在html字符串中呈现javascript
【发布时间】:2015-11-08 23:44:00
【问题描述】:

我试图让 PhantomJS 获取一个 html 字符串,然后让它像浏览器一样呈现整个页面(包括在页面源代码中执行任何 javascript)。我需要将生成的 html 结果作为字符串。我已经看到了 page.open 的示例,因为我的数据库中已经有了页面源,所以没有用。

是否需要使用 page.open 来触发 PhantomJS 中的 javascript 渲染引擎?有没有办法在内存中完成这一切(即......没有 page.open 发出请求或从/向磁盘读取/写入 html 源代码?

我看到了一个类似的问题和答案here,但这并不能完全解决我的问题。运行下面的代码后,我似乎没有在 html 源字符串中呈现 javascript。

var page = require('webpage').create();
page.setContent('raw html and javascript in this string', 'http://whatever.com');
//everything i've tried from here on doesn't execute the javascript in the string

-------------更新---------------

根据下面的建议尝试了以下方法,但这仍然不起作用。只返回我提供的未呈现 javascript 的原始源代码。

var page = require('webpage').create();
page.settings.localToRemoteUrlAccessEnabled = true;
page.settings.webSecurityEnabled = false;
page.onLoadFinished = function(){
    var resultingHtml = page.evaluate(function() {
        return document.documentElement.innerHTML;
    });
    console.log(resultingHtml);
    //console.log(page.content); // this didn't work either
    phantom.exit();
};
page.url = input.Url;
page.content = input.RawHtml;
//page.setContent(input.RawHtml, input.Url); //this didn't work either

【问题讨论】:

  • 您使用哪个 PhantomJS 版本?请注册onConsoleMessageonErroronResourceErroronResourceTimeout 活动 (Example)。可能有错误。

标签: javascript phantomjs


【解决方案1】:

以下作品

page.onLoadFinished = function(){
    console.log(page.content); // rendered content
};
page.content = "your source html string";

但您必须记住,如果您从字符串设置页面,则域将为 about:blank。因此,如果 html 从其他域加载资源,那么您应该使用 --web-security=false --local-to-remote-url-access=true 命令行选项运行 PhantomJS:

phantomjs --web-security=false --local-to-remote-url-access=true script.js

此外,您可能需要等待 JavaScript 执行完成,当 PhantomJS 认为它完成时,这可能还没有完成。使用setTimeout() 等待静态时间量或使用waitFor() 等待页面上的特定条件。这个问题给出了更强大的等待整页的方法:phantomjs not waiting for “full” page load

【讨论】:

  • 感谢您的回复。我用代码更新了我上面的问题,尝试了你的建议。这似乎仍然不能解决我的问题。只返回我提供的原始源,没有渲染。
  • 你没有说你的页面在做什么,所以我提供了一个一般性的答案。我现在也扩展了一点。
【解决方案2】:

setTimeout 使它工作,即使我不高兴为每个页面等待一定的时间。 here 讨论的 waitFor 方法不起作用,因为我不知道每个页面可能包含哪些元素。

var system = require('system');
var page = require('webpage').create();
page.setContent(input.RawHtml, input.Url);
window.setTimeout(function () {
    console.log(page.content);
    phantom.exit();
}, input.WaitToRenderTimeInMilliseconds);

【讨论】:

  • 我可能会在未来尝试类似 checkin $.active 来查看页面是否有任何未决的 ajax 请求。然后我可以避免做一个 setTimeout。
  • 您也可以使用here 的一些建议来等待完整的页面加载。
【解决方案3】:

也许不是你想要的答案,但使用 PhantomJsCloud.com 你可以轻松做到,这里有一个例子:http://api.phantomjscloud.com/api/browser/v2/a-demo-key-with-low-quota-per-ip-address/?request={url:%22http://example.com%22,content:%22%3Ch1%3ENew%20Content!%3C/h1%3E%22,renderType:%22png%22,scripts:{domReady:[%22var%20hiDiv=document.createElement%28%27div%27%29;hiDiv.innerHTML=%27Hello%20World!%27;document.body.appendChild%28hiDiv%29;window._pjscMeta.scriptOutput={Goodbye:%27World%27};%22]},outputAsJson:false}“新内容!”是替换原始内容的内容,而“Hello World!”由脚本放置在页面中。

如果您想通过普通的 PhantomJs 执行此操作,则需要在页面内容加载后使用 injectJs 或 includeJs 函数。

【讨论】:

  • 哦,披露,我写了 PhantomJsCloud
猜你喜欢
  • 2019-11-28
  • 1970-01-01
  • 2019-07-22
  • 2013-03-11
  • 2021-02-12
  • 2017-06-10
  • 2016-05-21
  • 2019-02-28
  • 1970-01-01
相关资源
最近更新 更多