Maison  >  Article  >  interface Web  >  Exemple de fonction d'exploration Web simple implémentée par Node.js_node.js

Exemple de fonction d'exploration Web simple implémentée par Node.js_node.js

WBOY
WBOYoriginal
2016-05-16 16:28:491281parcourir

De nos jours, l'exploration du Web est une technologie bien connue, mais il existe encore de nombreuses complexités. Les robots d'exploration Web simples sont encore difficiles à gérer diverses technologies complexes telles que la formation à la rotation Ajax, XMLHttpRequest, WebSockets, Flash Sockets, etc. site web.

Prenons comme exemple nos besoins de base sur le projet Hubdoc. Dans ce projet, nous récupérons les montants des factures, les dates d'échéance, les numéros de compte et, plus important encore, les sites Web des banques, des services publics et des sociétés de cartes de crédit de : pdf des factures récentes. Pour ce projet, j'ai commencé avec une solution très simple (n'utilisant pas les produits commerciaux coûteux que nous évaluons pour le moment) - un simple projet de robot d'exploration que j'avais réalisé avant d'utiliser Perl chez MessageLab/Symantec. Mais les résultats ont été désastreux. Les spammeurs ont créé des sites Web bien plus simples que ceux des banques et des services publics.

Alors comment résoudre ce problème ? Nous avons principalement commencé par utiliser l'excellente librairie request développée par Mikea. Faites une requête dans le navigateur, vérifiez dans la fenêtre Réseau quels en-têtes de requête sont envoyés, puis copiez ces en-têtes de requête dans le code. Le processus est simple. Il suit simplement le processus depuis la connexion jusqu'au téléchargement du fichier PDF, puis simule toutes les demandes de ce processus. Afin de faciliter la gestion de choses similaires et de permettre aux développeurs Web d'écrire des programmes d'exploration de manière plus rationnelle, j'ai exporté la méthode d'obtention des résultats du HTML vers jQuery (en utilisant la bibliothèque légère cheerio), qui fait des choses similaires tâches faciles et facilite également l'utilisation des sélecteurs CSS pour sélectionner des éléments sur une page. L'ensemble du processus est intégré dans un framework, et ce framework peut également effectuer un travail supplémentaire, tel que la récupération de certificats dans la base de données, le chargement de robots individuels et la communication avec l'interface utilisateur via socket.io.

Cela fonctionne pour certains sites Web, mais il s'agit simplement d'un script JS, pas de mon code node.js que ces sociétés mettent sur leurs sites. Ils ont superposé les problèmes hérités sur la complexité, ce qui rend très difficile de déterminer quoi faire pour obtenir le point d'information de connexion. J'ai essayé pendant plusieurs jours d'obtenir des sites en combinant avec la bibliothèque request(), mais toujours en vain.

Après avoir failli planter, j'ai découvert node-phantomjs, une bibliothèque qui me permet de contrôler le navigateur phantomjs headless webkit depuis node (Note du traducteur : je n'ai pas ça) En pensant à un nom correspondant, headless signifie ici que le rendu de la page est effectué en arrière-plan sans périphérique d'affichage). Cela semble être une solution simple, mais il reste encore quelques problèmes inévitables avec phantomjs qui doivent être résolus :

1. PhantomJS peut uniquement vous dire si la page a été chargée, mais vous ne pouvez pas déterminer s'il y a une redirection via JavaScript ou des balises méta dans le processus. Surtout lorsque JavaScript utilise setTimeout() pour retarder les appels.

2.PhantomJS vous fournit un hook pageLoadStarted qui vous permet de gérer les problèmes mentionnés ci-dessus, mais cette fonction ne peut être utilisée que lorsque vous déterminez le nombre de pages à charger et lorsque chaque page est chargée, diminuez ce nombre. et gérez les éventuels délais d'attente (puisque cela n'arrive pas toujours) afin que lorsque votre nombre diminue à 0, votre fonction de rappel soit appelée. Cette approche fonctionne, mais elle ressemble toujours un peu à un hack.

3. PhantomJS nécessite un processus indépendant complet pour chaque page qu'il explore, car sinon, les cookies entre chaque page ne peuvent pas être séparés. Si vous utilisez le même processus phantomjs, la session sur la page de connexion sera envoyée vers une autre page.

4. Impossible de télécharger des ressources à l'aide de PhantomJS - vous ne pouvez enregistrer la page qu'au format png ou pdf. C'est utile, mais cela signifie que nous devons recourir à request() pour télécharger le pdf.

5. Pour les raisons ci-dessus, je dois trouver un moyen de distribuer les cookies de la session de PhantomJS vers la bibliothèque de session de request(). Distribuez simplement la chaîne document.cookie, analysez-la et injectez-la dans le pot à cookies request().

6. Injecter des variables dans la session du navigateur n'est pas facile. Pour ce faire, je dois créer une chaîne pour créer une fonction Javascript.

Copier le code Le code est le suivant :

Robot.prototype.add_page_data = fonction (page, nom, données) {
page.évaluer(
"function () { var " nom " = fenêtre." nom " = " JSON.stringify(data) "}"
);
>

7. Certains sites Web sont toujours pleins de codes tels que console.log(), et ils doivent être redéfinis et affichés à l'emplacement souhaité. Pour y parvenir, je fais ceci :
Copier le code Le code est le suivant :

si (!console.log) {
var iframe = document.createElement("iframe");
​ document.body.appendChild(iframe);
console = window.frames[0].console;
>

8. Certains sites Web sont toujours pleins de codes tels que console.log(), et ils doivent être redéfinis et affichés à l'emplacement souhaité. Pour y parvenir, je fais ceci :

Copier le code Le code est le suivant :

si (!console.log) {
var iframe = document.createElement("iframe");
​ document.body.appendChild(iframe);
console = window.frames[0].console;
>

9. Il n'est pas facile de dire au navigateur que j'ai cliqué sur la balise a. Afin de compléter ces choses, j'ai ajouté le code suivant :
.
Copier le code Le code est le suivant :

var clickElement = window.clickElement = function (id){
var a = document.getElementById(id);
var e = document.createEvent("MouseEvents");
e.initMouseEvent("clic", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
a.dispatchEvent(e);
};

10. Je dois également limiter la simultanéité maximale des sessions de navigateur pour m'assurer que nous ne ferons pas exploser le serveur. Cela dit, cette limite est bien supérieure à ce que peuvent offrir des solutions commerciales coûteuses. (Note du traducteur : la solution commerciale a une plus grande concurrence que cette solution)

Une fois tout le travail terminé, j'ai une solution décente de robot d'exploration de requêtes PhantomJS. Vous devez vous connecter à l'aide de PhantomJS avant de pouvoir revenir à la requête request(). Elle utilisera le cookie défini dans PhantomJS pour authentifier la session connectée. C'est une énorme victoire car nous pouvons utiliser le flux de request() pour télécharger le fichier pdf.

L'ensemble du plan est de permettre aux développeurs Web de comprendre relativement facilement comment utiliser les sélecteurs jQuery et CSS pour créer des robots d'exploration pour différents sites Web. Je n'ai pas encore réussi à prouver que cette idée est réalisable, mais je pense qu'elle le sera bientôt. .

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn