Prefacio: Antes de escribir este artículo, leo principalmente algunos estilos de escritura de rastreadores similares. Algunos de ellos usan colas para escribirlas, lo que no se siente muy intuitivo. Algunos solo tienen una solicitud y luego realizan análisis de página. No se levantan automáticamente en absoluto. ¿Esto también se llama Crawler? Por lo tanto, escribí sobre un simple rastreador basado en mis propias ideas.
Introducción de un algoritmo
El programa utiliza un algoritmo de amplio primer en su idea, inicia las solicitudes de enlaces no controlados uno tras otro, y luego analiza la página devuelta con expresiones regulares, saca el nuevo enlace que no se ha descubierto, lo agrega a la colección y la atraviesa en el siguiente bucle.
La implementación específica utiliza MAP <String, Boolean> y los pares de valor clave son el enlace y si se atraviesa. Se utilizan dos colecciones de mapas en el programa, a saber: Oldmap y Newmap. El enlace inicial está en Oldmap, y luego se realiza una solicitud para un enlace con el indicador falso en Oldmap, analiza la página y use regularmente para eliminar el enlace en la etiqueta <a>. Si este enlace no está en Oldmap y Newmap, significa que este es un nuevo enlace. Al mismo tiempo, si este enlace es el enlace del sitio web de destino que necesitamos obtener, pondremos este enlace en NewMap y continuaremos analizándolo. Cuando la página se analiza, el valor del enlace en la página actual en OldMap se establece en True, lo que significa que ha sido atravesado.
Finalmente, cuando el enlace completo que no ha sido atravesado por Oldmap ha sido atravesado, si encuentra que el Newmap no está vacío, significa que se han generado nuevos enlaces en este bucle. Por lo tanto, estos nuevos enlaces se agregan a Oldmap y continúan atravesando recursivamente. De lo contrario, significa que no se han generado nuevos enlaces en este bucle. Si continúa en bucle, ya no puede generar nuevos enlaces. Debido a que la tarea ha terminado, se devolverá la colección de enlaces Oldmap.
Dos implementación del programa
Las ideas relacionadas anteriormente se han explicado muy claramente, y hay comentarios en las áreas clave del código, por lo que no hablaré de eso aquí, el código es el siguiente:
Acción del paquete; import java.io.bufferedReader; import java.io.ioexception; import java.io.inputstream; import java.io.inputstreamreader; import java.net.httpurlConnection; import java.net.malformedurlexception; import java.net.net.url; import java.util.linkedhashmap; java.util.map; import java.util.regex.matcher; import java.util.regex.pattern; public class Webcrawlerdemo {public static void main (string [] args) {webcrawlerdemo webcrawlerDemo = newcrawlerDemo (); webcrawlerdemo.myprint ("http://www.zifangsky.cn"); } public void myprint (String baseUrl) {map <string, boolean> oldmap = new LinkedHashMap <String, Boolean> (); // Link de almacenamiento: si está atravesado // Cadena de par de valores de clave OldLinkHost = ""; // Patrón de host P = Pattern.compile ("(https?: //)? [^/// s]*"); // Por ejemplo: http://www.zifangsky.cn matcher m = p.matcher (baseurl); if (m.find ()) {OldLinkHost = M.Group (); } Oldmap.put (baseUrl, falso); Oldmap = Crawllinks (OldLinkhost, Oldmap); para (map.Entry <String, Boolean> Mapping: Oldmap.Entryset ()) {System.out.println ("Link:" + Mapping.getKey ()); }} /*** rastree todos los enlaces de la página web que se pueden rastrear en un sitio web y utilizar el algoritmo de prioridad en la idea. Las solicitudes GET se inician constantemente para nuevos enlaces que no se han atravesado hasta que se atraviese el conjunto completo. Esto significa que no se pueden encontrar nuevos enlaces, y la tarea termina * * @param OldLinkhost Nombre de dominio, como: http://www.zifangsky.cn * @param Oldmap Collection of Links para ser atravesado * * @Return return todas las colecciones de enlaces Crawled * */private Map <String, boolean> crawllinks (String OldLinkHostHostHost, @ReturN {Map <string, boolean> newMap = new LinkedHashMap <String, boolean> (); Cadena OldLink = ""; para (map.entry <string, boolean> mapping: oldmap.entryset ()) {system.out.println ("link:" + mapping.getkey () + "--------- check:" + mapping.getValue ()); // Si no ha sido atravesado por (! Mapping.getValue ()) {oldLink = mapping.getKey (); // iniciar una solicitud GET prueba {url url = nueva url (OldLink); Httpurlconnection Connection = (httpurlconnection) url .openconnection (); Connect.SetRequestMethod ("Get"); Connection.SetConnectTimeOut (2000); Connection.SetReadtimeOut (2000); if (conexión.getResponseCode () == 200) {inputStream inputStream = Connection.getInputStream (); BufferedReader Reader = new BufferedReader (new InputStreamReader (inputStream, "UTF-8")); Línea de cadena = ""; Pattern Pattern = Pattern .Compile ("<a.*? Href = [/" ']? (((Https?: //)?/? [^/"']+) [/" ']?.*?> (.+) </a> "); matcher matcher = null; while (line = lerer.readline ()) {String newLink = Matcher.group (1) .trim (); OldLinkHost + "/" + NewLink; newlink.startswith (OldLinkHost)) {// System.out.println ("Temp2:" + NewLink); Thread.sleep (1000); } catch (InterruptedException e) {E.PrintStackTrace (); } Oldmap.replace (Oldlink, falso, verdadero); }} // Hay un nuevo enlace, continúa atravesando if (! Newmap.isEmpty ()) {Oldmap.putall (newMap); Oldmap.putall (Crawllinks (OldLinkhost, Oldmap)); // Debido a las características del mapa, no habrá pares de valor clave duplicados} return Oldmap; }}Tres resultados finales de las pruebas
PD: De hecho, usar la recursión no es muy bueno, porque si el sitio web tiene más páginas, el consumo de memoria será muy grande si el programa se ejecuta durante mucho tiempo.
Gracias por leer, espero que pueda ayudarte. ¡Gracias por su apoyo para este sitio!