Prefácio: Antes de escrever este artigo, li principalmente alguns estilos de escrita de rastreador semelhantes. Alguns deles usam filas para escrevê -las, o que não parece muito intuitivo. Alguns têm apenas uma solicitação e, em seguida, executam a análise da página. Eles não se levantam automaticamente. Isso também é chamado de Crawler? Portanto, escrevi sobre um rastreador simples com base em minhas próprias idéias.
Uma introdução de algoritmo
O programa usa um algoritmo de largura em sua idéia, os iniciados recebem pedidos de links intimidados um após o outro e, em seguida, analisa a página devolvida com expressões regulares, retira o novo link que não foi descoberto, adiciona-o à coleção e o atravessa no próximo loop.
A implementação específica usa o mapa <string, boolean> e os pares de valor-chave são o link e se devem ser atravessados. Duas coleções de mapas são usadas no programa, a saber: Oldmap e Newmap. O link inicial está no Oldmap e, em seguida, é feita uma solicitação para um link com o sinalizador false no Oldmap, analisar a página e usar regularmente para remover o link na tag <a>. Se este link não estiver no Oldmap e no Newmap, significa que este é um novo link. Ao mesmo tempo, se este link for o link do site de destino que precisamos obter, colocaremos esse link no Newmap e continuaremos a analisá -lo. Quando a página é analisada, o valor do link na página atual no OldMap é definido como true, o que significa que ele foi atravessado.
Finalmente, quando todo o link que não foi atravessado pelo antigo mapa foi atravessado, se você achar que o novo mapa não está vazio, isso significa que novos links foram gerados nesse loop. Portanto, esses novos links são adicionados ao antigo e continuam a atravessar recursivamente. Caso contrário, isso significa que nenhum novo link foi gerado nesse loop. Se você continuar a fazer loop, não poderá mais gerar novos links. Como a tarefa terminou, o Oldmap da coleção de links será retornado.
Duas implementação do programa
As idéias relacionadas acima foram explicadas com muita clareza e há comentários nas principais áreas do código, então não vou falar sobre isso aqui, o código é o seguinte:
Ação do pacote de pacote Java.io.BufferedReader; importar java.io.ioException; importar java.io.inputStream; importar java.io.inputStreamReader; import java.net.httpurlconnection; imporn.Net.Net.MalformException; importação java.netlConnection; java.util.map; importar java.util.regex.matcher; importar java.util.regex.pattern; public class webcrawlerdemo {public static void main (string [] args) {webcrawlerDemo webcrawlerDemo = novo webcrawlerDemo (); webcrawlerdemo.myprint ("http://www.zifangsky.cn"); } public void myprint (string baseurl) {map <string, boolean> Oldmap = new LinkedHashmap <string, boolean> (); // Link de armazenamento---é atravessado // pare de chave String string oldlinkhost = ""; // Padrão do host P = Pattern.compile ("(https?: //)? [^/// s]*"); // por exemplo: http://www.zifangsky.cn Matcher M = P.Matcher (Baseurl); if (m.find ()) {OldLinkHost = m.Group (); } oldmap.put (baseurl, false); Oldmap = Crawllinks (OldLinkhost, Oldmap); para (map.entry <string, boolean> mapeamento: oldmap.entryset ()) {System.out.println ("link:" + mapping.getKey ()); }} /*** Rastreie todos os links da página da web que podem ser rastejados em um site e use o algoritmo de amplitude da prioridade na idéia. As solicitações GET são constantemente iniciadas para novos links que não foram atravessados até que o conjunto completo seja percorrido. 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 = ""; para (map.entry <string, boolean> mapeamento: oldmap.entryset ()) {System.out.println ("link:" + mapping.getKey () + "--------- Verifique:" + maping.getValue ()); // se não tiver sido atravessado por (! // inicia uma solicitação de get tente {url url = new url (OldLink); Conexão httpurlConnection = (httpurlConnection) url .openconnection (); Connection.SetRequestMethod ("Get"); Connection.setConnectTimeout (2000); Connection.SetReadTimeout (2000); if (Connection.GetRESPONSecode () == 200) {inputStream inputStream = conexão.getInputStream (); BUBLEREDREADER LEITOR = NEW BUBLESEDRADER (new InputStreamReader (InputStream, "UTF-8")); String line = ""; Padrão padrão = padrão .compile ("<a.*? Href = [/" ']? ((Https?: //)?/? [^/"']+) [/" ']?.*?> (.+) </a> "); matcher matcher = null; while = = leitor.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, false, verdadeiro); }} // Há um novo link, continue a atravessar se (! Newmap.isempty ()) {Oldmap.putall (newmap); Oldmap.putall (Crawllinks (OldLinkhost, Oldmap)); // Devido às características do mapa, não haverá pares de valor-chave duplicado} retornar o Oldmap; }}Três resultados de teste final
PS: De fato, o uso da recursão não é muito bom, porque se o site tiver mais páginas, o consumo de memória será muito grande se o programa for durar muito tempo.
Obrigado pela leitura, espero que isso possa ajudá -lo. Obrigado pelo seu apoio a este site!