Введение
Сканирование веб-страниц — это процесс программного посещения веб-страниц и извлечения их содержимого и исходящих ссылок для рекурсивного сканирования веб-сайта. При создании веб-сканера важно получать и анализировать только реальные веб-страницы HTML, игнорируя при этом другие типы файлов, такие как изображения, видео, PDF-файлы и т. д. В этой статье будут описаны два эффективных метода фильтрации URL-адресов, отличных от HTML, в веб-сайте C#. гусеничный трактор:
- Проверка суффикса URL-адреса по списку нежелательных расширений файлов.
- Выполнение облегченного запроса 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#:
- Фильтрация нежелательных расширений URL-адресов
- Проверка заголовка Content-Type с помощью запроса HEAD
Мы рассмотрели, как реализовать оба этих метода, а затем увидели, как объединить их для наиболее полного покрытия. Мы также коснулись некоторых других рекомендаций по поиску роботов, таких как уважение файла robots.txt и ограничение частоты запросов.
Надеемся, теперь у вас есть четкое представление о том, как эффективно игнорировать URL-адреса, отличные от HTML, в ваших веб-сканерах. Применение этих методов поможет вашему сканеру работать быстро и целенаправленно, избегая при этом ненужной нагрузки на серверы.
Вот несколько дополнительных ресурсов, которые вы можете просмотреть, чтобы узнать больше:
- Введение в парсинг веб-страниц с помощью C#
- Лучшие практики парсинга веб-страниц
- Руководство по файлу robots.txt
Счастливого (выборочного) ползания!