Eine Anleitung zu Crawler4j

1. Einleitung

Wir sehen Webcrawler jedes Mal im Einsatz, wenn wir unsere bevorzugte Suchmaschine verwenden. Sie werden auch häufig verwendet, um Daten von Websites zu kratzen und zu analysieren.

In diesem Tutorial erfahren Sie, wie Sie mit crawler4j eigene Webcrawler einrichten und ausführen. crawler4j ist ein Open Source Java-Projekt, mit dem wir dies einfach tun können.

2. Setup

Verwenden wir Maven Central, um die neueste Version zu finden und die Maven-Abhängigkeit einzufügen:

 edu.uci.ics crawler4j 4.4.0 

3. Crawler erstellen

3.1. Einfacher HTML-Crawler

Wir beginnen mit der Erstellung eines einfachen Crawlers, der die HTML-Seiten auf //baeldung.com crawlt .

Erstellen wir unseren Crawler, indem wir WebCrawler in unserer Crawler-Klasse erweitern und ein Muster definieren, um bestimmte Dateitypen auszuschließen:

public class HtmlCrawler extends WebCrawler js

In jeder Crawler-Klasse müssen zwei Methoden überschrieben und implementiert werden: shouldVisit und visit .

Lassen Sie uns jetzt unsere shouldVisit- Methode mit dem von uns erstellten EXCLUSIONS- Muster erstellen :

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

Dann können wir unsere Verarbeitung für besuchte Seiten in der Besuchsmethode durchführen :

@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 } }

Sobald wir unseren Crawler geschrieben haben, müssen wir ihn konfigurieren und ausführen:

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("//www.baeldung.com/"); CrawlController.WebCrawlerFactory factory = HtmlCrawler::new; controller.start(factory, numCrawlers);

Wir haben ein temporäres Speicherverzeichnis konfiguriert, die Anzahl der Crawling-Threads angegeben und den Crawler mit einer Start-URL versehen.

Wir sollten auch beachten, dass die CrawlController.start () -Methode eine blockierende Operation ist . Jeder Code nach diesem Aufruf wird erst ausgeführt, nachdem der Crawler ausgeführt wurde.

3.2. ImageCrawler

Standardmäßig crawlt crawler4j keine Binärdaten. In diesem nächsten Beispiel aktivieren wir diese Funktionalität und crawlen alle JPEGs in Baeldung.

Beginnen wir mit der Definition der ImageCrawler- Klasse mit einem Konstruktor, der ein Verzeichnis zum Speichern von Bildern verwendet:

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 }

Als nächstes implementieren wir die shouldVisit- Methode:

@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("//www.baeldung.com/")) { return true; } return false; }

Jetzt sind wir bereit , die zur Umsetzung Besuch Methode:

@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 } }

Das Ausführen unseres ImageCrawler ähnelt dem Ausführen des HttpCrawler , muss jedoch so konfiguriert werden, dass er binären Inhalt enthält:

CrawlConfig config = new CrawlConfig(); config.setIncludeBinaryContentInCrawling(true); // ... same as before CrawlController.WebCrawlerFactory factory = () -> new ImageCrawler(saveDir); controller.start(factory, numCrawlers);

3.3. Daten sammeln

Nachdem wir uns einige grundlegende Beispiele angesehen haben, erweitern wir unseren HtmlCrawler , um während des Crawls einige grundlegende Statistiken zu sammeln.

Definieren wir zunächst eine einfache Klasse für einige Statistiken:

public class CrawlerStatistics { private int processedPageCount = 0; private int totalLinksCount = 0; public void incrementProcessedPageCount() { processedPageCount++; } public void incrementTotalLinksCount(int linksCount) { totalLinksCount += linksCount; } // standard getters }

Als nächstes ändern wir unseren HtmlCrawler so , dass eine CrawlerStatistics- Instanz über einen Konstruktor akzeptiert wird :

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

Mit unserem neuen CrawlerStatistics Objekt, lassen Sie sich das ändert Besuch Methode zu sammeln , was wir wollen:

@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 } }

Kehren wir nun zu unserem Controller zurück und stellen dem HtmlCrawler eine Instanz von CrawlerStatistics zur Verfügung :

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

3.4. Mehrere Crawler

Aufbauend auf unseren vorherigen Beispielen schauen wir uns nun an, wie wir mehrere Crawler auf demselben Controller ausführen können .

Es wird empfohlen, dass jeder Crawler sein eigenes temporäres Speicherverzeichnis verwendet. Daher müssen wir für jedes von uns ausgeführte separate Konfigurationen erstellen.

Die CrawlController können einen einzelnen RobotstxtServer gemeinsam nutzen , ansonsten benötigen wir grundsätzlich eine Kopie von allem.

Bisher haben wir die CrawlController.start- Methode verwendet, um unsere Crawler auszuführen, und festgestellt, dass es sich um eine Blockierungsmethode handelt. Um mehrere auszuführen, verwenden wir CrawlerControlller.startNonBlocking in Verbindung mit CrawlController.waitUntilFinish .

Erstellen wir nun einen Controller, um HtmlCrawler und ImageCrawler gleichzeitig auszuführen :

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. Konfiguration

We've already seen some of what we can configure. Now, let's go over some other common settings.

Settings are applied to the CrawlConfig instance we specify in our controller.

4.1. Limiting Crawl Depth

By default, our crawlers will crawl as deep as they can. To limit how deep they'll go, we can set the crawl depth:

crawlConfig.setMaxDepthOfCrawling(2);

Seed URLs are considered to be at depth 0, so a crawl depth of 2 will go two layers beyond the seed URL.

4.2. Maximum Pages to Fetch

Another way to limit how many pages our crawlers will cover is to set the maximum number of pages to crawl:

crawlConfig.setMaxPagesToFetch(500);

4.3. Maximum Outgoing Links

We can also limit the number of outgoing links followed off each page:

crawlConfig.setMaxOutgoingLinksToFollow(2000);

4.4. Politeness Delay

Since very efficient crawlers can easily be a strain on web servers, crawler4j has what it calls a politeness delay. By default, it's set to 200 milliseconds. We can adjust this value if we need to:

crawlConfig.setPolitenessDelay(300);

4.5. Include Binary Content

We already used the option for including binary content with our ImageCrawler:

crawlConfig.setIncludeBinaryContentInCrawling(true);

4.6. Include HTTPS

By default, crawlers will include HTTPS pages, but we can turn that off:

crawlConfig.setIncludeHttpsPages(false);

4.7. Resumable Crawling

If we have a long-running crawler and we want it to resume automatically, we can set resumable crawling. Turning it on may cause it to run slower:

crawlConfig.setResumableCrawling(true);

4.8. User-Agent String

The default user-agent string for crawler4j is crawler4j. Let's customize that:

crawlConfig.setUserAgentString("baeldung demo (//github.com/yasserg/crawler4j/)");

Wir haben hier nur einige der Grundkonfigurationen behandelt. Wir können uns die CrawConfig- Klasse ansehen , wenn wir an einigen der erweiterten oder undurchsichtigen Konfigurationsoptionen interessiert sind.

5. Schlussfolgerung

In diesem Artikel haben wir crawler4j verwendet, um unsere eigenen Webcrawler zu erstellen. Wir haben mit zwei einfachen Beispielen für das Crawlen von HTML und Bildern begonnen. Anschließend haben wir auf diesen Beispielen aufgebaut, um zu sehen, wie wir Statistiken erfassen und mehrere Crawler gleichzeitig ausführen können.

Die vollständigen Codebeispiele finden Sie auf GitHub.