перейти к содержанию

Как игнорировать URL-адреса, отличные от HTML, при веб-сканировании с использованием C#

Введение

Сканирование веб-страниц — это процесс программного посещения веб-страниц и извлечения их содержимого и исходящих ссылок для рекурсивного сканирования веб-сайта. При создании веб-сканера важно получать и анализировать только реальные веб-страницы HTML, игнорируя при этом другие типы файлов, такие как изображения, видео, PDF-файлы и т. д. В этой статье будут описаны два эффективных метода фильтрации URL-адресов, отличных от HTML, в веб-сайте C#. гусеничный трактор:

  1. Проверка суффикса URL-адреса по списку нежелательных расширений файлов.
  2. Выполнение облегченного запроса HEAD и проверка заголовка ответа Content-Type.

Внедряя эти методы, вы можете повысить эффективность своего сканера и избежать ненужных запросов и обработки. Давайте углубимся в детали каждого метода и посмотрим, как применить их на практике.

Способ 1. Проверьте суффиксы URL-адресов на наличие нежелательных расширений файлов.

Один из простых способов игнорировать URL-адреса, отличные от HTML, — это посмотреть расширение файла в конце строки URL-адреса. Вы можете вести список распространенных расширений, используемых для изображений, мультимедийных файлов, документов и других ресурсов, не являющихся веб-страницами. Затем, прежде чем получать URL-адрес, извлеките его суффикс и пропустите его, если он соответствует одному из этих расширений.

Вот фрагмент кода, показывающий, как фильтровать URL-адреса с использованием этого подхода на 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...
}

Этот код определяет HashSet нежелательных расширений файлов, затем для данного URL-адреса он извлекает расширение, используя Path.GetExtension(). Если в UnwantedExtensions установлен, URL-адрес пропускается. В противном случае он будет получен и просканирован как HTML-страница.

Большим преимуществом этого метода является то, что он очень быстрый – всего лишь простая строковая операция для каждого URL-адреса. Обратной стороной является то, что он полагается на URL-адреса, имеющие правильное расширение файла, что не всегда так. Также возможно иметь HTML-страницы с .asp or .php расширения, которые мы хотели бы просканировать, но могли бы быть отфильтрованы.

Способ 2. Выполните запрос HEAD и проверьте заголовок типа контента.

Более надежный, но немного более медленный подход — выполнить упрощенный запрос HEAD для каждого URL-адреса и проверить заголовок Content-Type в ответе. Запрос HEAD аналогичен запросу GET, за исключением того, что он просит сервер вернуть только заголовки ответа, а не фактическое содержимое.

Заголовок Content-Type указывает тип носителя запрошенного ресурса. Для HTML-страниц Content-Type обычно имеет значение «text/html». Проверив это значение заголовка, вы сможете более надежно определить, указывает ли URL-адрес на HTML-страницу или файл другого типа.

Вот как это реализовать на 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}");
}

Это отправляет асинхронный запрос HEAD, используя HttpClient и извлекает заголовок Content-Type из ответа. Если тип носителя — «текст/html», URL-адрес извлекается и анализируется как HTML-страница. В противном случае он пропускается и регистрируется тип контента, отличный от HTML.

Преимущество запросов HEAD заключается в том, что они дают более точный ответ о типе контента прямо с сервера. Потенциальным недостатком является дополнительная задержка при обратном пути к серверу, которая может составлять для большого количества URL-адресов. Однако запросы HEAD обычно выполняются довольно быстро, поскольку контент не возвращается.

Сочетание двух методов для максимальной эффективности

Для наилучшего охвата и эффективности я рекомендую использовать оба вышеуказанных метода вместе в веб-сканере C#. Сначала проверив расширение URL-адреса на наличие списка запрещенных URL-адресов, вы можете быстро отфильтровать очевидные URL-адреса, отличные от HTML, без каких-либо запросов. Затем для URL-адресов, прошедших эту проверку, вы можете выполнить запрос HEAD, чтобы убедиться, что это действительно HTML-страница, прежде чем полностью ее получить.

Вот как может выглядеть основная логика сканирования, если сложить все это воедино:

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

Эта Crawl Метод сначала проверяет расширение файла URL-адреса и пропускает его, если оно находится в хэш-наборе нежелательных расширений. Затем он проверяет, был ли уже посещен URL-адрес, и если да, то пропускает его. Затем он выполняет запрос HEAD и проверяет, что Content-Type является HTML, прежде чем добавлять URL-адрес в файл. VisitedUrls hashset, полностью извлекающий контент и анализирующий ссылки для постановки в очередь для дальнейшего сканирования.

При совместном использовании фильтрация расширений и запросы HEAD обеспечивают эффективный двойной удар по игнорированию контента, отличного от HTML, во время сканирования. Проверка расширения — это быстрый предварительный фильтр, а запрос HEAD — окончательное подтверждение перед фиксацией полной загрузки страницы.

Другие соображения и лучшие практики

Помимо фильтрации URL-адресов, отличных от HTML, при создании качественного и эффективного веб-сканера следует учитывать еще несколько важных вещей:

  • Всегда соблюдайте правила файла robots.txt и не сканируйте запрещенные страницы. Вы можете анализировать файлы robots.txt и сверять с ними URL-адреса перед сканированием.

  • Ограничьте скорость сканирования и количество одновременных запросов, чтобы избежать перегрузки серверов. Хорошая рекомендация — не более одного запроса в секунду на домен.

  • Грамотно обрабатывайте коды состояния HTTP, тайм-ауты и ошибки. Повторяйте неудачные попытки с экспоненциальной задержкой и знайте, когда следует сдаться.

  • Отслеживайте уже посещенные URL-адреса, используя хэш-набор, базу данных или эффективную структуру данных, чтобы избежать повторного сканирования дублированного контента. Фильтр Блума — хороший компактный вариант.

Следуя этим рекомендациям и реализуя фильтрацию только по HTML, вы будете на верном пути к созданию вежливого и целенаправленного веб-сканера с использованием C#. Методы, описанные в этой статье, должны дать вам все необходимое, чтобы избежать нерелевантного контента и сосредоточиться на интересующих вас HTML-страницах.

Заключение

Веб-сканеры — мощный инструмент для изучения и анализа контента на веб-сайтах, но для того, чтобы они были эффективными и вежливыми, очень важно, чтобы они концентрировались на реальных HTML-страницах и пропускали другие типы URL-адресов. В этой статье мы изучили два взаимодополняющих метода выполнения этой задачи с помощью сканера C#:

  1. Фильтрация нежелательных расширений URL-адресов
  2. Проверка заголовка Content-Type с помощью запроса HEAD

Мы рассмотрели, как реализовать оба этих метода, а затем увидели, как объединить их для наиболее полного покрытия. Мы также коснулись некоторых других рекомендаций по поиску роботов, таких как уважение файла robots.txt и ограничение частоты запросов.

Надеемся, теперь у вас есть четкое представление о том, как эффективно игнорировать URL-адреса, отличные от HTML, в ваших веб-сканерах. Применение этих методов поможет вашему сканеру работать быстро и целенаправленно, избегая при этом ненужной нагрузки на серверы.

Вот несколько дополнительных ресурсов, которые вы можете просмотреть, чтобы узнать больше:

Счастливого (выборочного) ползания!

Присоединяйтесь к беседе

Ваш электронный адрес не будет опубликован. Обязательные поля помечены * *