Bỏ để qua phần nội dung

Cách bỏ qua các URL không phải HTML khi thu thập dữ liệu web bằng C#

  • by
  • Blog
  • Đã đọc 7 phút

Giới thiệu

Thu thập dữ liệu web là quá trình truy cập các trang web theo chương trình và trích xuất nội dung cũng như các liên kết đi của chúng để thu thập dữ liệu một trang web một cách đệ quy. Khi xây dựng trình thu thập dữ liệu web, điều quan trọng là chỉ tìm nạp và phân tích các trang web HTML thực tế trong khi bỏ qua các loại tệp khác như hình ảnh, video, PDF, v.v. Bài viết này sẽ giải thích hai phương pháp hiệu quả để lọc các URL không phải HTML trong web C# trình thu thập thông tin:

  1. Kiểm tra hậu tố URL dựa trên danh sách các phần mở rộng tệp không mong muốn
  2. Thực hiện yêu cầu HEAD nhẹ và kiểm tra tiêu đề phản hồi Kiểu nội dung

Bằng cách triển khai các kỹ thuật này, bạn có thể tăng hiệu quả của trình thu thập thông tin và tránh các yêu cầu và xử lý không cần thiết. Hãy cùng đi sâu vào chi tiết của từng phương pháp và xem cách áp dụng chúng vào thực tế.

Phương pháp 1: Kiểm tra hậu tố URL để tìm phần mở rộng tệp không mong muốn

Một cách đơn giản để bỏ qua các URL không phải HTML là xem phần mở rộng tệp ở cuối chuỗi URL. Bạn có thể duy trì danh sách các tiện ích mở rộng phổ biến được sử dụng cho hình ảnh, tệp phương tiện, tài liệu và các nội dung không phải trang web khác. Sau đó, trước khi tìm nạp URL, hãy trích xuất hậu tố của nó và bỏ qua nếu nó khớp với một trong các tiện ích mở rộng đó.

Đây là đoạn mã hiển thị cách lọc URL bằng phương pháp này trong 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...
}

Mã này định nghĩa một HashSet của các phần mở rộng tệp không mong muốn, sau đó đối với một URL nhất định, nó sẽ trích xuất phần mở rộng bằng cách sử dụng Path.GetExtension(). Nếu chữ thường, phần mở rộng được cắt bớt dấu chấm tồn tại trong UnwantedExtensions được đặt, URL sẽ bị bỏ qua. Nếu không, nó sẽ được tìm nạp và thu thập thông tin dưới dạng trang HTML.

Ưu điểm lớn của phương pháp này là nó rất nhanh – chỉ là một thao tác chuỗi đơn giản trên mỗi URL. Nhược điểm là nó phụ thuộc vào các URL có phần mở rộng tệp chính xác, điều này có thể không phải lúc nào cũng đúng. Cũng có thể có các trang HTML với .asp or .php các tiện ích mở rộng mà chúng tôi muốn thu thập thông tin nhưng có thể bị lọc ra.

Phương pháp 2: Thực hiện yêu cầu HEAD và kiểm tra tiêu đề loại nội dung

Một cách tiếp cận mạnh mẽ hơn nhưng chậm hơn một chút là thực hiện một yêu cầu HEAD nhẹ cho mỗi URL và kiểm tra tiêu đề Content-Type trong phản hồi. Yêu cầu HEAD giống như yêu cầu GET ngoại trừ việc nó yêu cầu máy chủ chỉ trả về tiêu đề phản hồi chứ không phải nội dung thực tế.

Tiêu đề Content-Type cho biết loại phương tiện của tài nguyên được yêu cầu. Đối với các trang HTML, Loại nội dung thường sẽ là "text/html". Bằng cách kiểm tra giá trị tiêu đề này, bạn có thể xác định một cách đáng tin cậy hơn liệu URL có trỏ đến trang HTML hay một số loại tệp khác hay không.

Đây là cách thực hiện điều này trong 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}");
}

Điều này sẽ gửi một yêu cầu HEAD không đồng bộ bằng cách sử dụng HttpClient và lấy tiêu đề Content-Type từ phản hồi. Nếu loại phương tiện là "text/html", URL sẽ được tìm nạp và phân tích cú pháp dưới dạng trang HTML. Nếu không, nó sẽ bị bỏ qua và Loại nội dung không phải HTML sẽ được ghi lại.

Ưu điểm của yêu cầu HEAD là chúng cung cấp cho bạn câu trả lời dứt khoát hơn về loại nội dung ngay từ máy chủ. Nhược điểm tiềm ẩn là độ trễ tăng thêm của chuyến đi khứ hồi đến máy chủ, điều này có thể tạo ra một số lượng lớn URL. Tuy nhiên, các yêu cầu HEAD thường khá nhanh vì không có nội dung nào được trả về.

Kết Hợp Hai Phương Pháp Để Đạt Hiệu Quả Tối Đa

