Prendre des captures d'écran fiables sur les sites Web? Phantomjs et Casperjs renvoient tous deux des tirs vides sur certains sites

Ouvrez une page Web et prenez une capture d'écran.

Utiliser UNIQUEMENT phantomjs: (c'est un script simple, en fait c'est le script d'exemple utilisé dans leurs documents. Http://phantomjs.org/screen-capture.html

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

Le problème est que, pour certains sites Web (comme github) assez drôle, ils détectent et ne servent pas de phantomjs et rien n'est rendu. Le résultat est github.png est un fichier blanc png blanc.

Remplacez github avec say: "google.com" et vous obtenez une belle capture d'écran (appropriée) comme cela est prévu.

Au début, je pensais que c'était une question Phantomjs, alors j'ai essayé de l'exécuter à travers Casperjs avec:

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

Mais j'ai le même comportement que chez Phantomjs.

Donc, j'ai bien compris, c'est probablement un problème d'agent utilisateur. Comme dans: Github renifle Phantomjs et décide de ne pas montrer la page. J'ai donc configuré l'agent utilisateur comme ci-dessous mais cela ne fonctionnait toujours pas.

 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(); }); 

Ensuite, j'ai essayé d'analyser la page et, apparemment, certains sites (à nouveau comme Github) ne semblent pas envoyer quoi que ce soit sur le fil.

À l'aide de casperjs, j'ai essayé d'imprimer le titre. Et pour google.com, j'ai récupéré Google mais pour github.com, j'ai récupéré les bupkis. Exemple de code:

 var casper = require('casper').create(); casper.start('http://github.com/', function() { this.echo(this.getTitle()); }); casper.run(); 

Le même résultat ci-dessus produit également le même résultat en purement phantomjs.

Mettre à jour:

Cela pourrait-il être un problème de chronométrage? Github est-il vraiment super lent? Je n'en doute que pour tester de toute façon …

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

Et le résultat est encore bupkis. Donc, ce n'est pas un problème temporel.

  1. Comment certains sites comme github bloquent des phantomjs?
  2. Comment peut-on prendre des captures d'écran fiables de TOUTES les pages Web? Obligation d'être rapide et sans tête.

Après avoir relancé pendant un certain temps, j'ai pu affiner le problème. Apparemment, PhantomJS utilise un ssl par défaut de sslv3 qui fait que Github refuse la connexion en raison d'une mauvaise poignée de main ssl

 phantomjs --debug=true github.js 

Affiche la sortie 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 

Par conséquent, nous pouvons conclure qu'aucun écran n'a été pris parce que Github a refusé la connexion. C'est vraiment logique. Donc, définissons le drapeau SSL dans --ssl-protocol=any et laissez également ignorer les erreurs ssl avec --ignore-ssl-errors=true

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

Grand succès! Une capture d'écran est maintenant rendue et enregistrée correctement, mais le débogueur nous montre 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 

J'ai vérifié la page d'accueil de github manuellement pour voir si TypeError existait et il ne l'est PAS.

Ma prochaine supposition est que les actifs ne sont pas suffisamment chargésPhantomjs est plus rapide qu'une balle excès de vitesse!

Alors essayons de ralentir artificiellement et de voir si nous pouvons nous débarrasser de ce 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); }); 

Cela n'a pas fonctionné … Après une inspection plus approfondie de l'image – il est clair que certains éléments manquent. Principalement des icônes et le logo.

Succès? Partiellement parce que nous recevons maintenant au moins une capture d'écran plus tôt, nous n'obtiendrions rien.

Travail terminé? Pas exactement. Besoin de déterminer ce qui provoque ce TypeError car il empêche certains actifs de charger et de déformer l'image.

Supplémentaire

Tentative de recréer avec CasperJS –debug est très moche et difficile à suivre par rapport à 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(); 

console:

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

En outre, l'image manquait les mêmes icônes, mais elle est également déformée visuellement. Étant donné que CasperJs s'appuie sur Phantomjs, je ne vois pas la valeur de l'utiliser pour cette tâche spécifique.

Si vous souhaitez ajouter à ma réponse, partagez vos résultats. Très intéressé par une solution PhantomJS impeccable

Mise à jour n ° 1: Suppression de TypeError

@ArtjomB souligne que Phantomjs ne prend pas en charge js bind dans sa version actuelle à partir de cette mise à jour (1.9.7). Pour cette raison, il explique: ArtjomB: PhantomJs Bind Answer

The TypeError: 'undefined' n'est pas une fonction qui se réfère à bind, car PhantomJS 1.x ne le supporte pas. PhantomJS 1.x utilise une ancienne fourchette de QtWebkit qui est comparable à Chrome 13 ou Safari 5. Le nouveau PhantomJS 2 utilisera un moteur plus récent qui prend en charge bind. Pour l'instant, vous devez ajouter une calque à l'intérieur de la page.on gestionnaire d'événements inactivé:

OK, alors le code suivant prendra soin de notre TypeError par dessus. (Mais pas entièrement fonctionnel, voir ci-dessous pour plus de détails)

 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; } }); } 

Maintenant, le code ci-dessus nous obtiendra une capture d'écran identique à celle que nous TypeError avant et le débogueur ne montrera pas un TypeError donc de la surface, tout semble fonctionner. Des progrès ont été réalisés.

Malheureusement, toutes les icônes d'image [logo, etc.] ne sont toujours pas correctement chargées. Nous voyons une sorte d'icone 3W qui ne sait pas d'où cela se produit.

Merci pour l'aide @ArtjomB

Entrez la description de l'image ici