Thu Thập Dữ liệu Trang Web (Web Scraping) với PUPPETEER
Khi cần dữ liệu của 1 trang web nào đó, trang web đó có thể cung cấp API cho ta kết xuất thông tin ở dạng JSON. Nhưng trong nhiều trường hợp, nếu không có API thì ta phải đi cào dữ liệu từ trang bằng cách mở Google Dev Tools và code qq gì đó lấy thông tin ở các element trong trang và có trích xuất được dữ liệu. Có khá nhiều công cụ phục vụ cho việc scraping, tùy theo ngôn ngữ bạn sử dụng. Trong bài viết này mình sẽ giới thiệu Puppeteer, một thư viện của Nodejs.
Một số kiến thức bạn cần có trước khi bắt đầu:
+ Javascript, Nodejs
+ Async await trong Javascript
+ Render được 1 trang html đơn giản (có thể sử dụng Pugjs) (có thể biết sau cũng được)
Đầu tiên, chúng ta tạo một project để test nhé (Lưu ý đặt tên khác Puppeteer (tên package) vì khi lưu vào file Package.json sẽ báo lỗi đấy)
+ Mở cửa sổ cmd tại folder project, gõ lệnh npm init: tạo file package.json lưu thông tin project, các module sử dụng...
+ Gõ npm install puppeteer --save
Bước thiết lập project hoàn tất, chúng ta bắt đầu với file index.js và gõ đoạn lệnh chạy thử, bật tab terminal trên IDE để xem các câu lệnh được console.log()
const puppeteer = require('puppeteer'); // add thư viện puppeteer
(async() => {
// Mở một browser ảo để lấy thông tin
const browser = await puppeteer.launch({headless: false});
console.log('Browser opened');
// Mở một trang có địa chỉ url và đi đến trang web đó
const page = await browser.newPage();
const url = 'https://www.DAMDANG.vn';
await page.goto(url);
console.log('Page loaded');
// set viewport cho browser ảo đó, méo quan trọng lắm
await page.setViewport({ width: 1920, height: 1080 });
// Thực thi lệnh blabla, thu thập dữ liệu trang web
// Đóng browser
await browser.close();
})();
* Các bạn nhớ kiểm tra kĩ và hiểu đoạn code trên nhé, kẻo lỗi...
* Cái {headless: false} sẽ bật lên một brower ảo. Mặc định sẽ là true, tức là không có brower nào được bật lên trên màn hình, nhưng brower đó vẫn được chạy ngầm.
Ví dụ ở bài này mình sử dụng trang thống kê top 100 channel youtube nhiều subscribes nhất: url = "https://vn.noxinfluencer.com/youtube-channel-rank/top-100-vn-all-youtuber-sorted-by-subs-weekly"
Giờ chúng ta vào trang trên, mở Dev Tool (ctrl + shift + I) để xem cấu trúc các element như thế nào.
Ví dụ mình muốn lấy ảnh các channel youtube chẳng hạn, ta thấy rằng nó là 1 thẻ img (với các attribute class='avatar', src="...") nằm trong thẻ td (class='profile'). Để đơn giản trên cửa sổ terminal, chúng ta sẽ console.log() các src đó ra.
Chúng ta sẽ test tại tab Console của Developer Tool (tại trang web thống kê có url trên), paste đoạn lệnh này:
// chọn các node là thẻ img(class='avatar') nằm trong thẻ td(class='profile')
let avatars = document.querySelectorAll('td.profile img.avatar');
// chuyển danh sách node thành 1 mảng (100 phần tử ứng với top 100 channel)
avatars = [...avatars];
// Có thể chuyển sang một mảng mới, với các phần tử là 1 object với key là src
let channel = avatars.map((avatar) => ({
src: avatar.getAttribute('src'),
}));
// In ra để xem có cl gì nhé
console.log(channel);
Test nhanh trên tab Console thành công, bạn có thể paste đoạn lệnh trên vào file index.js rồi chạy câu lệnh 'node index.js'...
const puppeteer = require('puppeteer'); // add thư viện puppeteer
(async() => {
// Mở một browser ảo để lấy thông tin
const browser = await puppeteer.launch({headless: false});
console.log('Browser opened');
// Mở một trang có địa chỉ url và đi đến trang web đó
const page = await browser.newPage();
const url = 'https://vn.noxinfluencer.com/youtube-channel-rank/top-100-vn-all-youtuber-sorted-by-subs-weekly';
await page.goto(url);
console.log('Page loaded');
// set viewport cho browser ảo đó, méo quan trọng lắm
await page.setViewport({ width: 1920, height: 1080 });
var channels = page.evaluate() => {
let avatars = document.querySelectorAll('td.profile img.avatar');
avatars = [...avatars];
let channels = avatars.map((avatar) => ({
src: avatar.getAttribute('src'),
}));
return channels;
}
console.log(channels);
// Đóng browser
await browser.close();
})();
Không chỉ lấy một thuộc tính như trên mà ta có thể lấy nhiều thông tin hơn đặt cho nó các thuộc tính khác nhau và render ra 1 trang html hay đơn giản như mình làm demo sương sương thế này...
Ngoài ra còn rất nhiều phương thức khác của Puppeteer mà bạn có thể tham khảo tại link github: https://github.com/puppeteer/puppeteer
Happy Hacking!
Người viết: Minh Thắng
[…] AJAX để tương tác với người dùng. Lúc này bạn có thể nghĩ tới việc dùng puppeteer thay vì cheerio mà bài viết trước team mình đã đề […]
Trả lờiXóa