[P1] Tìm hiểu Headless browser & Puppeteer
This post hasn't been updated for 3 years
Dạo gần đây mình có mày mò cách lấy dữ liệu từ các trang báo: 24h, dantri ... Qua đó mình cũng biết thêm được những khái niệm mới (đối với mình): Headless browser
, Puppeteer
. Vậy chúng là cái gì & sử dụng ra sao
1. Headless browser là gì
Headless Browser là một trình duyệt web không có giao diện đồ họa người dùng. Các headless browser cung cấp tương tác tự động một trang web trong một môi trường giống như các trình duyệt web phổ biến khác, nhưng nó được thực hiện thông qua giao diện dòng lệnh hoặc qua một mạng truyền thông. Chúng đặc biệt hữu ích cho việc kiểm thử các trang web vì chúng có thể hiển thị và hiểu HTML giống như các trình duyệt thông thường, bao gồm các cả styling như bố cục trang, màu sắc, font chữ và thực thi Javascript và AJAX mà thường không có sẵn khi sử dụng các phương pháp kiểm thử khác.
1.1: Trường hợp sử dụng
- Kiểm tra tự động hóa trong các ứng dụng web hiện đại.
- Chụp ảnh màn hình của các trang web.
- Chạy các bài kiểm tra tự động cho các thư viện JavaScript.
- Scrape các trang web cho dữ liệu.
- Tự động tương tác của các trang web.
2. Puppeteer là gì
Puppeteer
là một bộ thư viện của Nodejs, giúp bạn điều khiển headless Chrome.
Những gì mà bạn làm được bằng giao diện người dùng trên Chrome thì bạn đều có thể làm bằng Puppeteer
- Chụp màn hình và lưu lại thành file ảnh hoặc PDF
- Lấy dữ liệu từ website cho dù site đó bắt ta phải login hay dùng AJAX để load data
- Tự động submit form, UI testing, keyboard input ...
- Tạo ra môi trường automated testing. Chạy trực tiếp test của bạn trên phiên bản Chrome mới nhất
- Chụp lại
timeline trace
site của bạn để giúp cho việc chẩn đoán những vấn đề về hiện năng
2.1: Cài đặt
yarn add puppeteer
# or "npm i puppeteer"
Lưu ý: Khi bạn cài đặt
Puppeteer
, nó sẽ download về phiên bản chromium mới nhất (~71Mb Mac, ~90Mb Linux, ~110Mb Win)
Puppeteer
yêu cầu Nodejs v6.4.0 trở lên. Nhưng code mình chủ yếu dùng async/await nên Nodejs của bạn cần phải từ v7.6.0 trở lên. Như mình thì mình xài v9.4.2
2.2: Chụp màn hình
Ta sẽ di chuyển đến trang 24h.com.vn
và chụp lại ảnh mnaf hình rồi lưu lại với tên 24h.png
// file 24h.js
const puppeteer = require('puppeteer');
(async () => {
// mở trình duyệt
const browser = await puppeteer.launch({ headless: false });
// Mở 1 page mới
const page = await browser.newPage();
// đi đến trang 24h
await page.goto('https://24h.com.vn');
// chụp ảnh màn hình và lưu lại với tên 24h.png
await page.screenshot({path: '24h.png'});
// Lưu ảnh màn hình thành file pdf
await page.pdf({path: 'hn.pdf', format: 'A4'});
// tắt trình duyệt
await browser.close();
})();
Run command node 24h.js
& đây là kết quả
Trình duyệt mới sẽ được bật lên. Bạn để í thì đây không phải là chrome nhé mà chính là Chromium lúc nãy ta download về
Để ẩn trình duyệt này thì ta bỏ tham số { headless: false }
Còn nếu bạn muốn bật trình duyệt lên để debug hoặc xem cho vui thì ta có thể set kích thước cho nó bằng cách
page.setViewport({width: 1280, height: 720});
2.3: Chạy js trong browser
Nếu chỉ có mỗi chụp màn hình thì chắc hẳn puppeteer
này cũng không có gì đặc sắc. evaluate
là hàm quan trọng nhất của thằng này
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://24h.com.vn');
// Get the "viewport" of the page, as reported by the page.
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio
};
});
console.log('Dimensions:', dimensions);
await browser.close();
})();
Ở ví dụ trên ta lấy kích thước của website, mình có thể dùng js thuần để lấy dữ liệu của page đó & trả về qua return
rồi lưu vào db
3. Thủ thuật debug
- Tắt chế độ headless - chế độ này rất hữu dụng, ta có thể nhìn xem browser hiển thị & hoạt động có đúng í muốn của ta không. Thay vì chỉ debug trên console, ta có thể xem toàn bộ browser bằng cách sử dụng
headless: false
const browser = await puppeteer.launch({headless: false});
- Giảm tốc độ -
slowMo
cho phép giảm tốc độ củaPuppeteer
xuống bằng cách chỉ định số mili giây. Đây là một cách khác giúp ta xem chuyện gì sẽ xảy ra với code của chúng ta
const browser = await puppeteer.launch({
headless: false,
slowMo: 250 // slow down by 250ms
});
- Chụp lại
console
- Bạn có thể lắng nghe sự kiệnconsole
. Thử chạy đoạn code sau xem sao nhé
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
await page.evaluate(() => console.log(`url is ${location.href}`));
- Bật chế độ
verbose logging
- Tất cả các API công khai & nội bộ được gọi thì sẽ đều được ghi log thông qua chế độdebug
với namespace làpuppeteer
# Basic verbose logging
env DEBUG="puppeteer:*" node script.js
# Debug output can be enabled/disabled by namespace
env DEBUG="puppeteer:*,-puppeteer:protocol" node script.js # everything BUT protocol messages
env DEBUG="puppeteer:session" node script.js # protocol session messages (protocol messages to targets)
env DEBUG="puppeteer:mouse,puppeteer:keyboard" node script.js # only Mouse and Keyboard API calls
# Protocol traffic can be rather noisy. This example filters out all Network domain messages
env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
3. Kết luận
Vậy là mình đã giới thiệu qua khái niệm & một vài kiến thức cơ bản về thằng puppeteer
rồi
Ở phần sau mình sẽ dùng thằng này để lấy ảnh/dữ liệu từ 1 trang web thực tế nhé
Tài liệu tham khảo
https://github.com/GoogleChrome/puppeteer https://puppetron.now.sh/ https://try-puppeteer.appspot.com/ https://www.google.com.vn/url?sa=t&rct=j&q=&esrc=s&source=web&cd=6&cad=rja&uact=8&ved=0ahUKEwjwsZ7z3PDYAhXMj5QKHSNRCCoQFghPMAU&url=https%3A%2F%2Fdevelopers.google.com%2Fweb%2Ftools%2Fpuppeteer%2F&usg=AOvVaw0rJATETQwoWYIKhQzPIcM0
All Rights Reserved