Để có mức độ bao phủ và hiệu quả tốt nhất, tôi khuyên bạn nên sử dụng đồng thời cả hai phương pháp trên trong trình thu thập dữ liệu web C# của mình. Trước tiên, bằng cách kiểm tra tiện ích mở rộng URL theo danh sách từ chối, bạn có thể nhanh chóng lọc ra các URL không phải HTML rõ ràng mà không cần bất kỳ yêu cầu nào. Sau đó, đối với các URL vượt qua bước kiểm tra đó, bạn có thể thực hiện yêu cầu HEAD để xác minh rằng đó thực sự là một trang HTML trước khi tìm nạp đầy đủ.

Đây là những gì logic thu thập thông tin cốt lõi có thể kết hợp tất cả lại với nhau:

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

T Crawl trước tiên, phương pháp này sẽ kiểm tra phần mở rộng tệp của URL và bỏ qua phần mở rộng đó nếu nó nằm trong tập hợp băm các phần mở rộng không mong muốn. Sau đó, nó sẽ kiểm tra xem URL đã được truy cập chưa và nếu có thì bỏ qua nó. Tiếp theo, nó thực hiện yêu cầu HEAD và xác minh Kiểu nội dung là HTML trước khi thêm URL vào VisitedUrls hashset, tìm nạp đầy đủ nội dung và phân tích các liên kết để xếp hàng để thu thập thêm thông tin.

Được sử dụng cùng nhau như thế này, tính năng lọc tiện ích mở rộng và các yêu cầu HEAD cung cấp một cú đấm hiệu quả để bỏ qua nội dung không phải HTML trong khi thu thập thông tin. Kiểm tra tiện ích mở rộng là bộ lọc sơ bộ nhanh, trong khi yêu cầu HEAD là xác nhận cuối cùng trước khi cam kết tìm nạp toàn bộ trang.

Những cân nhắc khác và các phương pháp hay nhất

Ngoài việc lọc các URL không phải HTML, còn có một số điều quan trọng khác cần lưu ý khi xây dựng trình thu thập dữ liệu web hoạt động tốt và hiệu quả:

  • Luôn tôn trọng các quy tắc của robots.txt và không thu thập dữ liệu các trang không được phép. Bạn có thể phân tích cú pháp các tệp robots.txt và kiểm tra URL dựa trên chúng trước khi thu thập thông tin.

  • Giới hạn tốc độ thu thập dữ liệu và số lượng yêu cầu đồng thời để tránh làm máy chủ bị quá tải. Nguyên tắc tốt là không có nhiều hơn một yêu cầu mỗi giây cho mỗi tên miền.

  • Xử lý mã trạng thái HTTP, thời gian chờ và lỗi một cách khéo léo. Hãy thử lại những thất bại với mức độ lùi lại theo cấp số nhân và biết khi nào nên từ bỏ.

  • Theo dõi các URL đã truy cập bằng cách sử dụng bộ băm, cơ sở dữ liệu hoặc cấu trúc dữ liệu hiệu quả để tránh thu thập lại nội dung trùng lặp. Bộ lọc nở hoa là một lựa chọn tiết kiệm không gian.

Bằng cách làm theo những thực tiễn này và triển khai tính năng lọc chỉ HTML, bạn sẽ dần dần xây dựng được trình thu thập dữ liệu web lịch sự và tập trung bằng cách sử dụng C#. Các kỹ thuật được giải thích trong bài viết này sẽ cung cấp cho bạn tất cả những gì bạn cần để tránh nội dung không liên quan và tập trung vào các trang HTML mà bạn quan tâm.

Kết luận

Trình thu thập thông tin web là một công cụ mạnh mẽ để khám phá và phân tích nội dung trên trang web, nhưng để hiệu quả và lịch sự, điều quan trọng là chúng phải tập trung vào các trang HTML thực tế và bỏ qua các loại URL khác. Trong bài viết này, chúng ta đã học được hai kỹ thuật bổ sung để thực hiện điều đó trong trình thu thập thông tin C#:

  1. Lọc các phần mở rộng URL không mong muốn
  2. Kiểm tra tiêu đề Content-Type bằng yêu cầu HEAD

Chúng tôi đã hướng dẫn cách triển khai cả hai phương pháp đó và sau đó xem cách kết hợp chúng để có phạm vi bao phủ đầy đủ nhất. Chúng tôi cũng đã đề cập đến một số phương pháp hay nhất khác về trình thu thập thông tin như tôn trọng robots.txt và giới hạn tỷ lệ yêu cầu.

Hy vọng bây giờ bạn đã hiểu rõ về cách bỏ qua các URL không phải HTML một cách hiệu quả trong trình thu thập dữ liệu web của mình. Áp dụng các kỹ thuật này sẽ giúp trình thu thập thông tin của bạn nhanh và tập trung đồng thời tránh tải không cần thiết lên máy chủ.

Dưới đây là một số tài nguyên bổ sung mà bạn có thể muốn xem để tìm hiểu thêm:

Chúc mừng (chọn lọc) bò!

Tham gia vào cuộc đối thoại

Chúng tôi sẽ không công khai email của bạn. Các ô đánh dấu * là bắt buộc *