Um guia para o Crawler4j

Um guia para o Crawler4j

1. Introdução

Vemos rastreadores da Web em uso sempre que usamos nosso mecanismo de pesquisa favorito. Eles também são comumente usados ​​para raspar e analisar dados de sites.

Neste tutorial, aprenderemos como usarcrawler4j para configurar e executar nossos próprios rastreadores da web. crawler4j é um projeto Java de código aberto que nos permite fazer isso facilmente.

2. Configuração

Vamos usarMaven Central para encontrar a versão mais recente e trazer a dependência do Maven:


    edu.uci.ics
    crawler4j
    4.4.0

3. Criando rastreadores

3.1. Rastreador HTML simples

Vamos começar criando um rastreador básico que rastreia as páginas HTML emhttps://example.com.

Vamos criar nosso rastreador estendendoWebCrawler em nossa classe de rastreador e definindo um padrão para excluir certos tipos de arquivo:

public class HtmlCrawler extends WebCrawler {

    private final static Pattern EXCLUSIONS
      = Pattern.compile(".*(\\.(css|js|xml|gif|jpg|png|mp3|mp4|zip|gz|pdf))$");

    // more code
}

Em cada classe de rastreador,we must override and implement two methods: shouldVisit and visit.

Vamos criar nosso métodoshouldVisit agora usando o padrãoEXCLUSIONS que criamos:

@Override
public boolean shouldVisit(Page referringPage, WebURL url) {
    String urlString = url.getURL().toLowerCase();
    return !EXCLUSIONS.matcher(urlString).matches()
      && urlString.startsWith("https://www.example.com/");
}

Então, podemos fazer nosso processamento para as páginas visitadas no métodovisit:

@Override
public void visit(Page page) {
    String url = page.getWebURL().getURL();

    if (page.getParseData() instanceof HtmlParseData) {
        HtmlParseData htmlParseData = (HtmlParseData) page.getParseData();
        String title = htmlParseData.getTitle();
        String text = htmlParseData.getText();
        String html = htmlParseData.getHtml();
        Set links = htmlParseData.getOutgoingUrls();

        // do something with the collected data
    }
}

Depois de escrever nosso rastreador, precisamos configurá-lo e executá-lo:

File crawlStorage = new File("src/test/resources/crawler4j");
CrawlConfig config = new CrawlConfig();
config.setCrawlStorageFolder(crawlStorage.getAbsolutePath());

int numCrawlers = 12;

PageFetcher pageFetcher = new PageFetcher(config);
RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
RobotstxtServer robotstxtServer= new RobotstxtServer(robotstxtConfig, pageFetcher);
CrawlController controller = new CrawlController(config, pageFetcher, robotstxtServer);

controller.addSeed("https://www.example.com/");

CrawlController.WebCrawlerFactory factory = HtmlCrawler::new;

controller.start(factory, numCrawlers);

Configuramos um diretório de armazenamento temporário, especificamos o número de threads de rastreamento e propusemos ao rastreador um URL inicial.

Devemos também observar quethe CrawlController.start() method is a blocking operation. Qualquer código após essa chamada será executado somente depois que o rastreador terminar a execução.

3.2. ImageCrawler

Por padrão, crawler4j não rastreia dados binários. Neste próximo exemplo, vamos ativar essa funcionalidade ecrawl all the JPEGs on example.

Vamos começar definindo a classeImageCrawler com um construtor que leva um diretório para salvar imagens:

public class ImageCrawler extends WebCrawler {
    private final static Pattern EXCLUSIONS
      = Pattern.compile(".*(\\.(css|js|xml|gif|png|mp3|mp4|zip|gz|pdf))$");

    private static final Pattern IMG_PATTERNS = Pattern.compile(".*(\\.(jpg|jpeg))$");

    private File saveDir;

    public ImageCrawler(File saveDir) {
        this.saveDir = saveDir;
    }

    // more code

}

A seguir, vamos implementar o métodoshouldVisit:

@Override
public boolean shouldVisit(Page referringPage, WebURL url) {
    String urlString = url.getURL().toLowerCase();
    if (EXCLUSIONS.matcher(urlString).matches()) {
        return false;
    }

    if (IMG_PATTERNS.matcher(urlString).matches()
        || urlString.startsWith("https://www.example.com/")) {
        return true;
    }

    return false;
}

Agora, estamos prontos para implementar o métodovisit:

@Override
public void visit(Page page) {
    String url = page.getWebURL().getURL();
    if (IMG_PATTERNS.matcher(url).matches()
        && page.getParseData() instanceof BinaryParseData) {
        String extension = url.substring(url.lastIndexOf("."));
        int contentLength = page.getContentData().length;

        // write the content data to a file in the save directory
    }
}

Executar nossoImageCrawler é semelhante a executarHttpCrawler, mas precisamos configurá-lo para incluir conteúdo binário:

CrawlConfig config = new CrawlConfig();
config.setIncludeBinaryContentInCrawling(true);

// ... same as before

CrawlController.WebCrawlerFactory factory = () -> new ImageCrawler(saveDir);

controller.start(factory, numCrawlers);

3.3. Coletando dados

Agora que vimos alguns exemplos básicos, vamos expandir nossoHtmlCrawler para coletar algumas estatísticas básicas durante nosso rastreamento.

Primeiro, vamos definir uma classe simples para conter algumas estatísticas:

public class CrawlerStatistics {
    private int processedPageCount = 0;
    private int totalLinksCount = 0;

    public void incrementProcessedPageCount() {
        processedPageCount++;
    }

    public void incrementTotalLinksCount(int linksCount) {
        totalLinksCount += linksCount;
    }

    // standard getters
}

