Crawl Data (Trích xuất dữ liệu) Website với C# Phần 1
By Harry Wynn
4.6k views
1 likes
0 comments
4/10 rate
Crawl Data hiểu đơn giản là chúng ta đi thu thập dữ liệu từ các nguồn khác nhau trên các trang web.
Và với thời buổi hiện tại dữ liệu là cực kì lớn, việc thu thập dữ liệu từ đó cũng ngày càng tăng. Và việc của chúng ta là làm sao thu thập được đống dữ liệu khổng lồ đó?
Đối với các website lớn như Shoppe, Tiki, Google,... chúng ta có thể sử dụng các API do họ cung cấp để lấy dữ liệu.
Nhưng thử đặt ví dụ bạn vào web bán hàng cụ thể là "Web bán đồng hồ" và bạn muốn lấy thông tin các sản phẩm của web đó NHƯNG khổ cái là website này không có API? Vậy phải làm sao? Bạn sẽ mở trang web lên, copy dữ liệu vào file word, excel v…v? Cách làm này thật điên rồ và giải pháp duy nhất cho chuyện này là viết một tool trích xuất dữ liệu từ website đó.
Vậy làm sao để viết ra một tool crawl data từ website về? Thì sau đây mình sẽ hướng dẫn các bạn làm điều đó.
#Source Code ở cuối bài nhé
Về chức năng của tool sẽ có 2 chức năng là:
Trang web mình sẽ Crawl đó là fridayshopping.vn một website bán đồng hồ nhé các bạn.
B1. Tạo một project Console App với Visual Code
Các bước tiếp theo các bạn điền tên Project rồi cứ bấm next nhé ...
B2. Cài các Nuget cần thiết
Bước này chúng ta sẽ tiến hành cài đặt các Nuget Packages sau:
Về chức năng của từng Nuget mình sẽ nói ở phần dưới
B3. Phân tích mã nguồn HTML của Website
Các bạn vào đường link https://fridayshopping.vn sẽ thấy giao diện như sau:
Các bạn chú ý phần Header thấy ở đây có các bộ lọc chính gồm lọc theo Thương Hiệu, Đồng Hồ Nam, Đồng Hồ Nữ...
Và trong phạm vi bài này mình sẽ Crawl hết tất cả đồng hồ từ 2 mục Đồng Hồ Nam và Đồng Hồ Nữ.
Khi nhấn vào 2 đường dẫn này chúng ta thu được 2 URL sau:
Chúng ta thấy 2 phần hiển thị danh sách các sản phẩm hoàn toàn giống nhau. Chỉ có URL của chúng là khác nhau một chút, một cái là nam và một cái là nu.
Các bạn kéo xuống cuối trang sẽ thấy phần phân trang của sản phẩm.
Đối với Đồng Hồ Nam có 6 trang, Đồng Hồ Nữ có 5 trang.
Thử click vào trang thứ 2 chúng ta sẽ thu về được một URL có dạng sau:
Từ đây suy ra để có thể Crawl hết các sản phẩm của shop ta sẽ Crawl ở các URL:
Bắt đầu xem HTML của trang. Ở đây mình sẽ Crawl các thông tin của sản phẩm bao gồm:
Sử dụng Developer Tool của Chrome (Nhấn F12). Các bạn sẽ thấy tất cả các sản phẩm đều nằm trong thẻ div với class là shop-container => div class = products và các sản thông tin của sản phẩm nằm trong thẻ div có class là product-small
Và tất cả các thông tin của sản phẩm chúng ta muốn Crawl về đều nằm trong này cụ thể:
B4: Parse dữ liệu
Trước khi code, mình xin giới thiệu 1 số object, method của các Nuget đã cài ở trên mà các bạn nên biết:
1. HtmlAgilityPack
Đây là Nuget chính để lấy thông tin từ Website để Crawl
2. Fizzler.Systems.HtmlAgilityPack
Fizzler được mở rộng dựa trên HTMLAgilityPath, thêm 2 hàm sau vào HTMLNode:
Fizzler hỗ trợ CSS Selector, cho phép ta sử dụng selector của CSS để select Node cho HTMLAgilityPath. Cho các bạn nào chưa biết về CSS Selector có thể VÀO ĐÂY để đọc thêm nhé.
3. EPPlus
Nuget hỗ trợ đọc xuất file trong C#
OK. Sau khi đã hiểu được phần trên (Không hiểu cũng không sao đọc code dễ hiểu hơn 😂) chúng ta vào Code chính nào:
// URL website need to crawl
// Đường dẫn trang web cần crawl
const string baseUrl = "https://fridayshopping.vn";
// Create new instance
// Tạo một instance mới
var web = new HtmlWeb()
{
AutoDetectEncoding = false,
OverrideEncoding = Encoding.UTF8
};
// List gender for product
// List giới tính cho 2 site Đồng Hồ Nữ và Đồng Hồ Nam
var genders = new List() { "nam", "nu" };
// List product crawl
// List lưu danh sách các sản phẩm Crawl được
var listDataExport = new List();
// Loop for 2 gender
// Lặp List gender
foreach (var gender in genders)
{
var requestUrl = baseUrl + $"/kieu-dang/{gender}";
// Load HTML to document from requestUrl
// Load trang web, nạp html vào document từ requestUrl
var documentForGetTotalPageMale = web.Load(requestUrl);
// Get total page from requestUrl
// Lấy tổng số trang từ requestUrl
var textTotalPage = documentForGetTotalPageMale
.DocumentNode
.QuerySelectorAll(".page-numbers > li")
.ToList()
.Where(s => !string.IsNullOrEmpty(s.InnerText))
.ToList()
.Last()
.InnerText
.RemoveBreakLineTab();
int totalPage;
int.TryParse(textTotalPage, out totalPage);
// Loop each page
// Lặp qua từng trang
for (var i = 1; i <= totalPage; i++)
{
var requestPerPage = baseUrl + $"/{gender}/page/{i}";
// Load HTML to document from requestPerPage
// Load trang web, nạp html vào document từ requestPerPage
var documentForListItem = web.Load(requestPerPage);
// Get all Node Product
// Lấy tất cả các Node chứa thông tin của sản phẩm
var listNodeProductItem = documentForListItem
.DocumentNode
.QuerySelectorAll("div.shop-container " +
"> div.products " +
"> div.product-small " +
"> div.col-inner " +
"> div.product-small " +
"> div.box-text")
.ToList();
// Loop for each Node
// Lặp qua các Node
foreach (var node in listNodeProductItem)
{
// Get Link Detail of Product
// Lấy Link chi tiết của sản phẩm
var linkDetail = node
.QuerySelector("div.title-wrapper > p.name > a")
.Attributes["href"]
.Value
.RemoveBreakLineTab();
// Get Product Name
// Lấy tên của sản phẩm
var productName = node
.QuerySelector("div.title-wrapper")
.InnerText
.RemoveBreakLineTab();
// Get Product Price includes Orgin Price and Discount Price
// Lấy giá của sản phẩm bao gồm giá gốc và giá khuyển mãi
var priceText = node
.QuerySelector("div.price-wrapper > span.price")
.InnerText
.RemoveBreakLineTab()
.ReplaceMultiToEmpty(new List() { "₫", "," });
var priceList = priceText?.Split(" ").ToList();
// Parse text to price and format
var orginPrice = priceList?.Count > 0 ? double.Parse(priceList[0]).ToString("N2") : 0.ToString("N2");
var discountPrice = priceList?.Count > 0 ? double.Parse(priceList[1]).ToString("N2") : 0.ToString("N2");
// Add Product to listDataExport
// Thêm sản phẩm vào listDataExport
listDataExport.Add(new ProductModel()
{
ProductName = productName,
Gender = gender.Equals("nam") ? "Nam" : "Nữ",
Currency = "VND",
DiscountPrice = discountPrice,
OrginPrice = orginPrice,
LinkDetail = linkDetail,
Author = "https://www.code-mega.com"
});
}
}
}
// Export data to Excel
ExportToExcel.GenerateExcel(listDataExport, savePathExcel + fileName, "Code Mega");
Và đây là kết quả được lưu lại sau khi Crawl xong. Ở đây mình lưu vào Excel, các bạn cũng có thể lưu xuống bất kì đâu bạn muốn như Database
Vậy là xong rồi. Bạn cũng có thể sử dụng thư viện này để Crawl Data từ các trang web khác mà bạn muốn. Lưu ý là thư viện này sẽ không áp dụng được cho các web sử dụng JS để chạy Front End như React, Angular, VueJS,...
Hi vọng bài viết này có thể giúp ích được cho các bạn!