Préface: Avant d'écrire cet article, je lis principalement quelques styles d'écriture similaires. Certains d'entre eux utilisent des files d'attente pour les écrire, ce qui ne semble pas très intuitif. Certains n'ont qu'une seule demande, puis effectuent une analyse des pages. Ils ne se lèvent pas du tout automatiquement. C'est aussi ce qu'on appelle Crawler? Par conséquent, j'ai écrit sur un simple robot basé sur mes propres idées.
Une introduction algorithme
Le programme utilise un algorithme d'étendue-première dans son idée, initié les demandes de liens non torrides les uns après les autres, puis analyse la page retournée avec des expressions régulières, éliminent le nouveau lien qui n'a pas été découvert, l'ajoute à la collection et le traverse dans la prochaine boucle.
L'implémentation spécifique utilise MAP <String, Boolean>, et les paires de valeurs clés sont le lien et s'il faut être traversé. Deux collections de cartes sont utilisées dans le programme, à savoir: OldMap et Newmap. Le lien initial est dans OldMap, puis une demande est faite pour un lien avec le drapeau False dans OldMap, analyser la page et utiliser régulièrement pour supprimer le lien sous la balise <a>. Si ce lien n'est pas dans OldMap et Newmap, cela signifie qu'il s'agit d'un nouveau lien. Dans le même temps, si ce lien est le lien du site Web Target que nous devons obtenir, nous mettrons ce lien dans Newmap et continuerons à l'analyser. Lorsque la page est analysée, la valeur du lien sur la page actuelle dans OldMap est définie sur true, ce qui signifie qu'il a été traversé.
Enfin, lorsque le lien entier qui n'a pas été traversé par l'ancien a été traversé, si vous constatez que le newmap n'est pas vide, cela signifie que de nouveaux liens ont été générés dans cette boucle. Par conséquent, ces nouveaux liens sont ajoutés à l'ancien et continuent de traverser récursivement. Sinon, cela signifie qu'aucun nouveau lien n'a été généré dans cette boucle. Si vous continuez à boucler, vous ne pouvez plus générer de nouveaux liens. Parce que la tâche est terminée, la collection de liens OldMap sera retournée.
Deux implémentation du programme
Les idées liées ci-dessus ont été expliquées très clairement, et il y a des commentaires dans les domaines clés du code, donc je n'en parlerai pas ici, le code est le suivant:
Action du package; import java.io.bufferedReader; import java.io.ioexception; import java.io.inputStream; import java.io.inputstreamreader; import java.net.httpurlconnection; import java.net.malformedUrlexception; importer java.net.url; importation java.util.linkedhashmap; import; java.util.map; importer java.util.regex.matcher; import java.util.regex.pattern; classe publique webcrawlerdemo {public static void main (string [] args) {webcrawlerdemo webcrawlerdemo = new webcrawlerdemo (); webcrawlerdemo.myprint ("http://www.zifangsky.cn"); } public void myprint (String bunding) {map <string, boolean> oldmap = new LinkedHashMap <String, boolean> (); // lien de stockage - si il est traversé // la paire de valeurs de clé String OldLinkHost = ""; // Host Pattern p = motive.compile ("(https?: //)? [^ /// s] *"); // par exemple: http://www.zifangsky.cn Matcher M = P.Matcher (BUSURL); if (m.find ()) {oldLinkHost = M.Group (); } oldmap.put (substandul, false); OldMap = CrawLlinks (OldLinkHost, OldMap); for (map.entry <string, booléan> mapping: oldmap.entryset ()) {System.out.println ("link:" + mapping.getKey ()); }} / ** * Crawer tous les liens de la page Web qui peuvent être rampés sur un site Web et utilisez l'algorithme de priorité d'étendue dans l'idée. Les demandes de GET sont constamment lancées pour de nouveaux liens qui n'ont pas été traversés jusqu'à ce que l'ensemble complet soit traversé. This means that new links cannot be found, and the task ends * * @param oldLinkHost Domain name, such as: http://www.zifangsky.cn * @param oldMap Collection of links to be traversed* * @return Return all crawled link collections* */ private Map<String, Boolean> crawlLinks(String oldLinkHost, Map<String, Boolean> oldMap) { Map <string, boolean> newmap = new LinkedHashmap <String, boolean> (); String oldLink = ""; for (map.entry <string, booléan> mapping: oldmap.entryset ()) {System.out.println ("lien:" + mapping.getKey () + "--------- Vérifier:" + mapping.getValue ()); // s'il n'a pas été traversé par (! Mapping.getValue ()) {oldLink = mapping.getKey (); // initier une demande de get try {url url = new URL (oldLink); HttpurlConnection Connection = (httpurlConnection) url .OpenConnection (); connection.setRequestMethod ("get"); connection.setConnectTimeout (2000); connection.setReadTimeout (2000); if (connection.getResponSEcode () == 200) {inputStream inputStream = connection.getInputStream (); BufferedReader Reader = new BufferedReader (new InputStreamReader (InputStream, "UTF-8")); Chaîne line = ""; Pattern Match = Pattern .Compile ("<a. *? Href = [/" ']? ((Https?: //)? /? [^ / "'] +) [/" ']?. *?> (. +) </a> "); Matcher Matcher = Null; (Matcher.Find ()) {String newlink = Matcher.Group (1) .trim (); newLink; else newlink = oldlinkhost + "/" + newlink;} // retire / à la fin du lien if (newLink.endswith ("/")) ! newmap.containskey (newlink) && newlink.startswith (oldlinkhost)) {// system.out.println ("temp2:" + newlink); newmap.put (newLink, false); e.printStackTrace ();} essayez {Thread.Sleep (1000); } catch (InterruptedException e) {e.printStackTrace (); } oldmap.replace (oldlink, false, true); }} // Il y a un nouveau lien, continuez à traverser if (! Newmap.isempty ()) {oldmap.putall (newmap); oldmap.putall (crawllinks (oldlinkhost, oldmap)); // En raison des caractéristiques de la carte, il n'y aura pas de paires de valeurs clés en double} return oldmap; }}Trois résultats des tests finaux
PS: En fait, l'utilisation de la récursivité n'est pas très bonne, car si le site Web a plus de pages, la consommation de mémoire sera très importante si le programme fonctionne pendant longtemps.
Merci d'avoir lu, j'espère que cela peut vous aider. Merci pour votre soutien à ce site!