Zum Inhalt

So ignorieren Sie Nicht-HTML-URLs beim Web-Crawling mit C#

  • by
  • Blog
  • 7 min gelesen

Einleitung

Beim Webcrawlen werden Webseiten programmgesteuert besucht und deren Inhalt sowie ausgehende Links extrahiert, um eine Website rekursiv zu crawlen. Beim Erstellen eines Webcrawlers ist es wichtig, nur tatsächliche HTML-Webseiten abzurufen und zu analysieren und andere Dateitypen wie Bilder, Videos, PDFs usw. zu ignorieren. In diesem Artikel werden zwei effektive Methoden zum Herausfiltern von Nicht-HTML-URLs in einem C#-Web erläutert Crawler:

  1. Überprüfen des URL-Suffixes anhand einer Liste unerwünschter Dateierweiterungen
  2. Durchführen einer einfachen HEAD-Anfrage und Überprüfen des Content-Type-Antwortheaders

Durch die Implementierung dieser Techniken können Sie die Effizienz Ihres Crawlers steigern und unnötige Anfragen und Verarbeitung vermeiden. Lassen Sie uns in die Details jeder Methode eintauchen und sehen, wie Sie sie in der Praxis anwenden können.

Methode 1: Überprüfen Sie URL-Suffixe auf unerwünschte Dateierweiterungen

Eine einfache Möglichkeit, Nicht-HTML-URLs zu ignorieren, besteht darin, sich die Dateierweiterung am Ende der URL-Zeichenfolge anzusehen. Sie können eine Liste gängiger Erweiterungen verwalten, die für Bilder, Mediendateien, Dokumente und andere Nicht-Webseiten-Assets verwendet werden. Bevor Sie dann eine URL abrufen, extrahieren Sie deren Suffix und überspringen Sie es, wenn es mit einer dieser Erweiterungen übereinstimmt.

Hier ist ein Codeausschnitt, der zeigt, wie URLs mit diesem Ansatz in C# gefiltert werden:

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

Dieser Code definiert a HashSet von unerwünschten Dateierweiterungen, dann extrahiert es für eine bestimmte URL die Erweiterung mit Path.GetExtension(). Wenn die kleingeschriebene, durch Punkte abgeschnittene Erweiterung im vorhanden ist UnwantedExtensions gesetzt, wird die URL übersprungen. Andernfalls wird sie als HTML-Seite abgerufen und gecrawlt.

Der große Vorteil dieser Methode besteht darin, dass sie sehr schnell ist – nur eine einfache String-Operation pro URL. Der Nachteil besteht darin, dass URLs mit der richtigen Dateierweiterung erforderlich sind, was möglicherweise nicht immer der Fall ist. Es ist auch möglich, HTML-Seiten mit zu erstellen .asp or .php Erweiterungen, die wir crawlen möchten, aber möglicherweise herausgefiltert werden.

Methode 2: Führen Sie eine HEAD-Anfrage durch und prüfen Sie den Content-Type-Header

Ein robusterer, aber etwas langsamerer Ansatz besteht darin, eine einfache HEAD-Anfrage an jede URL durchzuführen und den Content-Type-Header in der Antwort zu überprüfen. Eine HEAD-Anfrage ähnelt einer GET-Anfrage, außer dass sie den Server auffordert, nur die Antwortheader und nicht den tatsächlichen Inhalt zurückzugeben.

Der Content-Type-Header gibt den Medientyp der angeforderten Ressource an. Bei HTML-Seiten ist der Inhaltstyp normalerweise „text/html“. Durch Überprüfen dieses Header-Werts können Sie zuverlässiger feststellen, ob eine URL auf eine HTML-Seite oder einen anderen Dateityp verweist.

So implementieren Sie dies in C#:

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}");
}

Dies sendet eine asynchrone HEAD-Anfrage mit HttpClient und ruft den Content-Type-Header aus der Antwort ab. Wenn der Medientyp „text/html“ ist, wird die URL abgerufen und als HTML-Seite geparst. Andernfalls wird es übersprungen und der Nicht-HTML-Inhaltstyp wird protokolliert.

Der Vorteil von HEAD-Anfragen besteht darin, dass Sie direkt vom Server eine eindeutigere Antwort auf den Inhaltstyp erhalten. Der potenzielle Nachteil ist die zusätzliche Latenz beim Roundtrip zum Server, die sich bei einer großen Anzahl von URLs summieren kann. HEAD-Anfragen sind jedoch normalerweise recht schnell, da kein Inhalt zurückgegeben wird.

Kombination der beiden Methoden für maximale Wirksamkeit

