javascript phantom.js 的截图保存在哪里?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15205538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 23:51:57  来源:igfitidea点击:

Where are screenshots from phantom.js saved?

javascriptphantomjs

提问by Adam Grant

Just starting out with Phantom.js after installing via Homebrew on my mac.

在我的 Mac 上通过 Homebrew 安装后,刚开始使用 Phantom.js。

I'm trying out the examples to save screenshots of websites via https://github.com/ariya/phantomjs/wiki/Quick-Start

我正在尝试通过https://github.com/ariya/phantomjs/wiki/Quick-Start保存网站截图的示例

var page = require('webpage').create();
page.open('http://google.com', function () {
    page.render('google.png');
    phantom.exit();
});

But I don't see the images anywhere. Will they be in the same directory as the .js file?

但我在任何地方都看不到图像。它们会与 .js 文件在同一目录中吗?

回答by Vivin Paliath

PhantomJS usually renders the images to the same directory as the script that you're running. So yes, it should be in the same directory as the JavaScript file that you're running using PhantomJS.

PhantomJS 通常将图像渲染到与您正在运行的脚本相同的目录中。所以是的,它应该与您使用 PhantomJS 运行的 JavaScript 文件位于同一目录中。

EDIT

编辑

It appears that that particular example is flawed. The problem is that page.render(...);takes some time to render the page, but you're calling phantom.exit()before it has finished rendering. I was able to get the expected output by doing this:

看来那个特定的例子是有缺陷的。问题是page.render(...);渲染页面需要一些时间,但您phantom.exit()在它完成渲染之前调用。通过这样做,我能够获得预期的输出:

var page = require('webpage').create();
page.open('http://google.com', function () {
    page.render('google.png');
    setTimeout(function() { phantom.exit(); }, 5000) // wait five seconds and then exit;
});

Unfortunately this isn't ideal, so I was able to come up with something that's a hair better. I say a "hair", because I'm basically polling to see when the page has finished rendering:

不幸的是,这并不理想,所以我能够想出一些更好的头发。我说“头发”,因为我基本上是在轮询页面何时完成渲染:

var done = false; //flag that tells us if we're done rendering

var page = require('webpage').create();
page.open('http://google.com', function (status) {
    //If the page loaded successfully...
    if(status === "success") {
        //Render the page
        page.render('google.png');
        console.log("Site rendered...");

        //Set the flag to true
        done = true;
    }
});

//Start polling every 100ms to see if we are done
var intervalId = setInterval(function() {
    if(done) {
        //If we are done, let's say so and exit.
        console.log("Done.");
        phantom.exit();
    } else {
        //If we're not done we're just going to say that we're polling
        console.log("Polling...");
    }
}, 100);

The code above works because the callback isn't immediately executed. So the polling code will start up and start to poll. Then when the callback is executed, we check to see the status of the page (we only want to render if we were able to load the page successfully). Then we render the page and set the flag that our polling code is checking on, to true. So the next time the polling code runs, the flag is trueand so we exit.

上面的代码有效,因为回调不会立即执行。所以轮询代码将启动并开始轮询。然后当回调被执行时,我们检查页面的状态(我们只想在我们能够成功加载页面时呈现)。然后我们渲染页面并将我们的轮询代码正在检查的标志设置为true。所以下次轮询代码运行时,标志是true,所以我们退出。

This looks to be a problem with the way PhantomJS is running the webpage#render(...)call. I suspected that it was a non-blocking call, but according to the author in this issue, it is a blocking call. If I had to hazard a guess, perhaps the act of rendering is a blocking call, but the code that does the rendering might be handing off the data to another thread, which handles persisting the data to disk (so this part might be a non-blocking call). Unfortunately, this call is probably still executing when execution comes back to the main script and executes phantom.exit(), which means that the aforementioned asynchronous code never gets a chance to finish what it's doing.

