在观看YouTube视频时,PhantomJS不会模仿浏览器行为

Sea*_*ean 12 javascript phantomjs

我在一周前将这个问题发布到PhantomJS邮件列表中,但没有得到回应.希望在这里有更好的运气......

我一直在尝试使用PhantomJS从YouTube上获取信息,但却无法使其正常运行.

考虑通过iframe元素嵌入到网页中的YouTube视频.如果将src属性引用的URL直接加载到浏览器中,则会获得视频的整页版本,其中视频封装在embed元素中.初始页面内容中不存在嵌入元素; 相反,页面上的一些脚本标记导致一些Javascript被评估,最终将嵌入元素添加到DOM.我想能够在它出现时访问这个embed元素,但是当我在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);
  }
});
Run Code Online (Sandbox Code Playgroud)

无论我设置多长时间,我都只会在控制台上看到"0".如果我查找"DIV"元素,我得到"3",如果我查找"SCRIPT"元素,我得到"5",所以代码似乎是合理的.我从来没有找到任何"EMBED"标签,即使我在浏览器中加载上面的URL,我也会在页面加载后立即找到一个.

有谁知道问题可能是什么?在此先感谢您的帮助.

Sea*_*ean 9

帕特里克的回答让我走上正轨,但完整的故事如下.

Youtube的Javascript在决定是否创建某种视频元素之前探测浏览器的功能.在浏览了缩小的代码之后,我最终能够通过包装document.createElement页面的onInitialized回调来欺骗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;
    };
  });
};
Run Code Online (Sandbox Code Playgroud)

然而,这是一个失误; 为了得到我最初的<embed>标签,我需要让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 } }
    };
  });
};
Run Code Online (Sandbox Code Playgroud)

这就是它的完成方式.