A seguir, vamos modificar nossoHtmlCrawler para aceitar uma instânciaCrawlerStatistics por meio de um construtor:

private CrawlerStatistics stats;

public HtmlCrawler(CrawlerStatistics stats) {
    this.stats = stats;
}

Com nosso novo objetoCrawlerStatistics, vamos modificar o métodovisit para coletar o que queremos:

@Override
public void visit(Page page) {
    String url = page.getWebURL().getURL();
    stats.incrementProcessedPageCount();

    if (page.getParseData() instanceof HtmlParseData) {
        HtmlParseData htmlParseData = (HtmlParseData) page.getParseData();
        String title = htmlParseData.getTitle();
        String text = htmlParseData.getText();
        String html = htmlParseData.getHtml();
        Set links = htmlParseData.getOutgoingUrls();
        stats.incrementTotalLinksCount(links.size());

        // do something with collected data
    }
}

Agora, vamos voltar ao nosso controlador e fornecer aoHtmlCrawler uma instância deCrawlerStatistics:

CrawlerStatistics stats = new CrawlerStatistics();
CrawlController.WebCrawlerFactory factory = () -> new HtmlCrawler(stats);

3.4. Vários rastreadores

Com base em nossos exemplos anteriores, vamos agora dar uma olhada em como podemosrun multiple crawlers from the same controller.

É recomendado queeach crawler use its own temporary storage directory, então precisamos criar configurações separadas para cada um que estaremos executando.

OCrawlControllers pode compartilhar um únicoRobotstxtServer, mas caso contrário, basicamente precisamos de uma cópia de tudo.

Até agora, usamos o métodoCrawlController.start para executar nossos rastreadores e observamos que é um método de bloqueio. To run multiples, we’ll use CrawlerControlller.startNonBlocking in conjunction with CrawlController.waitUntilFinish.

Agora, vamos criar um controlador para executarHtmlCrawlereImageCrawler simultaneamente:

File crawlStorageBase = new File("src/test/resources/crawler4j");
CrawlConfig htmlConfig = new CrawlConfig();
CrawlConfig imageConfig = new CrawlConfig();

// Configure storage folders and other configurations

PageFetcher pageFetcherHtml = new PageFetcher(htmlConfig);
PageFetcher pageFetcherImage = new PageFetcher(imageConfig);

RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcherHtml);

CrawlController htmlController
  = new CrawlController(htmlConfig, pageFetcherHtml, robotstxtServer);
CrawlController imageController
  = new CrawlController(imageConfig, pageFetcherImage, robotstxtServer);

// add seed URLs

CrawlerStatistics stats = new CrawlerStatistics();
CrawlController.WebCrawlerFactory htmlFactory = () -> new HtmlCrawler(stats);

File saveDir = new File("src/test/resources/crawler4j");
CrawlController.WebCrawlerFactory imageFactory
  = () -> new ImageCrawler(saveDir);

imageController.startNonBlocking(imageFactory, 7);
htmlController.startNonBlocking(htmlFactory, 10);

htmlController.waitUntilFinish();
imageController.waitUntilFinish();

4. Configuração

Já vimos algumas coisas que podemos configurar. Agora, vamos examinar algumas outras configurações comuns.

As configurações são aplicadas à instânciaCrawlConfig que especificamos em nosso controlador.

4.1. Limitando a profundidade do rastreamento

Por padrão, nossos rastreadores rastrearão o mais fundo possível. Para limitar a profundidade que eles irão, podemos definir a profundidade do rastreamento:

crawlConfig.setMaxDepthOfCrawling(2);

Os URLs de propagação são considerados com profundidade 0, portanto, uma profundidade de rastreamento de 2 irá duas camadas além do URL de propagação.

4.2. Máximo de páginas a serem buscadas

Outra maneira de limitar quantas páginas nossos rastreadores cobrirão é definir o número máximo de páginas a serem rastreadas:

crawlConfig.setMaxPagesToFetch(500);

Também podemos limitar o número de links de saída seguidos em cada página:

crawlConfig.setMaxOutgoingLinksToFollow(2000);

4.4. Atraso na educação

Como os rastreadores muito eficientes podem ser facilmente prejudiciais aos servidores da Web, o crawler4j tem o que chama de atraso de cortesia. Por padrão, é definido como 200 milissegundos. Podemos ajustar esse valor se precisarmos:

crawlConfig.setPolitenessDelay(300);

4.5. Incluir conteúdo binário

Já usamos a opção de incluir conteúdo binário com nossoImageCrawler:

crawlConfig.setIncludeBinaryContentInCrawling(true);

4.6. Incluir HTTPS

Por padrão, os rastreadores incluem páginas HTTPS, mas podemos desativar isso:

crawlConfig.setIncludeHttpsPages(false);

4.7. Rastreamento recuperável

Se tivermos um rastreador de longa execução e desejarmos que ele seja retomado automaticamente, podemos definir o rastreamento recuperável. Ligá-lo pode causar a lentidão:

crawlConfig.setResumableCrawling(true);

4.8. Cadeia de agente do usuário

A string do agente do usuário padrão para crawler4j écrawler4j. Vamos personalizar isso:

crawlConfig.setUserAgentString("example demo (https://github.com/yasserg/crawler4j/)");

Acabamos de cobrir algumas das configurações básicas aqui. Podemos olhar a classeCrawConfig se estivermos interessados ​​em algumas das opções de configuração mais avançadas ou obscuras.

5. Conclusão

Neste artigo, usamos crawler4j para criar nossos próprios rastreadores da web. Começamos com dois exemplos simples de rastreamento de HTML e imagens. Em seguida, criamos esses exemplos para ver como podemos coletar estatísticas e executar vários rastreadores simultaneamente.

Os exemplos de código completos estão disponíveisover on GitHub.