【问题标题】:PHP-PhantomJS renders screenshots on different servers differentlyPHP-PhantomJS 在不同服务器上以不同方式呈现屏幕截图
【发布时间】:2015-10-27 05:52:34
【问题描述】:

今天,我一直致力于为我的一个项目生成网站屏幕截图的解决方案。在深入研究了网上的各种主题后,我得出的结论是,使用 PhantomJS 可能是我的最佳选择。

由于我运行的是 vagrant (Homestead) 本地服务器,因此我需要将来自 jonnyw/php-phantomjs (https://packagist.org/packages/jonnyw/php-phantomjs) 的包放入现有项目并使用基本脚本启动:

$client = Client::getInstance();
$client->debug(true);
$client->setBinDir('/home/admin/domains/domain.com/public_html/bin/');

$request = $client->getMessageFactory()->createCaptureRequest('http://www.domain.com/preview/H/31', 'GET');
$request->setCaptureFile('/home/admin/domains/domain.com/public_html/screens/sample.jpg');
$request->setViewportSize(1366, 768);

$response = $client->getMessageFactory()->createResponse();
$client->send($request, $response);

在代码停止抛出警告之前我花了一点时间,但最终代码正常运行!然后我继续将代码迁移到它应该在的项目中,该项目是用过程 php 代码编写的。我需要这个包,包括自动加载器,它执行的命令与我的 Vagrant 环境中的命令完全相同。

结果有点不同:没有显示标题,也没有显示背景图片。我可能需要补充一点,标题附加了一个自定义字体。

几周前,我为需要 Laravel 的客户端设置了一个服务器,我还需要该服务器上的包并执行相同的代码。起初我得到一些随机的白页,但最终我得到了我期望的截图。我可以忍受截图变成白色的事实,只要它们最终正确出现。

然后我回到该脚本的目标代码,并对其进行了更多尝试。但结果一直是白色或缺少一些元素(自定义字体标题+​​背景图像)。我最后一次尝试是更改capture.proc 文件,我在渲染图像之前添加了一个 setTimeout 函数。这确实解决了一个问题:从那以后我没有任何白色图像,但没有解决最重要的问题:缺少标题和背景。

我已经仔细检查了所有 bin 文件,它们都使用 1.9.7 版的 PhantomJS,所以我怀疑那里存在问题。但是,服务器配置(或 PHP 版本)是否会导致脚本无法给出正确的结果?

只是为了提供尽可能多的信息,问题服务器是最低的 PHP 版本:

  • 问题服务器在 PHP 5.5.18 上
  • 工作服务器使用 PHP 5.5.27
  • Homestead 服务器使用 PHP 5.6.11

【问题讨论】:

  • 看起来您应该在加载页面后稍等片刻,然后再截屏 (sleep(2);?)。 Webfonts 通常在页面加载回调触发后加载(在普通的 PhantomJS 脚本中)。你在使用网络字体吗?您是否尝试过更长的超时时间?如果更长的超时不起作用,请尝试捕获流量(tcpdump)并查看是否重置了某些请求或类似的东西。我不知道如何在 php-phantomjs 中调试。另外,它是某种单页应用程序吗?如果是这样,那么在截取屏幕截图时它没有完全呈现在一定程度上是有道理的。
  • 再看一眼,你是对的。这在一定程度上取决于如何捕获图像的连接速度。使用延迟选项,图像在任何地方都呈现正确。谢谢!您可能希望将其添加为答案。

标签: php phantomjs screenshot php-phantomjs


【解决方案1】:

看起来您应该在加载页面后稍等片刻,然后再截取屏幕截图。单页应用程序和 Webfonts 通常需要一点时间来加载和呈现,而 PhantomJS 有点急于触发 load finished 事件并报告加载已完成。

您可以在...->createCaptureRequest(..) 和$request->setCaptureFile(...) 之间插入一个$request->setDelay(2);。见documentation。

使用静态延迟不是很可靠。最好使用waitFor() function,它会在满足条件(例如页面上出现特定页面元素)时立即触发。 php-phantomjs 没有通过它的 API 提供这样的功能,但是你可以直接使用 PhantomJS 脚本来做这种事情。请参阅documentation。

【讨论】:

  • 谢谢! setDelay 功能完美运行!我将深入研究 waitFor 函数。感谢您的快速帮助!
猜你喜欢
  • 1970-01-01
  • 2017-12-22
  • 2014-03-18
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 2015-10-30
  • 2012-03-03
相关资源
最近更新 更多