这看起来是 PhantomJS 运行webpage#render(...)调用的方式有问题。我怀疑这是一个非阻塞调用,但根据本期作者的说法,它是一个阻塞调用。如果我不得不冒险猜测,也许渲染的行为是一个阻塞调用,但是执行渲染的代码可能会将数据移交给另一个线程,该线程处理将数据持久化到磁盘(因此这部分可能是非- 阻塞呼叫)。不幸的是,当执行返回到主脚本并执行时,这个调用可能仍在执行phantom.exit(),这意味着上述异步代码永远没有机会完成它正在做的事情。

I was able to find a post on the PhantomJS forums that deals with what you're describing. I can't see any issue that has been filed, so if you'd like you can go ahead and post one.

我能够在 PhantomJS 论坛上找到一篇关于您所描述的内容的帖子。我看不到任何已提交的问题,因此如果您愿意,可以继续发布一个。

回答by Caleb G

I have the very same issue as the author of this post, and none of the code examples worked for me. Kind of disorienting to have the second example in Phantom.js documentation not work. Installed using Home Brew on Snow Leopard.

我和这篇文章的作者有同样的问题,没有一个代码示例对我有用。Phantom.js 文档中的第二个示例不起作用,这有点令人迷惑。在 Snow Leopard 上使用 Home Brew 安装。

I found a working example

我找到了一个工作示例

var page = require("webpage").create();
var homePage = "http://www.google.com/";
page.settings.javascriptEnabled = false;
page.settings.loadImages = false;
page.open(homePage);
page.onLoadFinished = function(status) {
  var url = page.url;
  console.log("Status:  " + status);
  console.log("Loaded:  " + url);
  page.render("google.png");
  phantom.exit();
};

回答by Stan Smulders

Just a quick help for people who come here looking for the directory where PhantomJS or CasperJS's screenshots are saved: it is in the scripts directory by default. However, you do have control.

对于来这里寻找保存 PhantomJS 或 CasperJS 屏幕截图的目录的人来说,这是一个快速帮助:默认情况下,它在脚本目录中。但是,您确实可以控制。

If you want to control where they are saved you can just alter the filename like so:

如果你想控制它们的保存位置,你可以像这样改变文件名:

page.render('screenshots/google.jpg'); // saves to scriptLocation/screenshots/
page.render('/opt/google.jpg'); // saves to /screenshots (in the root)

Or if you use CasperJS you can use:

或者,如果您使用 CasperJS,您可以使用:

casper.capture('/opt/google.jpg',
        undefined,
        { // imgOptions
            format: 'jpg',
            quality: 25
        }); 

Hope this saves someone the trouble!

希望这可以为某人省去麻烦!

回答by Justin Pavatte

I'm not sure if something has changed, but the example on http://phantomjs.org/screen-capture.htmlworked fine for me:

我不确定是否发生了某些变化,但http://phantomjs.org/screen-capture.html上的示例对我来说效果很好:

var page = require('webpage').create();
page.open('http://github.com/', function() {
  page.render('github.png');
  phantom.exit();
});

I am running phantomjs-2.1.1-windows.

我正在运行 phantomjs-2.1.1-windows。

However, what led me to this thread was initially the image file was never getting created on my disk just like the original question. I figured it was some kind of security issues so I logged into a VM and started by putting everything in the same directory. I was using a batch file to kick off phantomjs.exe with my .js file passed in as a parameter. With all of the files in the same directory on my VM, it worked great. Through trial and error, I found that my batch file had to be in the same directory as my .js file. Now all is well on my host machine as well.

然而,导致我进入这个线程的原因是最初图像文件从未像原始问题一样在我的磁盘上创建。我认为这是某种安全问题,所以我登录到虚拟机并开始将所有内容放在同一目录中。我使用批处理文件来启动 phantomjs.exe 并将我的 .js 文件作为参数传入。所有文件都在我的 VM 上的同一目录中,效果很好。通过反复试验,我发现我的批处理文件必须与我的 .js 文件位于同一目录中。现在我的主机上也一切正常。

So in summary...it was probably a security related problem for me. No need for adding any kind of timeout.

所以总而言之......对我来说这可能是一个与安全相关的问题。无需添加任何类型的超时。

My answer to the original question would be IF you have everything set up correctly, the file will be in the same directory as the .js file that phantomjs.exe runs. I tried specifying a fully qualified path for the image file but that didn't seem to work.

我对原始问题的回答是,如果您已正确设置所有内容,则该文件将与 phantomjs.exe 运行的 .js 文件位于同一目录中。我尝试为图像文件指定一个完全限定的路径,但这似乎不起作用。

回答by Rich Kuzsma

The root cause is that page.render() may not be ready to render the image even during the onLoadFinished() event. You may need to wait upwards of several seconds before page.render() can succeed. The only reliable way I found to render an image in PhantomJS is to repeatedly invoke page.render() until the method returns true, indicating it successfully rendered the image.

根本原因是即使在 onLoadFinished() 事件期间 page.render() 可能还没有准备好渲染图像。在 page.render() 成功之前,您可能需要等待几秒钟。我发现在 PhantomJS 中渲染图像的唯一可靠方法是重复调用 page.render() 直到该方法返回 true,表明它成功渲染了图像。

Solution:

解决方案:

var page = require("webpage").create();
var homePage = "http://www.google.com/";

page.onLoadFinished = function(status) {
  var rendered, started = Date.now(), TIMEOUT = 30 * 1000; // 30 seconds
  while(!((rendered = page.render('google.png')) || Date.now() - started > TIMEOUT));
  if (!rendered) console.log("ERROR: Timed out waiting to render image.")
  phantom.exit();
};

page.open(homePage);

回答by Paul L

Steal from rasterize.js example, it works more reliable than the accepted answer for me.

rasterize.js 示例中窃取,它比我接受的答案更可靠。

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

page.open('http://localhost/TestForTest/', function (status) {
    console.log("starting...");
    console.log("Status: " + status);

    if (status === "success") {
        window.setTimeout(function () {
            page.render('myExample.png');
            phantom.exit();
        }, 200);
    } else {
        console.log("failed for some reason.");
    }
});

回答by pelson

Plenty of good suggestions here. The one thing I'd like to add:

这里有很多很好的建议。我想补充的一件事:

I was running a phantomjs docker image, and the default user was "phantomjs", not root. I was therefore trying to write to a location that I didn't have permission on (it was the pwd on the docker host)...

我正在运行 phantomjs docker 映像,默认用户是“phantomjs”,而不是 root。因此,我试图写入一个我没有权限的位置(它是 docker 主机上的密码)...

> docker run -i -t -v $(pwd):/pwd --rm wernight/phantomjs touch /pwd/foo.txt
touch: cannot touch '/pwd/foo.txt': Permission denied

The code(s) above all run without error, but if they don't have permission to write to the destination then they will silently ignore the request...

上面的代码运行没有错误,但如果他们没有写入目标的权限,那么他们将默默地忽略请求......

So for example, taking @vivin-paliath's code (the current accepted answer):

例如,以@vivin-paliath 的代码(当前接受的答案)为例:

var done = false; //flag that tells us if we're done rendering

var page = require('webpage').create();
page.open('http://google.com', function (status) {
    //If the page loaded successfully...
    if(status === "success") {
        //Render the page
        page.render('google.png');
        console.log("Site rendered...");

        //Set the flag to true
        done = true;
    }
});

//Start polling every 100ms to see if we are done
var intervalId = setInterval(function() {
    if(done) {
        //If we are done, let's say so and exit.
        console.log("Done.");
        phantom.exit();
    } else {
        //If we're not done we're just going to say that we're polling
        console.log("Polling...");
    }
}, 100);

And running it as the default user produces:

并以默认用户身份运行它会产生:

docker run -i -t -v $(pwd):/pwd -w /pwd --rm wernight/phantomjs phantomjs google.js 
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Site rendered...
Done.

But no google.pngand no error. Simply adding -u rootto the docker command solves this, and I get the google.pngin my CWD.

但没有google.png也没有错误。只需添加-u root到 docker 命令即可解决此问题,并且我google.png在 CWD 中得到了。

For completeness, the final command:

为了完整起见,最后的命令:

docker run -u root -i -t -v $(pwd):/pwd -w /pwd --rm wernight/phantomjs phantomjs google.js

docker run -u root -i -t -v $(pwd):/pwd -w /pwd --rm wernight/phantomjs phantomjs google.js