【问题标题】:HTML output from PhantomJS and Google Chrome/Firefox are differentPhantomJS 和 Google Chrome/Firefox 的 HTML 输出不同
【发布时间】:2014-05-14 05:46:49
【问题描述】:

我已经调试了很长时间,这让我完全困惑。我需要将广告保存到我的计算机以进行工作项目。这是我从 CNN.com 获得的示例广告:

http://ads.cnn.com/html.ng/site=cnn&cnn_pagetype=main&cnn_position=300x250_rgt&cnn_rollup=homepage&page.allowcompete=no&params.styles=fs&Params.User.UserID=5372450203c5be0a3c695e599b05d821&transactionID=13999976982075532128681984&tile=2897967999935&domId=6f4501668a5e9d58&kxid=&kxseg=

当我在 Google Chrome 和 Firefox 中访问此链接时,我看到了一个广告(如果链接停止工作,只需访问 CNN.com 并获取其中一个广告的 iframe URL)。我开发了一个 PhantomJS 脚本,它将保存屏幕截图和任何页面的 HTML。它适用于任何网站,但似乎不适用于这些广告。屏幕截图为空白,HTML 包含一个跟踪像素(用于跟踪广告的 1x1 透明 gif)。我认为它会给我在普通浏览器中看到的内容。

我唯一能想到的是 AJAX 调用以某种方式弄乱了 PhantomJS,所以我硬编码了延迟,但得到了相同的结果。

这是重现我的问题的最基本的测试代码:

var fs = require('fs');
var page = require('webpage').create();
var url = phantom.args[0];

page.open(url, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    }
    else {
        // Output Results Immediately
        var html = page.evaluate(function () {
            return document.getElementsByTagName('html')[0].innerHTML;
        });
        fs.write("HtmlBeforeTimeout.htm", html, 'w');
        page.render('RenderBeforeTimeout.png');

        // Output Results After Delay (for AJAX)
        window.setTimeout(function () {
            var html = page.evaluate(function () {
                return document.getElementsByTagName('html')[0].innerHTML;
            });
            fs.write("HtmlAfterTimeout.htm", html, 'w');
            page.render('RenderAfterTimeout.png');
            phantom.exit();
        }, 9000); // 9 Second Delay 
    }
});

您可以在终端中使用此命令运行此代码:

phantomjs getHtml.js 'http://www.google.com/'

上述命令运行良好。当您将 Google URL 替换为广告 URL(如本文顶部的那个)时,会得到我所解释的意外结果。

非常感谢您的帮助!这是我在这里发布的第一个问题,因为我几乎总能通过搜索 Stack Overflow 找到答案。然而,这一个让我完全难住了! :)

编辑:我在 Ubuntu 14.04 (Trusty Tahr) 上运行 PhantomJS 1.9.7

编辑:好的,我已经研究了一段时间,我认为这与 cookie 有关。如果我清除所有历史记录并在浏览器中查看链接,它也会出现空白。如果我然后刷新页面,它显示正常。如果我在新选项卡中打开它,它也显示得很好。唯一没有的情况是我在清除我的 cookie 后尝试直接查看它。

编辑:我尝试在 PhantomJS 中加载链接两次而不退出(在调用 phantom.exit() 之前在我的脚本中手动请求两次)。它不起作用。在 PhantomJS 文档中,它说默认情况下启用 cookie jar。有任何想法吗? :)

【问题讨论】:

  • 这真是个笨蛋!无论我尝试什么,我都只能得到 1x1 黑色图像。我想知道这是否与某些广告在嵌入式 Flash 播放器中运行这一事实有关? PhantomJS 从 1.5 版开始不再支持 Flash,以允许 PhantomJS 完全无头运行而无需 xvfb。值得一试的是 SlimerJS,它使用 Gecko 引擎而不是 Webkit,它支持 Flash 并且具有与 PhantomJS 几乎相同的 API。

标签: javascript html phantomjs scrape scraper


【解决方案1】:

您应该尝试使用 onLoadFinished 回调而不是在 page.open 中检查状态。像这样的东西应该可以工作:

var fs = require('fs');
var page = require('webpage').create();
var url = phantom.args[0];

page.open(url);

page.onLoadFinished = function()
{
    // Output Results Immediately
    var html = page.evaluate(function () {
        return document.getElementsByTagName('html')[0].innerHTML;
    });
    fs.write("HtmlBeforeTimeout.htm", html, 'w');
    page.render('RenderBeforeTimeout.png');

    // Output Results After Delay (for AJAX)
    window.setTimeout(function () {
        var html = page.evaluate(function () {
            return document.getElementsByTagName('html')[0].innerHTML;
        });
        fs.write("HtmlAfterTimeout.htm", html, 'w');
        page.render('RenderAfterTimeout.png');
        phantom.exit();
    }, 9000); // 9 Second Delay 
};

我在这里有一个答案,它遍历本地文件夹中的所有文件并保存结果页面的图像:Using Phantom JS to convert all HTML files in a folder to PNG 同样的原则也适用于远程 HTML 页面。

这是我从输出中得到的:
超时前:
http://i.stack.imgur.com/GmsH9.jpg

超时后:
http://i.stack.imgur.com/mo6Ax.jpg

【讨论】:

  • 似乎是合理的,尤其是因为您开始加载的只是一堆 JS 以便稍后渲染 iframe,这里的时间对于渲染的内容变得很重要。
  • 我只是将 OP 的原始代码移动到 onLoadFinished 回调中。 9 秒的延迟与 OP 一样。
  • 抱歉评论是针对 OP 的。我同意你的看法:)
  • @dbrin 没问题! :)
  • 感谢您的快速回复!我将您的代码复制并粘贴到一个新文件中并进行了测试。输出与我的完全相同(它与 Google 链接配合得很好,但与 CNN 的广告不配合)。你还有其他建议吗? :)
猜你喜欢
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 2019-08-25
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多