Für die beste Abdeckung und Effizienz empfehle ich, beide oben genannten Methoden zusammen in Ihrem C#-Webcrawler zu verwenden. Indem Sie zunächst die URL-Erweiterung mit einer Sperrliste vergleichen, können Sie offensichtliche Nicht-HTML-URLs schnell und ohne Anfragen herausfiltern. Dann können Sie für URLs, die diese Prüfung bestehen, eine HEAD-Anfrage durchführen, um zu überprüfen, ob es sich tatsächlich um eine HTML-Seite handelt, bevor Sie sie vollständig abrufen.

So könnte die zentrale Crawling-Logik insgesamt aussehen:

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));
}

Dieser Crawl Die Methode überprüft zunächst die Dateierweiterung der URL und überspringt sie, wenn sie im Hashset für unerwünschte Erweiterungen enthalten ist. Anschließend wird geprüft, ob die URL bereits besucht wurde, und wenn ja, wird sie übersprungen. Als nächstes führt es eine HEAD-Anfrage durch und überprüft, ob der Inhaltstyp HTML ist, bevor die URL hinzugefügt wird VisitedUrls Hashset erstellen, den Inhalt vollständig abrufen und Links analysieren, um sie für das weitere Crawlen in die Warteschlange zu stellen.

In dieser Kombination bieten Erweiterungsfilterung und HEAD-Anfragen einen effektiven Doppelschlag zum Ignorieren von Nicht-HTML-Inhalten beim Crawlen. Die Erweiterungsprüfung ist ein schneller Vorfilter, während die HEAD-Anfrage die letzte Bestätigung ist, bevor der vollständige Seitenabruf durchgeführt wird.

Weitere Überlegungen und Best Practices

Neben dem Filtern von Nicht-HTML-URLs gibt es noch einige andere wichtige Dinge zu beachten, wenn Sie einen gut funktionierenden und effizienten Webcrawler erstellen:

  • Beachten Sie immer die robots.txt-Regeln und crawlen Sie keine unzulässigen Seiten. Sie können robots.txt-Dateien analysieren und URLs vor dem Crawlen mit ihnen vergleichen.

  • Begrenzen Sie Ihre Crawling-Rate und die Anzahl gleichzeitiger Anfragen, um eine Überlastung der Server zu vermeiden. Eine gute Richtlinie ist nicht mehr als eine Anfrage pro Sekunde und Domain.

  • Behandeln Sie HTTP-Statuscodes, Zeitüberschreitungen und Fehler ordnungsgemäß. Wiederholen Sie Fehler mit exponentiellem Backoff und wissen Sie, wann Sie aufgeben müssen.

  • Verfolgen Sie bereits besuchte URLs mithilfe eines Hashsets, einer Datenbank oder einer effizienten Datenstruktur, um ein erneutes Crawlen doppelter Inhalte zu vermeiden. Ein Blütenfilter ist eine schöne platzsparende Option.

Wenn Sie diese Vorgehensweisen befolgen und eine reine HTML-Filterung implementieren, sind Sie auf dem besten Weg, einen höflichen und zielgerichteten Webcrawler mit C# zu erstellen. Die in diesem Artikel erläuterten Techniken sollen Ihnen alles bieten, was Sie brauchen, um irrelevante Inhalte zu vermeiden und sich auf die HTML-Seiten zu konzentrieren, die Ihnen wichtig sind.

Zusammenfassung

Webcrawler sind ein leistungsstarkes Werkzeug zum Durchsuchen und Analysieren von Inhalten auf Websites. Um jedoch effizient und höflich zu sein, ist es wichtig, dass sie sich auf tatsächliche HTML-Seiten konzentrieren und andere Arten von URLs überspringen. In diesem Artikel haben wir zwei komplementäre Techniken kennengelernt, um dies in einem C#-Crawler zu tun:

  1. Herausfiltern unerwünschter URL-Erweiterungen
  2. Überprüfen des Content-Type-Headers mit einer HEAD-Anfrage

Wir haben erläutert, wie diese beiden Methoden implementiert werden, und haben dann gesehen, wie man sie kombiniert, um eine möglichst vollständige Abdeckung zu erzielen. Wir haben auch einige andere Best Practices für Crawler angesprochen, z. B. die Berücksichtigung von robots.txt und die Begrenzung der Anfragerate.

Hoffentlich haben Sie jetzt ein solides Verständnis dafür, wie Sie Nicht-HTML-URLs in Ihren Webcrawlern effizient ignorieren können. Die Anwendung dieser Techniken trägt dazu bei, dass Ihr Crawler schnell und konzentriert bleibt und gleichzeitig eine unnötige Belastung der Server vermeidet.

Hier sind ein paar zusätzliche Ressourcen, die Sie sich vielleicht ansehen sollten, um mehr zu erfahren:

Viel Spaß beim (selektiven) Krabbeln!

Mitreden

E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind MIT * gekennzeichnet. *