【问题标题】:PhantomJS not mimicking browser behavior when looking at YouTube videosPhantomJS 在观看 YouTube 视频时不会模仿浏览器行为
【发布时间】:2018-04-13 12:02:46
【问题描述】:

我在一周前将这个问题发布到了 PhantomJS 邮件列表,但没有得到任何回复。希望在这里好运...

我一直在尝试使用 PhantomJS 从 YouTube 上抓取信息,但无法正常工作。

考虑通过 iframe 元素嵌入网页的 YouTube 视频。如果您将 src 属性引用的 URL 直接加载到浏览器中,您将获得视频的整页版本,其中视频被封装在 embed 元素中。 embed 元素不存在于初始页面内容中;相反,页面上的一些脚本标签会导致一些 Javascript 被评估,最终将 embed 元素添加到 DOM。我希望能够在它出现时访问这个嵌入元素,但是当我在 PhantomJS 中加载页面时它永远不会出现。

这是我正在使用的代码:

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

page.settings.userAgent = "Mozilla/5.0 (X11; rv:24.0) Gecko/20130909 Firefox/24.0";

page.open("https://www.youtube.com/embed/dQw4w9WgXcQ", function (status) {
  if (status !== "success") {
    console.log("Failed to load page");
    phantom.exit();
  } else {
    setTimeout(function () {
      var size = page.evaluate(function () {
        return document.getElementsByTagName("EMBED").length;
      });
      console.log(size);
      phantom.exit();
    }, 15000);
  }
});

无论我设置了多长时间,我都只看到控制台打印出“0”。如果我寻找“DIV”元素,我得到“3”,如果我寻找“SCRIPT”元素,我得到“5”,所以代码似乎是正确的。我只是从来没有找到任何“嵌入”标签,即使我在浏览器中加载上面的 URL,我确实在页面加载后很快就找到了。

有人知道问题可能是什么吗?提前感谢您的帮助。

【问题讨论】:

  • 您是否尝试过将完整的 HTML 转储到控制台?可能是 YouTube 响应的内容与您在浏览器中看到的内容不同,可能是基于用户代理过滤。
  • 这就是为什么我在上面的代码中将 User-Agent 设置为我实际浏览器使用的字符串。
  • 嗯。所以你也是。对不起;从移动设备上发布了该评论。尽管如此:您是否已经倾倒了完整的 HTML 以查看您得到了什么?
  • 我不记得我是否在一周前的实验中尝试过这个。但是,如果我发送与浏览器相同的用户代理,是否有任何理由期待不同的 HTML?我编写的程序可以进行相当多的自动 Web 访问,我想不出任何我无法使行为正常的网站,只是适当地设置用户代理。
  • 好吧,我同意用户代理可能不是它。但是,由于您的脚本没有找到 <embed> 标记,问题是为什么不找到。完整的 HTML 可能会回答这个问题。

标签: javascript phantomjs


【解决方案1】:

Patrick 的回答让我走上了正轨,但全文如下。

Youtube 的 Javascript 在决定是否创建某种视频元素之前会探测浏览器的功能。在浏览了缩小的代码之后,我最终能够通过在页面的 onInitialized 回调中包装 document.createElement 来欺骗 Youtube,使其认为 PhantomJS 支持 HTML5 视频。

page.onInitialized = function () {
  page.evaluate(function () {
    var create = document.createElement;
    document.createElement = function (tag) {
      var elem = create.call(document, tag);
      if (tag === "video") {
        elem.canPlayType = function () { return "probably" };
      }
      return elem;
    };
  });
};

但是,这是一个失误;为了获得我最初想要的 标签,我需要让 Youtube 的代码认为 PhantomJS 支持 Flash,而不是 HTML5 视频。这也是可行的:

page.onInitialized = function () {
  page.evaluate(function () {
    window.navigator = {
      plugins: { "Shockwave Flash": { description: "Shockwave Flash 11.2 e202" } },
      mimeTypes: { "application/x-shockwave-flash": { enabledPlugin: true } }
    };
  });
};

原来如此。

【讨论】:

  • 嗨@Sean,我正在尝试使用 PhantomJS 捕获 Youtube 的屏幕截图,但我就是不能。我没有看到任何错误 - 正在加载页面,但视频窗口为黑色。我尝试将您的 sn-p 代码放在我的脚本中的任何地方,但每次都显示为黑色。你能举一个完整的例子来说明如何使用它吗?非常感谢;)
  • @elad 我认为这是不可能的。我的代码所做的只是诱使 Youtube 认为 phantomjs 支持视频播放,因此它会在页面上插入
  • 当我想截取网站的屏幕截图时,这是否有效?因为我收到“此设备不支持视频播放”
  • 谢谢,为我工作!我发现获得动态加载的视频 src 的唯一方法是使用您的代码
【解决方案2】:

phantomjs 执行not support flash,或html5 video element

【讨论】:

  • 我不希望它支持这些东西。我所期望的是 Youtube 的 Javascript 应该像在我的浏览器中那样向 DOM 添加一个 标签,这在 PhamtomJS 中不会有任何进一步的影响,但我可以读取它的属性。
  • 是的 - 但它不会在视频开始播放之前注入嵌入。在任何其他检查器中检查来源。
  • 你失去了我。我根本不希望播放视频,只是为了添加一个嵌入标签。为什么不是?
  • 因为在您点击开始播放视频之前它不会添加嵌入。
  • 这不是我看到的。例如,在我访问上面代码中的 URL 后,我可以让我的浏览器检查 DOM 并告诉我它找到了多少嵌入元素,我得到 1。那时我还没有以任何方式与页面交互,当然不是通过开始播放视频。
【解决方案3】:

作为选项 - 尝试自己构建具有视频/音频支持的 phantomjs

原答案链接:https://github.com/ariya/phantomjs/issues/10839#issuecomment-331457673

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2013-06-28
    • 2011-04-08
    • 1970-01-01
    相关资源
    最近更新 更多