Een gids voor Crawler4j

1. Inleiding

Elke keer dat we onze favoriete zoekmachine gebruiken, zien we webcrawlers in gebruik. Ze worden ook vaak gebruikt om gegevens van websites te schrapen en te analyseren.

In deze zelfstudie leren we hoe we crawler4j kunnen gebruiken om onze eigen webcrawlers in te stellen en uit te voeren. crawler4j is een open source Java-project waarmee we dit eenvoudig kunnen doen.

2. Installatie

Laten we Maven Central gebruiken om de meest recente versie te vinden en de Maven-afhankelijkheid binnen te halen:

 edu.uci.ics crawler4j 4.4.0 

3. Crawlers maken

3.1. Eenvoudige HTML-crawler

We beginnen met het maken van een standaardcrawler die de HTML-pagina's crawlt //baeldung.com.

Laten we onze crawler maken door uit te breiden WebCrawler in onze crawlerklasse en een patroon definiëren om bepaalde bestandstypen uit te sluiten:

openbare klasse HtmlCrawler breidt WebCrawler js uit

In elke crawlerklasse we moeten twee methoden overschrijven en implementeren: zou moeten bezoeken en bezoek.

Laten we onze zou moeten bezoeken methode nu met behulp van de UITSLUITINGEN patroon dat we hebben gemaakt:

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

Vervolgens kunnen we onze verwerking uitvoeren voor bezochte pagina's in de bezoek methode:

@Override openbaar ongeldig bezoek (pagina pagina) {String url = page.getWebURL (). GetURL (); if (page.getParseData () instantie van HtmlParseData) {HtmlParseData htmlParseData = (HtmlParseData) page.getParseData (); String title = htmlParseData.getTitle (); String text = htmlParseData.getText (); String html = htmlParseData.getHtml (); Stel links = htmlParseData.getOutgoingUrls (); // doe iets met de verzamelde gegevens}}

Zodra we onze crawler hebben geschreven, moeten we deze configureren en uitvoeren:

Bestand crawlStorage = nieuw bestand ("src / test / resources / crawler4j"); CrawlConfig config = nieuwe CrawlConfig (); config.setCrawlStorageFolder (crawlStorage.getAbsolutePath ()); int aantalCrawlers = 12; PageFetcher pageFetcher = nieuwe PageFetcher (config); RobotstxtConfig robotstxtConfig = nieuwe RobotstxtConfig (); RobotstxtServer robotstxtServer = nieuwe RobotstxtServer (robotstxtConfig, pageFetcher); CrawlController controller = nieuwe CrawlController (config, pageFetcher, robotstxtServer); controller.addSeed ("// www.baeldung.com/"); CrawlController.WebCrawlerFactory factory = HtmlCrawler :: nieuw; controller.start (fabriek, aantalCrawlers);

We hebben een map voor tijdelijke opslag geconfigureerd, het aantal crawlthreads gespecificeerd en de crawler voorzien van een start-URL.

Dat moeten we ook opmerken de CrawlController.start () methode is een blokkerende operatie. Elke code na die aanroep wordt pas uitgevoerd nadat de crawler is voltooid.

3.2. ImageCrawler

Crawler4j crawlt standaard geen binaire gegevens. In dit volgende voorbeeld zetten we die functionaliteit aan en doorzoek alle JPEG's op Baeldung.

Laten we beginnen met het definiëren van de ImageCrawler class met een constructor die een map nodig heeft voor het opslaan van afbeeldingen:

public class ImageCrawler breidt WebCrawler uit {privé definitief statisch Pattern EXCLUSIONS = Pattern.compile (". * (\. (css | js | xml | gif | png | mp3 | mp4 | zip | gz | pdf)) $"); privé statisch laatste patroon IMG_PATTERNS = Pattern.compile (". * (\. (jpg | jpeg)) $"); privébestand saveDir; openbare ImageCrawler (Bestand saveDir) {this.saveDir = saveDir; } // meer code}

Laten we vervolgens het zou moeten bezoeken methode:

@Override openbare boolean shouldVisit (Pagina 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; }

Nu zijn we klaar om het bezoek methode:

@Override openbaar ongeldig bezoek (pagina pagina) {String url = page.getWebURL (). GetURL (); if (IMG_PATTERNS.matcher (url) .matches () && page.getParseData () instantie van BinaryParseData) {String extension = url.substring (url.lastIndexOf (".")); int contentLength = page.getContentData (). lengte; // schrijf de inhoudsgegevens naar een bestand in de opslagmap}}

Onze ImageCrawler is vergelijkbaar met het uitvoeren van het HttpCrawler, maar we moeten het configureren om binaire inhoud op te nemen:

CrawlConfig config = nieuwe CrawlConfig (); config.setIncludeBinaryContentInCrawling (true); // ... hetzelfde als voorheen CrawlController.WebCrawlerFactory factory = () -> nieuwe ImageCrawler (saveDir); controller.start (fabriek, aantalCrawlers);

3.3. Gegevens verzamelen

Nu we een paar basisvoorbeelden hebben bekeken, gaan we verder met onze HtmlCrawler om enkele basisstatistieken te verzamelen tijdens onze crawl.

Laten we eerst een eenvoudige klasse definiëren die een aantal statistieken bevat:

openbare klasse CrawlerStatistics {privé int verwerktPageCount = 0; private int totalLinksCount = 0; openbare ongeldige incrementProcessedPageCount () {verwerktPageCount ++; } openbare ongeldige incrementTotalLinksCount (int linksCount) {totalLinksCount + = linksCount; } // standaard getters}

Laten we vervolgens onze HtmlCrawler om een CrawlerStatistics instantie via een constructor:

privé CrawlerStatistics-statistieken; openbare HtmlCrawler (CrawlerStatistics stats) {this.stats = stats; }

Met onze nieuwe CrawlerStatistics object, laten we het bezoek methode om te verzamelen wat we willen:

@Override openbaar ongeldig bezoek (pagina pagina) {String url = page.getWebURL (). GetURL (); stats.incrementProcessedPageCount (); if (page.getParseData () instantie van HtmlParseData) {HtmlParseData htmlParseData = (HtmlParseData) page.getParseData (); String title = htmlParseData.getTitle (); String text = htmlParseData.getText (); String html = htmlParseData.getHtml (); Stel links = htmlParseData.getOutgoingUrls (); stats.incrementTotalLinksCount (links.size ()); // doe iets met verzamelde gegevens}}

Laten we nu teruggaan naar onze controller en het HtmlCrawler met een instantie van CrawlerStatistics:

CrawlerStatistics-statistieken = nieuwe CrawlerStatistics (); CrawlController.WebCrawlerFactory factory = () -> nieuwe HtmlCrawler (statistieken);

3.4. Meerdere crawlers

Laten we nu, voortbouwend op onze eerdere voorbeelden, eens kijken hoe we dat kunnen voer meerdere crawlers uit vanaf dezelfde controller.

Dat wordt aanbevolen elke crawler gebruikt zijn eigen map voor tijdelijke opslag, dus we moeten afzonderlijke configuraties maken voor elke configuratie die we gaan uitvoeren.

De CrawlControllers kan een single delen RobotstxtServer, maar verder hebben we eigenlijk van alles een kopie nodig.

Tot nu toe hebben we de CrawlController.start methode om onze crawlers uit te voeren en merkte op dat het een blokkeermethode is. Om veelvouden uit te voeren, gebruiken we CrawlerControlller.startNonBlocking in combinatie met CrawlController.waitUntilFinish.

Laten we nu een controller maken om uit te voeren HtmlCrawler en ImageCrawler gelijktijdig:

Bestand crawlStorageBase = nieuw bestand ("src / test / resources / crawler4j"); CrawlConfig htmlConfig = nieuwe CrawlConfig (); CrawlConfig imageConfig = nieuwe CrawlConfig (); // Configureer opslagmappen en andere configuraties PageFetcher pageFetcherHtml = nieuwe PageFetcher (htmlConfig); PageFetcher pageFetcherImage = nieuwe PageFetcher (imageConfig); RobotstxtConfig robotstxtConfig = nieuwe RobotstxtConfig (); RobotstxtServer robotstxtServer = nieuwe RobotstxtServer (robotstxtConfig, pageFetcherHtml); CrawlController htmlController = nieuwe CrawlController (htmlConfig, pageFetcherHtml, robotstxtServer); CrawlController imageController = nieuwe CrawlController (imageConfig, pageFetcherImage, robotstxtServer); // voeg seed-URL's toe CrawlerStatistics stats = new CrawlerStatistics (); CrawlController.WebCrawlerFactory htmlFactory = () -> nieuwe HtmlCrawler (statistieken); Bestand saveDir = nieuw bestand ("src / test / resources / crawler4j"); CrawlController.WebCrawlerFactory imageFactory = () -> nieuwe ImageCrawler (saveDir); imageController.startNonBlocking (imageFactory, 7); htmlController.startNonBlocking (htmlFactory, 10); htmlController.waitUntilFinish (); imageController.waitUntilFinish ();

4. Configuratie

We hebben al gezien wat we kunnen configureren. Laten we nu een paar andere veelvoorkomende instellingen bekijken.

Instellingen worden toegepast op de CrawlConfig instantie specificeren we in onze controller.

4.1. Kruipdiepte beperken

Standaard kruipen onze crawlers zo diep als ze kunnen. Om te beperken hoe diep ze gaan, kunnen we de crawl-diepte instellen:

crawlConfig.setMaxDepthOfCrawling (2);

Seed-URL's worden geacht op diepte 0 te zijn, dus een crawl-diepte van 2 gaat twee lagen verder dan de seed-URL.

4.2. Maximaal aantal op te halen pagina's

Een andere manier om te beperken hoeveel pagina's onze crawlers beslaan, is door het maximale aantal te crawlen pagina's in te stellen:

crawlConfig.setMaxPagesToFetch (500);

4.3. Maximumaantal uitgaande links

We kunnen ook het aantal uitgaande links dat van elke pagina wordt gevolgd, beperken:

crawlConfig.setMaxOutgoingLinksToFollow (2000);

4.4. Beleefdheid Vertraging

Omdat zeer efficiënte crawlers gemakkelijk een belasting kunnen zijn voor webservers, heeft crawler4j wat het een beleefdheidsvertraging noemt. Standaard is deze ingesteld op 200 milliseconden. We kunnen deze waarde aanpassen als we:

crawlConfig.setPolitenessDelay (300);

4.5. Inclusief binaire inhoud

We hebben al gebruik gemaakt van de optie om binaire inhoud op te nemen met onze ImageCrawler:

crawlConfig.setIncludeBinaryContentInCrawling (true);

4.6. Inclusief HTTPS

Crawlers bevatten standaard HTTPS-pagina's, maar we kunnen dit uitschakelen:

crawlConfig.setIncludeHttpsPages (false);

4.7. Hervat crawlen

Als we een langlopende crawler hebben en we willen dat deze automatisch wordt hervat, kunnen we hervatten van crawlen instellen. Als u het inschakelt, werkt het mogelijk langzamer:

crawlConfig.setResumableCrawling (true);

4.8. User-Agent-tekenreeks

De standaard user-agent-tekenreeks voor crawler4j is crawler4j. Laten we dat aanpassen:

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

We hebben hier zojuist enkele basisconfiguraties besproken. We kunnen kijken CrawConfig class als we geïnteresseerd zijn in enkele van de meer geavanceerde of obscure configuratie-opties.

5. Conclusie

In dit artikel hebben we crawler4j gebruikt om onze eigen webcrawlers te maken. We zijn begonnen met twee eenvoudige voorbeelden van het crawlen van HTML en afbeeldingen. Vervolgens hebben we op die voorbeelden voortgebouwd om te zien hoe we statistieken kunnen verzamelen en meerdere crawlers tegelijkertijd kunnen uitvoeren.

De volledige codevoorbeelden zijn beschikbaar op GitHub.