Meteen naar de inhoud

Niet-HTML-URL's negeren bij webcrawlen met C#

  • by
  • Blog
  • 7 min gelezen

Introductie

Webcrawlen is het proces waarbij webpagina's programmatisch worden bezocht en de inhoud en uitgaande links worden opgehaald om recursief een website te crawlen. Bij het bouwen van een webcrawler is het belangrijk om alleen daadwerkelijke HTML-webpagina's op te halen en te parseren, terwijl andere typen bestanden zoals afbeeldingen, video's, pdf's, enz. worden genegeerd. In dit artikel worden twee effectieve methoden uitgelegd voor het uitfilteren van niet-HTML-URL's in een C#-web crawler:

  1. Het URL-achtervoegsel controleren aan de hand van een lijst met ongewenste bestandsextensies
  2. Een lichtgewicht HEAD-verzoek uitvoeren en de Content-Type-antwoordheader inspecteren

Door deze technieken te implementeren, kunt u de efficiëntie van uw crawler verhogen en onnodige verzoeken en verwerkingen voorkomen. Laten we eens dieper ingaan op de details van elke methode en zien hoe u deze in de praktijk kunt toepassen.

Methode 1: Controleer URL-achtervoegsels op ongewenste bestandsextensies

Een eenvoudige manier om niet-HTML-URL's te negeren, is door naar de bestandsextensie aan het einde van de URL-reeks te kijken. U kunt een lijst bijhouden met veelvoorkomende extensies die worden gebruikt voor afbeeldingen, mediabestanden, documenten en andere niet-webpagina-items. Voordat u een URL ophaalt, extraheert u het achtervoegsel ervan en slaat u deze over als deze overeenkomt met een van deze extensies.

Hier is een codefragment dat laat zien hoe u URL's kunt filteren met deze aanpak in C#:

HashSet<string> UnwantedExtensions = new HashSet<string> { 
  "jpg", "jpeg", "png", "gif", "bmp", "tiff",  // Images
  "mp4", "avi", "mov", "wmv", "flv", "webm",   // Videos 
  "mp3", "wav", "aac", "flac", "ogg",          // Audio
  "pdf", "doc", "docx", "xls", "xlsx", "ppt",  // Documents
  "zip", "tar", "gz", "rar", "7z"              // Archives
}; 

Uri uri = new Uri("http://example.com/image.jpg");
string extension = Path.GetExtension(uri.AbsolutePath).ToLower().TrimStart(‘.‘);

if (UnwantedExtensions.Contains(extension))
{
   Console.WriteLine($"Skipping URL with extension ‘{extension}‘: {uri}");
}
else 
{
   Console.WriteLine($"Fetching URL: {uri}");
   // Crawl the HTML page...
}

Deze code definieert a HashSet van ongewenste bestandsextensies, waarna het voor een bepaalde URL de extensie extraheert met behulp van Path.GetExtension(). Als de extensie met kleine letters en met punten bijgesneden bestaat in de UnwantedExtensions ingesteld, wordt de URL overgeslagen. Anders wordt de pagina opgehaald en gecrawld als een HTML-pagina.

Het grote voordeel van deze methode is dat deze erg snel is: slechts een eenvoudige tekenreeksbewerking per URL. Het nadeel is dat het afhankelijk is van URL's met de juiste bestandsextensie, wat niet altijd het geval hoeft te zijn. Het is ook mogelijk om HTML-pagina's mee te nemen .asp or .php extensies die we zouden willen crawlen, maar die mogelijk worden uitgefilterd.

Methode 2: Voer een HEAD-verzoek uit en inspecteer de header van het inhoudstype

Een robuustere, maar iets langzamere aanpak is het uitvoeren van een lichtgewicht HEAD-verzoek voor elke URL en het controleren van de Content-Type-header in het antwoord. Een HEAD-verzoek is net als een GET-verzoek, behalve dat het de server vraagt ​​om alleen de antwoordheaders terug te sturen en niet de daadwerkelijke inhoud.

De Content-Type header geeft het mediatype van de aangevraagde bron aan. Voor HTML-pagina's is het inhoudstype doorgaans "text/html". Door deze headerwaarde te controleren, kunt u betrouwbaarder bepalen of een URL naar een HTML-pagina of een ander type bestand verwijst.

Hier leest u hoe u dit in C# implementeert:

HttpClient httpClient = new HttpClient();

Uri uri = new Uri("http://example.com/page");
HttpRequestMessage headRequest = new HttpRequestMessage(HttpMethod.Head, uri);
HttpResponseMessage response = await httpClient.SendAsync(headRequest);

string contentType = response.Content.Headers.ContentType?.MediaType;

if (contentType == "text/html")
{
   Console.WriteLine($"Fetching HTML page: {uri}");
   // Crawl the HTML page...
}  
else
{
   Console.WriteLine($"Skipping non-HTML URL with Content-Type ‘{contentType}‘: {uri}");
}

Hiermee wordt een asynchrone HEAD-aanvraag verzonden met behulp van HttpClient en haalt de Content-Type header op uit het antwoord. Als het mediatype 'text/html' is, wordt de URL opgehaald en geparseerd als een HTML-pagina. Anders wordt het overgeslagen en wordt het niet-HTML-inhoudstype vastgelegd.

Het voordeel van HEAD-verzoeken is dat ze u rechtstreeks vanaf de server een definitiever antwoord geven over het inhoudstype. Het potentiële nadeel is de extra latentie van de heen- en terugreis naar de server, die kan oplopen tot een groot aantal URL's. HEAD-verzoeken zijn echter doorgaans vrij snel, omdat er geen inhoud wordt geretourneerd.

Combineer de twee methoden voor maximale effectiviteit

Voor de beste dekking en efficiëntie raad ik aan beide bovenstaande methoden samen te gebruiken in uw C#-webcrawler. Door eerst de URL-extensie te vergelijken met een weigeringslijst, kunt u zonder enig verzoek snel voor de hand liggende niet-HTML-URL's filteren. Voor URL's die deze controle doorstaan, kunt u vervolgens een HEAD-verzoek uitvoeren om te verifiëren dat het daadwerkelijk een HTML-pagina is voordat deze volledig wordt opgehaald.

Hier ziet u hoe de kerncrawllogica eruit zou kunnen zien als u alles samenvoegt:

public async Task Crawl(Uri uri) 
{
  string extension = Path.GetExtension(uri.AbsolutePath).ToLower().TrimStart(‘.‘);

  if (UnwantedExtensions.Contains(extension))
  {
    Console.WriteLine($"Skipping URL with unwanted extension ‘{extension}‘: {uri}");
    return;
  }

  if (VisitedUrls.Contains(uri))
  {
    Console.WriteLine($"Skipping already visited URL: {uri}");
    return;
  }

  HttpRequestMessage headRequest = new HttpRequestMessage(HttpMethod.Head, uri);
  HttpResponseMessage headResponse = await _httpClient.SendAsync(headRequest);

  string contentType = headResponse.Content.Headers.ContentType?.MediaType;

  if (contentType != "text/html")
  {    
    Console.WriteLine($"Skipping non-HTML URL with Content-Type ‘{contentType}‘: {uri}");
    return;
  }

  VisitedUrls.Add(uri);

  HttpResponseMessage getResponse = await _httpClient.GetAsync(uri);
  string content = await getResponse.Content.ReadAsStringAsync();

  Console.WriteLine($"Crawled URL: {uri}");

  // Parse links from HTML and queue them for crawling
  CrawlQueue.Enqueue(ExtractLinks(uri, content));
}

Deze Crawl methode controleert eerst de bestandsextensie van de URL en slaat deze over als deze in de hashset voor ongewenste extensies staat. Vervolgens wordt gecontroleerd of de URL al is bezocht en zo ja, dan wordt deze overgeslagen. Vervolgens voert het een HEAD-verzoek uit en verifieert het dat het inhoudstype HTML is voordat de URL aan het VisitedUrls hashset, het volledig ophalen van de inhoud en het ontleden van links om in de wachtrij te staan ​​voor verder crawlen.

Op deze manier samen gebruikt, bieden extensiefiltering en HEAD-verzoeken een effectief een-tweetje voor het negeren van niet-HTML-inhoud tijdens het crawlen. De extensiecontrole is een snel voorlopig filter, terwijl het HEAD-verzoek de laatste bevestiging is voordat de volledige pagina wordt opgehaald.

Andere overwegingen en best practices

Naast het filteren van niet-HTML-URL's zijn er nog enkele andere belangrijke zaken waarmee u rekening moet houden bij het bouwen van een goed gedragen en efficiënte webcrawler:

  • Respecteer altijd de robots.txt-regels en crawl geen pagina's die niet zijn toegestaan. U kunt robots.txt-bestanden parseren en de URL's vergelijken voordat u gaat crawlen.

  • Beperk uw crawlsnelheid en het aantal gelijktijdige verzoeken om overbelasting van servers te voorkomen. Een goede richtlijn is niet meer dan één verzoek per seconde per domein.

  • Ga op een correcte manier om met HTTP-statuscodes, time-outs en fouten. Probeer mislukte pogingen opnieuw met exponentieel uitstel en weet wanneer u moet opgeven.

  • Houd reeds bezochte URL's bij met behulp van een hashset, database of efficiënte datastructuur om te voorkomen dat dubbele inhoud opnieuw wordt gecrawld. Een bloeifilter is een mooie ruimtebesparende optie.

Door deze werkwijzen te volgen en alleen-HTML-filters te implementeren, bent u goed op weg om een ​​beleefde en gerichte webcrawler te bouwen met behulp van C#. De technieken die in dit artikel worden uitgelegd, zouden u alles moeten bieden wat u nodig heeft om irrelevante inhoud te vermijden en u te concentreren op de HTML-pagina's die u belangrijk vindt.

Conclusie

Webcrawlers zijn een krachtig hulpmiddel voor het verkennen en analyseren van inhoud op websites, maar om efficiënt en beleefd te zijn is het van cruciaal belang dat ze zich concentreren op daadwerkelijke HTML-pagina's en andere typen URL's overslaan. In dit artikel hebben we twee complementaire technieken geleerd om dat te doen in een C#-crawler:

  1. Filteren van ongewenste URL-extensies
  2. De Content-Type header controleren met een HEAD-verzoek

We hebben doorgenomen hoe u beide methoden kunt implementeren en vervolgens hebben we gezien hoe u ze kunt combineren voor de meest complete dekking. We hebben ook enkele andere best practices voor crawlers besproken, zoals het respecteren van robots.txt en het beperken van het verzoekpercentage.

Hopelijk heeft u nu een goed begrip van hoe u niet-HTML-URL's in uw webcrawlers efficiënt kunt negeren. Door deze technieken toe te passen, blijft uw crawler snel en gefocust en wordt onnodige belasting van servers vermeden.

Hier zijn enkele aanvullende bronnen die u wellicht wilt raadplegen voor meer informatie:

Gelukkig (selectief) kruipen!

Doe mee aan het gesprek

Uw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd *