概要
Web クローリングは、プログラムによって Web ページにアクセスし、そのコンテンツと送信リンクを抽出して Web サイトを再帰的にクロールするプロセスです。 Web クローラーを構築するときは、画像、ビデオ、PDF などの他の種類のファイルを無視し、実際の HTML Web ページのみを取得して解析することが重要です。この記事では、C# Web で非 HTML URL をフィルターで除外するための 2 つの効果的な方法について説明します。昇降補助具:
- URL サフィックスを不要なファイル拡張子のリストと照合する
- 軽量の HEAD リクエストを実行し、Content-Type 応答ヘッダーを検査する
これらの手法を実装すると、クローラーの効率が向上し、不必要なリクエストや処理を回避できます。各メソッドの詳細を詳しく見て、実際にそれらを適用する方法を見てみましょう。
方法 1: URL サフィックスで不要なファイル拡張子を確認する
非 HTML URL を無視する簡単な方法の 1 つは、URL 文字列の末尾にあるファイル拡張子を確認することです。画像、メディア ファイル、ドキュメント、その他の非 Web ページ アセットに使用される一般的な拡張子のリストを管理できます。次に、URL を取得する前に、そのサフィックスを抽出し、それらの拡張子のいずれかに一致する場合はスキップします。
C# でこのアプローチを使用して URL をフィルターする方法を示すコード スニペットを次に示します。
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 リクエストを実行し、Content-Type ヘッダーを検査する
より堅牢ですが、少し遅いアプローチは、各 URL に対して軽量の HEAD リクエストを実行し、応答内の 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 ヘッダーを取得します。メディア タイプが「text/html」の場合、URL は HTML ページとして取得され、解析されます。それ以外の場合はスキップされ、非 HTML コンテンツ タイプがログに記録されます。
HEAD リクエストの利点は、コンテンツ タイプのより明確な回答がサーバーから直接得られることです。潜在的な欠点は、サーバーへの往復の待ち時間が余分に長くなり、URL の数が膨大になる可能性があることです。ただし、HEAD リクエストはコンテンツが返されないため、通常は非常に高速です。
2 つの方法を組み合わせて最大の効果を得る
最適な範囲と効率を得るには、C# Web クローラーで上記の両方の方法を一緒に使用することをお勧めします。最初に URL 拡張子を拒否リストと照合することで、リクエストを行わずに明らかな HTML 以外の URL をすばやくフィルタリングして除外できます。その後、そのチェックを通過した 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
ハッシュセットを取得し、コンテンツを完全に取得し、さらなるクロールのためにキューに入れるリンクを解析します。
このように拡張機能フィルタリングと HEAD リクエストを組み合わせて使用すると、クロール中に HTML 以外のコンテンツを無視する効果的なワンツーパンチが提供されます。拡張子チェックは高速な予備フィルターですが、HEAD リクエストはページ全体のフェッチにコミットする前の最終確認です。
その他の考慮事項とベストプラクティス
非 HTML URL のフィルタリングに加えて、適切に動作する効率的な Web クローラーを構築する際に留意すべき重要な点がいくつかあります。
robots.txt のルールを常に尊重し、許可されていないページをクロールしないでください。クロールする前に、robots.txt ファイルを解析し、それらのファイルに対して URL をチェックできます。
サーバーの過負荷を避けるために、クロール レートと同時リクエストの数を制限します。適切なガイドラインは、ドメインごとに 1 秒あたり 1 リクエストを超えないようにすることです。
HTTP ステータス コード、タイムアウト、エラーを適切に処理します。指数バックオフを使用して失敗を再試行し、いつ諦めるべきかを判断します。
重複コンテンツの再クロールを避けるために、ハッシュセット、データベース、または効率的なデータ構造を使用して、すでにアクセスした URL を追跡します。ブルーム フィルターはスペース効率の優れたオプションです。
これらのプラクティスに従って HTML のみのフィルター処理を実装すると、C# を使用して丁寧で焦点を絞った Web クローラーを構築できるようになります。この記事で説明するテクニックは、無関係なコンテンツを避け、関心のある HTML ページに焦点を当てるために必要なすべてを提供します。
まとめ
Web クローラーは、Web サイト上のコンテンツを探索および分析するための強力なツールですが、効率的かつ丁寧に行うためには、実際の HTML ページに焦点を当て、他のタイプの URL をスキップすることが重要です。この記事では、C# クローラーでこれを行うための 2 つの補完的なテクニックを学びました。
- 不要な URL 拡張子をフィルタリングして除外する
- HEAD リクエストによる Content-Type ヘッダーの確認
これらの両方の方法を実装する方法を説明し、次にそれらを組み合わせて最も完全にカバーする方法を確認しました。また、robots.txt の尊重やリクエスト レートの制限など、他のクローラーのベスト プラクティスについても触れました。
Web クローラーで HTML 以外の URL を効率的に無視する方法をしっかりと理解できたと思います。これらのテクニックを適用すると、サーバーへの不要な負荷を回避しながら、クローラーの高速性と集中力を維持することができます。
詳細については、以下の追加リソースを参照してください。
楽しく(選択的に)クロールしてください!