Récemment, j'ai besoin d'explorer les informations de l'article sur le compte officiel de WeChat. J'ai recherché en ligne et j'ai constaté que la difficulté de ramper les comptes publics WeChat est que le lien vers l'article officiel du compte ne peut pas être ouvert du côté PC. Nous devons utiliser le propre navigateur de WeChat (vous ne pouvez l'ouvrir que sur d'autres plates-formes après avoir obtenu les paramètres complétés par le client WeChat). Cela cause de grands problèmes au programme Crawler. Plus tard, j'ai vu un compte officiel de WECHAT rampant écrit par un grand gars sur Zhihu, et j'ai directement suivi l'idée du patron et je l'ai transformée en Java. J'ai rencontré de nombreux problèmes détaillés pendant la transformation, donc je vais le partager.
L'idée de base du système est d'exécuter WeChat sur l'émulateur Android, de configurer un proxy pour l'émulateur, d'intercepter les données WeChat via le serveur de proxy et d'envoyer les données obtenues à votre propre programme de traitement.
Environnements qui doivent être préparés: Nodejs, proxy anyproxy et émulateur Android
Adresse de téléchargement de Nodejs: http://nodejs.cn/download/. J'ai téléchargé la version Windows, il suffit de l'installer directement. Après l'installation, l'exécution des fichiers C: / Program / Nodejs / npm.cmd configurera automatiquement l'environnement.
Installation de AnyProxy: Après avoir installé des NodeJS en fonction de l'étape précédente, exécutez NPM Installer -g AnyProxy directement dans CMD et installer
Allez simplement à l'émulateur Android en ligne, beaucoup d'entre eux.
Tout d'abord, installez le certificat pour le serveur proxy. AnyProxy ne résout pas le lien HTTPS par défaut. Après avoir installé le certificat, il peut être résolu. Exécutez AnyProxy --Root dans CMD pour installer le certificat. Après cela, vous devez télécharger ce certificat dans l'émulateur.
Entrez ensuite la commande anyProxy -i pour ouvrir le service proxy. (N'oubliez pas d'ajouter des paramètres!)
N'oubliez pas cette adresse IP et ce port, puis l'agent de l'émulateur Android l'utilisera. Utilisez maintenant votre navigateur pour ouvrir la page Web: http: // localhost: 8002 / Il s'agit de l'interface Web d'AnyProxy, qui est utilisée pour afficher les données de transmission HTTP.
Cliquez sur le menu dans la boîte rouge ci-dessus et un code QR sera publié. Utilisez l'émulateur Android pour scanner le code pour l'identifier. L'émulateur (téléphone mobile) téléchargera le certificat et l'installera simplement.
Vous êtes maintenant prêt à configurer un proxy pour l'émulateur. La méthode de proxy est définie sur manuelle. L'IP proxy est l'IP qui exécute n'importe quelle machine Proxy, et le port est 8001
Le travail de préparation est essentiellement terminé ici. Ouvrez WeChat sur l'émulateur et ouvrez un article sur un compte public, et vous pouvez voir les données capturées par AnyProxy à partir de l'interface Web que vous venez d'ouvrir:
Le lien vers l'article WeChat est dans la boîte rouge ci-dessus. Cliquez pour voir les données spécifiques. S'il n'y a rien dans l'organisme de réponse, il y a un problème avec l'installation du certificat.
Si tout ce qui précède est terminé, vous pouvez continuer à descendre.
Ici, nous nous appuyons sur les services proxy pour capturer les données de WeChat, mais nous ne pouvons pas saisir un morceau de données et faire fonctionner nous-mêmes WeChat. C'est mieux de le copier manuellement. Nous avons donc besoin que le client WeChat saute en soi vers la page. À l'heure actuelle, vous pouvez utiliser AnyProxy pour intercepter les données renvoyées par le serveur WeChat, injecter le code de saut de page, puis retourner les données traitées au simulateur pour obtenir un saut automatique du client WeChat.
Ouvrez un fichier JS appelé dule_default.js dans anyProxy. Le fichier sous Windows est: c: / utilisateurs / administrateur / appdata / roaming / npm / node_modules / anyProxy / lib
Il existe une méthode appelée RepaceServerResDataaSync: fonction (req, res, serverresdata, rappel) dans le fichier. Cette méthode est chargée d'effectuer diverses opérations sur les données obtenues par AnyProxy. Au début, il ne devrait y avoir que du rappel (serverresData); Cette instruction signifie renvoyer directement les données de réponse du serveur au client. Supprimez directement cette déclaration et remplacez-la par le code suivant écrit par Daniu. Je n'ai apporté aucune modification au code ici, et les commentaires en elle sont expliqués très clairement. Il suffit de les lire directement selon la logique, et il n'y a pas de gros problème.
RemplaceServerResDataaSync: Function (req, res, serverresdata, rappel) {if (/mp//getmassendmsg/i.test (req.url)) {// Lorsque l'adresse du lien est la page de message historique du compte officiel (formulaire de première page) //console.log("Start la première page crawl "); if (serverresdata.toString ()! == "") {6 try {// empêcher les erreurs de quitter le programme var reg = / msglist = (. *?); /; // définir le message historique des règles de correspondance régulières var rever = reg.exec (serverresData.tostring ()); // convertir la variable à la corde Httppost (ret [1], req.url, "/ internetpider / getData / showbiz"); // Cette fonction est définie ultérieurement, envoyant le message historique correspondant JSON à son propre serveur var http = require (http '); http.get ('http: // xxx / getwxhis', function (res) {// Cette adresse est un programme sur son propre serveur. Le but est d'obtenir l'adresse de liaison suivante, placer l'adresse dans un script JS, et sauter automatiquement à la page suivante. Le principe de getwxhis.php sera introduit plus tard. rappel (chunk + serverresData); // insérer le code renvoyé dans la page de message historique et revenir pour l'afficher})}); } catch (e) {// Si le régulier ci-dessus ne correspond pas, le contenu de cette page peut être la deuxième page de la page de message historique du compte officiel, car la première page du message historique est au format HTML, et la deuxième page est au format JSON. //console.log("Start la première page rampe vers le bas "); try {var json = json.psese (serverresdata.toString ()); if (json.general_msg_list! = []) {httppost (json.general_msg_list, req.url, "/ xxx / showbiz"); // Cette fonction est définie ultérieurement comme ci-dessus, envoyant le JSON du message historique de la deuxième page à votre propre serveur}} catch (e) {console.log (e); // Capture d'erreur} rappel (serverresData); // retournez directement à la deuxième page JSON Content}} //console.log("Start la première page Crawl fin "); } else if (/mp//profile_ext/?action=home/i.test (req.url)) {// Lorsque l'adresse du lien est la page de message historique du compte officiel (le formulaire de deuxième page) essayez {var reg = / var msglist = /'(*?))/' ;/ ;///define les règles correspondantes régulières des messages historiques (différents de la première page de page régulière) reg.exec (serverresdata.toString ()); // convertit la variable en chaîne httppost (ret [1], req.url, "/ xxx / showbiz"); // Cette fonction est définie ultérieurement, envoyez le message historique correspondant à son propre serveur var http = requis (http '); http.get ('xxx / getwxhis', function (res) {// Cette adresse est un programme sur votre serveur. Le but est d'obtenir l'adresse de liaison suivante, de placer l'adresse dans un script JS, et de sauter automatiquement à la page suivante. Le principe de GetWxhis.php sera introduit plus tard. Res.on ('Data', Fonction) {Rappel (Callage) dans la page de message historique et revenir pour l'afficher})}); } catch (e) {//console.log(e); rappel (serverresData); }} else if (/mp//profile_ext/?action=getmsg/i.test (req.url)) {// L'expression de deuxième page json try {var json = json.parse (serverresdata.tostring ()); if (json.general_msg_list! = []) {httppost (json.general_msg_list, req.url, "/ xxx / showbiz"); // Cette fonction est définie ultérieurement comme ci-dessus, envoyant le json du message historique de la deuxième page à son propre serveur}} catch (e) {console.log (e); } rappel (serverresData); } else if (/mp//getappmsgext/i.test (req.url)) {// Lorsque l'adresse du lien est le nombre de vues et de goûts pour l'article de compte officiel, essayez {httppost (ServerResData, req.url, "/ xxx / getmsgext"); // La fonction est définie plus tard, et la fonction est à envoyer JSON avec le nombre de vues et goûts pour la fonction de la fin, et la fonction est à envoyer JSON avec le nombre de vues et aux goûts pour la fonction de la fin, et la fonction est pour envoyer JSON avec le nombre de vues et goûts pour la fin de l'article pour la plus grande server} catch (e) {} callback (serverresData); } else if (/ s /? __ biz / i.test (req.url) || /mp//rumor/i.test(req.url)) {//when L'adresse de liaison est l'article de compte officiel (l'adresse de la rumeur est l'article du compte officiel, il a été refusé) essayez {var http = require (http '); http.get ('http: // xxx / getwxpost', fonction (res) {// Cette adresse est un autre programme sur votre serveur. Le but est d'obtenir l'adresse du lien suivant, de placer l'adresse dans un script JS, et de sauter automatiquement vers la page suivante. Le principe de getwxpost.php sera introduit plus tard. })}); } catch (e) {callback (serverresData); }} else {callback (serverresData); } // callback (serverresData); },Permettez-moi d'expliquer brièvement ici qu'il existe deux formes de liens vers la page de message historique des comptes officiels de WeChat: l'un commence par mp.weixin.qq.com/mp/getmassendmsg, et l'autre commence par mp.weixin.qq.com/mp/profile_ext. La page d'histoire peut être retournée. S'il est basculé, il déclenchera l'événement JS pour envoyer une demande pour obtenir des données JSON (le contenu de la page suivante). Il existe également des liens d'articles de compte officiels, ainsi que des liens vers le nombre d'articles lus et likes (renvoyant les données JSON). Les formes de ces liens sont fixes et peuvent être distinguées par un jugement logique. Il y a une question ici: comment faire si toutes les pages d'histoire doivent être rampées. Mon idée est de simuler la souris glissante via JS, déclenchant ainsi la demande de soumettre une demande de chargement de la partie suivante de la liste. Ou utilisez directement AnyProxy pour analyser la demande de chargement de glissement et générer directement cette demande au serveur WeChat. Mais il y a un problème avec la façon de juger qu'il n'y a pas de données restantes. Je rampe les dernières données, et je n'ai pas cette exigence pour le moment, et je le souhaite à l'avenir. Si vous en avez besoin, vous pouvez l'essayer.
Le chiffre suivant est le contenu de la méthode HTTPPOST ci-dessus.
fonction httppost (str, url, chemin) {// Envoyer JSON au serveur, STR est contenu JSON, URL est l'adresse de la page de message historique, le chemin est le chemin et le nom de fichier du programme de réception
console.log ("Démarrer le transfert");
essayer{
var http = require ('http');
var data = {
Str: EncodeuriComponent (Str),
URL: EncodeuriComponent (URL)
};
data = require ('queerystring'). stringify (data);
Var Options = {
Méthode: "Post",
Hôte: "xxx", // Notez qu'il n'y a pas de http: //, c'est le nom de domaine du serveur.
Port: xxx,
Chemin: Chemin, // le chemin et le nom de fichier du programme de réception
En-têtes: {
«Contenu-Type»: «Application / X-Www-Form-Urlencoced; charse = utf-8 ',
"Content-Length": data.length
}
};
var req = http.request (options, fonction (res) {
res.setEncoding ('utf8');
res.on ('data', fonction (chunk) {
Console.log ('Body:' + Chunk);
});
});
req.on ('error', fonction (e) {
console.log ('Problème avec demande:' + e.Message);
});
req.write (données);
req.end ();
} catch (e) {
console.log ("Message d'erreur:" + e);
}
Console.log ("Formeing Operation se termine");
}Après avoir fait le travail ci-dessus, l'étape suivante consiste à terminer le code du serveur en fonction de votre propre entreprise. Notre service est utilisé pour recevoir des données envoyées par le serveur proxy pour le traitement, effectuer des opérations persistantes et en même temps envoyer le code JS qui doit être injecté dans WeChat au serveur proxy. Pour les données envoyées à partir de plusieurs liens différents interceptés par le serveur proxy, nous devons concevoir des méthodes correspondantes pour traiter ces données. À partir de la méthode JS de AnyProxy pour traiter les données WeChat RemplaceServerResDataasync: Fonction (req, res, serverresdata, rappel), nous pouvons savoir qu'au moins trois méthodes sont nécessaires pour concevoir les données de la page historique du compte officiel, les données de la page d'article du compte officiel, l'article de compte officiel Likes and Lire Data. Dans le même temps, nous devons également concevoir une méthode pour générer des tâches rampantes et compléter le compte aller-retour du compte officiel. Si vous avez besoin de ramper plus de données, vous pouvez analyser plus de données nécessaires à partir des liens capturés par AnyProxy, puis ajouter un jugement pour remplacer le service de dataasync: fonction (req, res, serverresdata, rappeler), intercepter les données requises et les envoyer à votre propre serveur, et ajouter la méthode correspondante pour traiter ce type de données sur le serveur.
J'écris du code de serveur dans Java.
Méthodes pour traiter les données de la page de l'historique du compte officiel:
public void getmsgjson (string str, string URL) lève unportedEncodingException {// TODO Méthode générée automatique Stub String biz = ""; Map <string, string> queryStrs = httpurlparser.parseurl (url); if (queryStrs! = null) {biz = querystrs.get ("__ biz"); biz = biz + "=="; } / ** * Requête de la base de données, si Biz existe déjà, et insérez-le s'il n'existe pas. * Cela signifie que nous avons ajouté un nouveau compte officiel pour l'objectif de collecte. * / List <Weixin> Results = WeixinMapper.SelectByBiz (Biz); if (résultats == null || results.size () == 0) {weixin weixin = new Weixin (); weixin.setbiz (biz); weixin.setCollect (System.CurrentTimemillis ()); weixinmapper.insert (Weixin); } //System.out.println(str); // Parse Str Variable List <Bject> lists = jsonPath.read (str, "['list']"); pour (Liste d'objets: listes) {objet JSON = list; int type = jsonpath.read (json, "['Comm_msg_info'] ['type']"); if (type == 49) {// type = 49 signifie qu'il s'agit d'une chaîne de message texte contenu_url = jsonpath.read (json, "$ .app_msg_ext_info.content_url"); content_url = content_url.replace ("//", "") .replaceALL ("amp;", ""); // Obtenez l'adresse de lien du message texte int is_multi = jsonpath.read (json, "$ .app_msg_ext_info.is_multi"); / est it a-t-il un message multi-graphisé "$ .comm_msg_info.dateTime"); // Envoyez l'heure de l'image et du message texte / ** * Ici, l'adresse de liaison d'image et de message texte est insérée dans la bibliothèque de file d'attente d'acquisition TMPLIST * (La bibliothèque de file d'attente sera introduite plus tard. L'objectif principal est de l'établissement d'un lot de lot ! = null &&! "". equals (content_url)) {tmplist tmplist = new tmplist (); tmplist.setContenUrl (content_url); tmplistmapper.insertSelective (tmplist); }} catch (exception e) {System.out.println ("La file d'attente existe déjà, non insérée!"); } / ** * Ici, nous jugeons s'il est répété à partir de la publication de base de données basée sur $ contenu_url * / list <ost> postlist = postmapper.selectbycontenturl (content_url); booléen contenuSurlexist = false; if (postlist! = null && postlist.size ()! = 0) {ContitreLAxist = true; } if (! ContentUrlexist) {// 'Le même $ content_url existe dans la base de données post' Integer FileID = JSONPath.read (JSON, "$ .App_msg_ext_info.fileid"); // a wechat id title = JSONPATH.Read (json, "$ .App_msg_ext_info.Title"); title_encode = urlencoder.encode (title, "utf-8"); String digest = jsonpath.read (json, "$ .app_msg_ext_info.digest"); // Résumé de la chaîne Source_URL = JSONPATH.READ (JSON, "$ .App_msg_ext_info.source_url"); // "" ") String Cover = JSONPath.read (JSON, "$ .app_msg_ext_info.cover"); // couverture d'image couverte = cover.replace ("//", ""); /** * Save to the database*/// System.out.println("Title: "+title);// System.out.println("WeChat ID: "+fileid);// System.out.println("Article summary:"+digest);// System.out.println("Read original link:"+source_url);// System.out.println("Cover image Adresse: "+ couverture); Post Post = new Post (); post.setbiz (biz); post.settitle (titre); post.setTitleencode (title_encode); poster.setFieldId (fileId); post.setdigest (digest); post.SetSourceUrl (source_url); Post.setcover (couverture); post.Settistop (1); // le taguez-le comme le titre de contenu post.Setismulti (is_multi); post.setDateTime (DateTime); post.setContenTurl (content_url); Postmapper.insert (post); } if (is_multi == 1) {// s'il s'agit d'une liste de messages multi-graphiques <objet> multitilists = jsonpath.read (json, "['app_msg_ext_info'] ['multi_app_msg_item_list']"); pour (objet Multist: Multists) {objet Multijson = Multist; content_url = jsonpath.read (multijson, "['contenu_url']"). toString (). remplacer ("//", "") .replaceAll ("amp;", ""); // le lien de message graphique / ** * Ici, nous jugerons si la base de données est répétée sur la base de contenu_url pour éviter les erreurs * / ContentUxist = false; List <ost> poters = postmapper.selectByContenUrl (content_url); if (poteaux! = null && posts.size ()! = 0) {ContitreLUxist = true; } if (! ContentUrlexist) {// 'le même $ contenu_url n'est pas présent dans la base de données' / ** * ici, insérer l'adresse graphique et le lien de message texte dans la bibliothèque de file d'attente d'acquisition * (La bibliothèque de file d'attente sera introduite plus tard. Le but principal est d'établir une file d'attente par lots de mise en file &&! "". equals (content_url)) {tmplist tmplistt = new tmplist (); tmplistt.setContenUrl (contenu_url); tmplistmapper.insertSelective (tmplistt); } String title = jsonpath.read (multijson, "$ .title"); String title_encode = urlencoder.encode (title, "utf-8"); Integer FileId = JSONPath.read (Multijson, "$ .FileId"); String digest = jsonpath.read (Multijson, "$ .digest"); String source_url = jsonpath.read (Multijson, "$ .source_url"); source_url = source_url.replace ("//", ""); String Cover = JSONPath.read (Multijson, "$ .cover"); Cover = Cover.replace ("//", ""); // System.out.println ("Title:" + Title); // System.out.println ("WECHAT ID:" + FileId); // System.out.println ("Résumé de l'article:" + Digest); // System.out.println ("" Lien d'origine: "+ Source_Url); // System.out.println (" Couverture d'image Address: "+ couvercle); Post Post = new Post (); post.setbiz (biz); post.settitle (titre); post.setTitleencode (title_encode); poster.setFieldId (fileId); post.setdigest (digest); post.SetSourceUrl (source_url); Post.setcover (couverture); post.Settistop (0); // Tag Ce n'est pas le contenu de la tête post.Setismulti (is_multi); post.setDateTime (DateTime); post.setContenTurl (content_url); Postmapper.insert (post); }}}}}}}}}Comment gérer les pages d'article officiel du compte:
Public String getWxPost () {// TODO Méthode générée automatique Stub / ** * Lorsque la page actuelle est la page de l'article officiel du compte, lisez ce programme * Supprimez d'abord la ligne de ligne = 1 dans la liste de files d'attente de la collection * puis sélectionnez plusieurs lignes en fonction de "Order by Asc" de la liste de file d'attente (notez que cette ligne est différente du programme ci-dessus) * / tmpLeledMapper.DeleteByLoad (1); List <tmplist> files d'attente = tmplistmapper.selectMany (5); String url = ""; if (files d'attente! = null && files d'attente.size ()! = 0 && queues.size ()> 1) {tmplist queue = quelles.get (0); url = queue.getContenUrl (); queue.setSoLot (1); Int result = tmplistMapper.UpDateByPrimaryKey (file d'attente); System.out.println ("Résultat de mise à jour:" + résultat); } else {System.out.println ("GetPost files d'attente est null?" + files d'attente == null? null: files.size ()); Weixin weixin = weixinmapper.selectone (); String biz = weixin.getBiz (); if ((math.random ()> 0,5? 1: 0) == 1) {url = "http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=" + biz + "# wechat_webview_type = 1 & wechat_redirect"; // diviser l'admission url du message historique officiel (First Page Form). "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=" + biz + "#wechat_redirect"; // diviser l'adresse URL du message historique officiel (deuxième page)} url = "https://mp.weixin..com/mp/profile_ext? biz + "#wechat_redirect"; // diviser l'adresse URL du message historique du compte officiel (le deuxième formulaire de page) // Mettez à jour le champ de temps de collecte dans le tableau officiel du compte mentionné à l'heure à l'heure actuelle. weixin.setCollect (System.CurrentTimemillis ()); Int result = weixinmapper.updateByPrimaryKey (Weixin); System.out.println ("GetPost Weixin Updateresult:" + Result); } int randomtime = new random (). nextInt (3) + 3; String jscode = "<script> setTimeout (function () {window.location.href = '" + url + "';}," + randomtime * 1000 + "); </ script>"; return jscode; }Comment gérer le nombre de goûts et de lectures des comptes officiels:
public void getmsgext (string str, string url) {// TODO Méthode générée automatique Stub string biz = ""; String sn = ""; Map <string, string> queryStrs = httpurlparser.parseurl (url); if (queryStrs! = null) {biz = querystrs.get ("__ biz"); biz = biz + "=="; sn = queyrystrs.get ("sn"); sn = "%" + sn + "%"; } / ** * $ sql = "SELECT * From 'Article Table` où` biz` =' ". $ biz." '* et `content_url` like'%". $ sn. "% '" limite 0,1; * Trouvez l'article correspondant basé sur Biz et Sn * / Post Post = PostMapper.SelectByBizandsn (Biz, Sn); if (post == null) {System.out.println ("biz:" + biz); System.out.println ("Sn:" + Sn); tmplistMapper.DeleteByload (1); retour; } // System.out.println ("Data JSON:" + Str); Integer read_num; Entier like_num; try {read_num = jsonpath.read (str, "['appmsgstat'] ['read_num']"); // read volume like_num = jsonpath.read (str, "['appmSgStat'] ['like_num']"); // like volume} catch (exception e) {read_num = 123; // like volume like_num = 321; System.out.println ("read_num:" + read_num); System.out.println ("like_num:" + like_num); System.out.println (e.getMessage ()); } / ** * Ici, l'article correspondant est également supprimé dans la liste des files d'attente de collection basés sur SN, ce qui signifie que cet article peut être supprimé de la file d'attente de collection. * $ sql = "Supprimer de 'Team List` où` `Content_url` like'%". $ sn. "% '" * / tmplistmapper.deleteBysn (sn); // Mettez ensuite à jour le nombre de vues et de likes vers le tableau des articles. post.setReadnum (read_num); post.setlikenum (like_num); Postmapper.UpdateByPrimaryKey (Post); }Comment gérer le saut vers WeChat Injection JS:
public String getwxhis () {String url = ""; // TODO Méthode générée automatiquement Stume / ** * Lorsque la page actuelle est un message historique de compte public, lisez ce programme * Il y a un champ de chargement dans la liste des files d'attente de collection. Lorsque la valeur est égale à 1, cela signifie qu'il est lu * Supprimer d'abord la ligne de ligne = 1 dans la liste des files d'attente de collection * puis sélectionnez n'importe quelle ligne dans la liste d'équipe * / tmplistmapper.deleteByLoad (1); TMPLIST Queue = tmplistMapper.Selectrandomone (); System.out.println ("La file d'attente est null?" + File d'attente); if (queue == null) {// La liste des files d'attente est vide / ** * Si la liste des files d'attente est vide, obtenez un biz de la table en stockant le compte officiel du compte. * Ici, j'ai défini un champ de temps de l'heure de collecte dans la table de compte officielle. Après l'avoir trié dans un ordre positif, * obtenez l'enregistrement du compte officiel avec le plus petit horodatage et obtenez son biz * / weixin weixin = weixinmapper.selectone (); String biz = weixin.getBiz (); url = "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=" + biz + "#wechat_redirect"; // diviser l'adresse de message historique du compte officiel (le formulaire de deuxième page) // mette à jour le terrain de temps de collecte dans le tableau de compte officiel mentionné maintenant vers le temps de temps actuel. weixin.setCollect (System.CurrentTimemillis ()); Int result = weixinmapper.updateByPrimaryKey (Weixin); System.out.println ("Gethis Weixin Updateresult:" + Result); } else {// Obtenez le champ contenu_url de la ligne actuelle url = queue.getContenTUrl (); // Mettez à jour le champ de chargement vers 1 tmplistmapper.UpdateByContenUrl (URL); } // Modifiez l'url $ suivante à rediriger en un script JS et injectez-le dans la page WeChat par AnyProxy. // echo "<script> setTimeout (function () {window.location.href = '". $ url. "';}, 2000); </cript>"; int randomtime = new random (). NextInt (3) + 3; String jscode = "<script> setTimeout (function () {window.location.href = '" + url + "';}," + randomtime * 1000 + "); </ script>"; return jscode; }Ce qui précède est le programme qui traite les données interceptées par le serveur proxy. Il y a un problème qui doit être prêté attention ici. Le programme effectuera un accès à la ronde à chaque compte officiel inclus dans la base de données, et même les articles stockés seront à nouveau accessibles. Le but est de continuer à mettre à jour le nombre de vues et de goûts de l'article. Si vous avez besoin de ramper un grand nombre de comptes publics, il est recommandé de modifier le code pour ajouter des files d'attente de tâches et ajouter des restrictions conditionnelles. Sinon, le compte officiel rampera les données en double en plusieurs tours et les cycles affecteront grandement l'efficacité.
À ce stade, tous les liens de l'article du compte officiel de WeChat ont été rampants, et ce lien est valable en permanence et peut être ouvert dans le navigateur. Ensuite, rédigez un programme de chenilles pour explorer le contenu de l'article et d'autres informations de la base de données.
Je suis un robot écrit en webmagic, il est léger et facile à utiliser.
classe publique SpiderModel implémente PageProcessor {Private Static Postmapper PostMapper; Liste statique privée <ost> publications; // Configuration pertinente du site Web de rampe, y compris le codage, l'intervalle de crawl, les heures de réception, etc. Site privé Site = site.me (). SetRetryTimes (3) .SetSleEptime (100); Site public getSite () {// TODO Méthode générée automatique Stub Retour.Site; } Processus public void (page de page) {// TODO Méthode générée automatique Stub post Post = Posts.Remove (0); String content = page.gethtml (). Xpath ("// div [@ id = 'js_content']"). Get (); // Les articles Harry sont déterminés ici. S'il existe un enregistrement de suppression directe ou définissez le bit de représentation pour indiquer que l'article est harmonieux if (content == null) {System.out.println ("L'article est harmonieux!"); //PostMapper.DeleteByPrimaryKey (post.getId ()); retour; } String ContentsNap = Content.replaceAll ("Data-Src", "Src"). RemplaceALL ("préview.html", "player.html"); // Snapshot String Contenttxt = htmltoword.striphtml (Content); // Plain Text ContentsElectable Metacontent = page.gethtml (). xpath ("// div [@ id = 'meta_content']"); String pubtime = null; String wxName = null; String auteur = null; if (metacontent! = null) {pubtime = metacontent.xpath ("// em [@ id = 'post-date']"). get (); if (pubtime! = null) {pubtime = htmltoword.striphtml (pubtime); // time de publication d'article} wxname = metacontent.xpath ("// a [@ id = 'post-user']"). get (); if (wxname! = null) {wxName = htmltoword.striphtml (wxName); // Nom de compte public} auteur = metacontent.xpath ("// em [@ class = 'rich_media_meta rich_media_meta_text' et @id! = 'post-date']"). Get ();); if (auteur! = null) {auteur = htmltoword.striphtml (auteur); // Article auteur}} // System.out.println ("Publish Time:" + pubtime); // System.out.println ("Article Nom:" + Wxname); // System.out.println ("Article Auteur:" + auteur); Titre de la chaîne = poster.getTitle (). RempaceALL ("", ""); // Article Title String Digest = Post.getDigest (); // Résumé de l'article Int Likenum = Post.getLikEnum (); // Article aime int.getContunTuLnUm () New Wechatinfobean (); wechatbean.settitle (titre); wechatbean.setContent (contenutxt); // contenu de texte brut wechatbean.setsourCode (contenuNap); // snapshot wechatbean.setlikeCount (likenum); wechatbean.setViewCount (readnum); wechatbean.setabstractText (digest); // abstrait wechatbean.setUrl (ContinentUrl); wechatbean.setpublishtime (pubtime); wechatbean.setsItename (wxName); // nom du site nom de compte public wechatbean.setauthor (auteur); wechatbean.setmediaType ("compte officiel de WeChat"); // type de média source WeChatStorage.Savewechatinfo (WeChatbean); // TAGE L'article a été rampé par post.Settisspider (1); Postmapper.UpdateByPrimaryKey (Post); } public static void startSpider (list <ost> inposts, postmapper myposostmapper, string ... urls) {long startTime, endtime; startTime = System.CurrentTimemillis (); PostMapper = mypostmapper; Posts = inposts; HttpClientDownloader httpClientDownloader = new httpclientDownloader (); SpiderModel SpiderModel = nouveau SpiderModel (); Spider myspider = spider.create (spidermodel) .addurl (URL); myspider.setDownloader (httpclientDowner); essayez {spiderMonitor.instance (). Register (myspider); myspider.thread (1) .run (); } catch (jMException e) {e.printStackTrace (); } endtime = system.currentTimemillis (); System.out.println ("Crawl Time" + ((Fintime - StartTime) / 1000) + "Seconds--"); }}Je ne publierai pas d'autres codes de stockage logique non pertinents. Ici, j'ai mis les données capturées par le serveur proxy dans MySQL et j'ai stocké les données rampées par mon programme Crawler dans MongoDB.
Vous trouverez ci-dessous les informations sur le numéro de compte officiel que vous avez rampé: