Tomando capturas de pantalla confiables de sitios web? Phantomjs y Casperjs devuelven capturas de pantalla vacías en algunos sitios web


Abra una página web y tome una captura de pantalla.

Usando SOLO phantomjs: (este es un script simple, de hecho es el script de ejemplo usado en sus documentos. http://phantomjs.org/screen-capture.html

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

El problema es que para algunos sitios web (como github) lo suficientemente divertidos están detectando y no sirviendo phantomjs y no se está renderizando nada. El resultado es github.png es un archivo png blanco en blanco.

Reemplace github por decir: "google.com" y se obtiene un buen (adecuado) captura de pantalla como se pretende.

Al principio pensé que esto era un problema de Phantomjs, así que intenté ejecutarlo a través de Casperjs con:

casper.start('http://www.github.com/', function() {
    this.captureSelector('github.png', 'body');
});

casper.run();

Pero tengo el mismo comportamiento que con Phantomjs.

Así que pensé ok esto es más probable un problema de agente de usuario. Como en: Github olfatea Phantomjs y decide no mostrar la página. Así que configuré el agente de usuario como abajo pero eso aún no funcionó.

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36';
page.open('http://github.com/', function() {
  page.render('github.png');
  phantom.exit();
});

Entonces traté de analizar la página y aparentemente algunos sitios (de nuevo como github) no parece estar enviando nada por el cable.

Usando casperjs intenté imprimir el título. Y para google.com He vuelto Google pero para github.com Tengo bupkis de vuelta. Código de ejemplo:

var casper = require('casper').create();

casper.start('http://github.com/', function() {
    this.echo(this.getTitle());
});

casper.run();  

Lo mismo que arriba también produce el mismo resultado en puras phantomjs.

Actualización:

¿Podría ser esto un problema de tiempo? ¿Github es súper lento? Lo dudo, pero probemos de todos modos..

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

Y el resultado sigue siendo bupkis. Así que no, no es un tiempo cuestión.

  1. ¿Cómo son algunos sitios como github bloqueando phantomjs?
  2. ¿Cómo podemos tomar capturas de pantalla confiables de TODAS las páginas web? Requiere ser rápido y sin cabeza.
Author: fabbb, 2014-10-23

1 answers

Después de rebotar esto durante algún tiempo, pude reducir el problema. Aparentemente PhantomJS usa un ssl predeterminado de sslv3 que hace que github rechace la conexión debido a un mal apretón de manos ssl

phantomjs --debug=true github.js

Muestra la salida de:

. . .
2014-10-22T19:48:31 [DEBUG] WebPage - updateLoadingProgress: 10 
2014-10-22T19:48:32 [DEBUG] Network - Resource request error: 6 ( "SSL handshake failed" ) URL: "https://github.com/" 
2014-10-22T19:48:32 [DEBUG] WebPage - updateLoadingProgress: 100 

Así que de esto podemos concluir que no se tomó ninguna pantalla porque github estaba rechazando la conexión. Genial, eso tiene mucho sentido. Así que vamos a establecer la bandera SSL a --ssl-protocol=any y también vamos a ignorar los errores ssl con --ignore-ssl-errors=true

phantomjs --ignore-ssl-errors=true --ssl-protocol=any --debug=true github.js

Gran éxito! Una captura de pantalla ahora se está renderizando y guardando correctamente, pero debugger nos muestra un TypeError:

TypeError: 'undefined' is not a function (evaluating 'Array.prototype.forEach.call.bind(Array.prototype.forEach)')

  https://assets-cdn.github.com/assets/frameworks-dabc650f8a51dffd1d4376a3522cbda5536e4807e01d2a86ff7e60d8d6ee3029.js:29
  https://assets-cdn.github.com/assets/frameworks-dabc650f8a51dffd1d4376a3522cbda5536e4807e01d2a86ff7e60d8d6ee3029.js:29
2014-10-22T19:52:32 [DEBUG] WebPage - updateLoadingProgress: 72 
2014-10-22T19:52:32 [DEBUG] WebPage - updateLoadingProgress: 88 
ReferenceError: Can't find variable: $

  https://assets-cdn.github.com/assets/github-fa2f009761e3bc4750ed00845b9717b09646361cbbc3fa473ad64de9ca6ccf5b.js:1
  https://assets-cdn.github.com/assets/github-fa2f009761e3bc4750ed00845b9717b09646361cbbc3fa473ad64de9ca6ccf5b.js:1

Revisé la página de inicio de github manualmente solo para ver si existía un error de tipo y NO lo hace.

Mi siguiente conjetura es que los activos no se cargan lo suficientemente rápido.. ¡Phantomjs es más rápido que una bala a toda velocidad!

Así que vamos a tratar de ralentizarlo artificialmente y ver si podemos deshacernos de eso TypeError...

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36';
page.open('http://github.com', function (status) {
   window.setTimeout(function () {
            page.render('github.png');
            phantom.exit();
        }, 3000);
});

Eso no funcionó... Después de una inspección más cercana de la imagen - está claro que faltan algunos elementos. Principalmente algunos iconos y el logotipo.

¿Éxito? En parte porque ahora al menos estamos recibiendo una captura de pantalla donde antes, no estábamos recibiendo nada.

Trabajo realizado? No exactamente. Necesidad de determinar lo que está causando que TypeError, ya que la prevención de algunos activos de carga y distorsionar la imagen.

Adicional

Intentó recrear con CasperJS deb debug es muy feo y difícil de seguir en comparación con PhantomJS:

casper.start();
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
casper.thenOpen('https://www.github.com/', function() {
    this.captureSelector('github.png', 'body');
});

casper.run();

Consola:

casperjs test --ssl-protocol=any --debug=true github.js

Además, a la imagen le faltan los mismos iconos, pero también está distorsionada visualmente. Siendo que CasperJS confía en Phantomjs, no veo el valor de usarlo para esta tarea específica.

Si desea agregar algo a mi respuesta, por favor comparta sus hallazgos. Muy interesado en un PhantomJS impecable solución

Actualización # 1: Eliminar el TypeError

@ArtjomB señala que Phantomjs no soporta js bind en su versión actual a partir de esta actualización (1.9.7). Por esta razón explica: ArtjomB: PhantomJS Bind Issue Answer

El TypeError: 'undefined' no es una función se refiere a bind, porque PhantomJS 1.x no lo soporta. PhantomJS 1.x utiliza un viejo tenedor de QtWebKit que es comparable a Chrome 13 o Safari 5. El más nuevo PhantomJS 2 utilizará un motor más nuevo que soportará bind. Por ahora es necesario añadir una cuña dentro de la página.Un manejador de eventos inicializado:

Ok genial, por lo que el siguiente código se encargará de nuestro TypeError desde arriba. (Pero no completamente funcional, ver más abajo para más detalles)

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36';
page.open('http://github.com', function (status) {
   window.setTimeout(function () {
            page.render('github.png');
            phantom.exit();
        }, 5000);
});
page.onInitialized = function(){
    page.evaluate(function(){
        var isFunction = function(o) {
          return typeof o == 'function';
        };

        var bind,
          slice = [].slice,
          proto = Function.prototype,
          featureMap;

        featureMap = {
          'function-bind': 'bind'
        };

        function has(feature) {
          var prop = featureMap[feature];
          return isFunction(proto[prop]);
        }

        // check for missing features
        if (!has('function-bind')) {
          // adapted from Mozilla Developer Network example at
          // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
          bind = function bind(obj) {
            var args = slice.call(arguments, 1),
              self = this,
              nop = function() {
              },
              bound = function() {
                return self.apply(this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments)));
              };
            nop.prototype = this.prototype || {}; // Firefox cries sometimes if prototype is undefined
            bound.prototype = new nop();
            return bound;
          };
          proto.bind = bind;
        }
    });
}

Ahora el código anterior nos dará una captura de pantalla igual que antes Y debug no mostrará un TypeError por lo que desde la superficie, todo parece funcionar. El progreso ha sido hecho.

Desafortunadamente, todos los iconos de la imagen [logotipo, etc] todavía no se cargan correctamente. Vemos algún tipo de 3W icono no estoy seguro de dónde es eso.

Gracias por la ayuda @ArtjomB

introduzca la descripción de la imagen aquí

 26
Author: fabbb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:16