Playwright là một framework mã nguồn mở dành cho kiểm thử web và tự động hóa. Được phát triển dựa trên Node.js và bởi Microsoft, nó hỗ trợ Chromium, Firefox và WebKit thông qua một API duy nhất. Playwright có thể hoạt động trên Windows, Linux và macOS, và tương thích với TypeScript, JavaScript, Python, .NET và Java.
Playwright không chỉ là một công cụ mà là một giải pháp toàn diện cho web scraping trong Node.js, kết hợp sức mạnh, sự linh hoạt và hiệu quả để đáp ứng các yêu cầu khắt khe nhất của tự động hóa web hiện đại.
Trong Node.js, chế độ headless trong Playwright là một lợi thế lớn. Nó cho phép bạn chạy trình duyệt mà không cần giao diện trực quan, tăng tốc quá trình scraping và phù hợp cho các nhiệm vụ quy mô lớn.
Playwright xử lý tốt các tương tác web phức tạp như tải nội dung động, quản lý đầu vào của người dùng và xử lý các hành động không đồng bộ. Điều này làm cho nó trở nên hoàn hảo để scraping dữ liệu từ các trang web hiện đại dựa nhiều vào JavaScript. Khả năng chặn và xử lý các yêu cầu mạng là một điểm mạnh khác. Nó cho phép bạn kiểm soát các yêu cầu và phản hồi, giúp vượt qua các biện pháp chống scraping và tinh chỉnh quy trình scraping của bạn.
Một điểm nổi bật nữa của Playwright là sự dễ dàng tích hợp vào các dự án Node.js. Bạn có thể tích hợp nó một cách trơn tru vào các quy trình làm việc hiện tại và sử dụng nó cùng với các thư viện JavaScript hoặc TypeScript khác. Ngoài ra, vì nó hoạt động trên Windows, Linux và macOS, bạn có thể triển khai các script scraping của mình trên các nền tảng khác nhau mà không gặp bất kỳ khó khăn nào.
Browserless là một dịch vụ trình duyệt không giao diện dựa trên đám mây được thiết kế bởi Nstbrowser để thực hiện các hoạt động web và các script tự động hóa mà không cần giao diện đồ họa.
Một trong những tính năng chính của Nstbrowserless là khả năng vượt qua các rào cản phổ biến như CAPTCHA và chặn IP, nhờ vào hệ thống Anti-detect, Web Unblocker và proxy thông minh được tích hợp sẵn. Những công cụ này đảm bảo rằng các script tự động hóa của bạn chạy mượt mà, ngay cả trên các trang web có các biện pháp bảo mật nghiêm ngặt.
Browserless hỗ trợ các cụm container đám mây, cho phép bạn mở rộng quy mô hoạt động một cách dễ dàng. Dù bạn đang chạy trên Windows, Linux hay macOS, nền tảng của chúng tôi cung cấp một giải pháp nhất quán và cấp doanh nghiệp cho tất cả các nhu cầu tự động hóa web của bạn. Nó được thiết kế để tích hợp một cách liền mạch vào các quy trình làm việc hiện có của bạn, cung cấp một môi trường mạnh mẽ và đáng tin cậy cho các hoạt động web hiệu suất cao.
Bạn có bất kỳ ý tưởng tuyệt vời hoặc nghi ngờ nào về web scraping và Browserless không?
Hãy xem những gì các nhà phát triển khác đang chia sẻ trên Discord và Telegram!

Trước tiên, hãy đảm bảo rằng Node.js đã được cài đặt trên hệ thống của bạn. Nếu chưa, hãy tải xuống và cài đặt phiên bản LTS. Sau đó, sử dụng npm, trình quản lý gói của Node.js, để cài đặt Playwright.
npm init playwright@latest
Thực hiện lệnh cài đặt và đưa ra các lựa chọn sau để bắt đầu:
test hoặc e2e nếu đã có thư mục kiểm thử).npx playwright install).Giống như một trình duyệt thông thường, Playwright cũng có thể hiển thị JavaScript, hình ảnh, v.v., vì vậy nó có thể trích xuất dữ liệu được tải động. Script khó bị phát hiện và chặn vì nó mô phỏng hành vi người dùng thông thường và khó nhận diện là một script tự động hóa.
import { chromium } from 'playwright';
const browser = await chromium.launch({ headless: false }); // Mở trình duyệt và tạo một tab mới
const page = await browser.newPage();
await page.goto('https://developer.chrome.com/'); // Truy cập URL đã chỉ định
await page.setViewportSize({ width: 1080, height: 1024 }); // Đặt kích thước viewport
console.log('[Trình duyệt đã mở!]');
Theo mặc định, Playwright hoạt động ở chế độ headless. Trong mã được cung cấp, chúng tôi tắt chế độ headless bằng cách đặt headless: false, cho phép bạn kiểm tra script của mình một cách trực quan. Bản demo và các ví dụ sau không cần các hàm async nhờ cài đặt "type": "module" trong package.json, cho phép thực thi ES module.
Chúng ta sẽ bắt đầu với một nhiệm vụ web scraping cơ bản để nhanh chóng làm quen với Playwright. Hãy trích xuất các đánh giá cho Apple AirPods Pro từ Amazon!
Việc web scraping hiệu quả bắt đầu với phân tích trang. Bạn cần xác định nơi dữ liệu bạn muốn trích xuất nằm ở đâu. Console debug của trình duyệt có thể giúp chúng ta rất nhiều:
Sau khi mở trang web, bạn cần mở console debug bằng cách nhấn Ctrl + Shift + I (Windows/Linux) hoặc Cmd + Option + I (Mac).

Playwright hỗ trợ nhiều phương pháp để chọn phần tử, nhưng sử dụng các selector CSS đơn giản thường là cách dễ nhất để bắt đầu. .devsite-search-field được sử dụng trước đó là một ví dụ về selector CSS.

Đối với các cấu trúc CSS phức tạp, console debug có thể sao chép trực tiếp các selector CSS. Nhấp chuột phải vào HTML của phần tử bạn muốn lấy, và mở menu > Sao chép > Sao chép selector.
Khi selector phần tử đã được xác định, chúng ta có thể sử dụng Playwright để cố gắng lấy tên người dùng mà tôi đã chọn ở trên.
import { chromium } from 'playwright'; // Bạn cũng có thể sử dụng 'firefox' hoặc 'webkit'
// Khởi chạy một phiên bản trình duyệt mới
const browser = await chromium.launch();
// Tạo một trang mới
const page = await browser.newPage();
// Điều hướng đến URL đã chỉ định
await page.goto('https://www.amazon.com/Apple-Generation-Cancelling-Transparency-Personalized/product-reviews/B0CHWRXH8B/ref=cm_cr_dp_d_show_all_btm?ie=UTF8&reviewerType=all_reviews');
// Chờ cho đến khi nút tải xong, tối đa 10 giây
await page.waitForSelector('div[data-hook="genome-widget"] .a-profile-name', { timeout: 10000 });
// Trích xuất tên người dùng
const username = await page.$eval('div[data-hook="genome-widget"] .a-profile-name', node
=> node.textContent);
console.log('[username]===>', username);
// Đóng trình duyệt
await browser.close();
Bạn có thể điều chỉnh mã để trích xuất nhiều hơn chỉ một tên người dùng, chẳng hạn như lấy một danh sách đầy đủ các bình luận:
page.waitForSelector để đảm bảo các phần tử đánh giá được tải đầy đủ.page.$$ để chọn tất cả các phần tử khớp với selector đã chỉ định.Sau đó, lặp qua danh sách các phần tử đánh giá và trích xuất thông tin cần thiết từ mỗi phần tử. Mã được cung cấp sẽ lấy tiêu đề, xếp hạng, tên người dùng, nội dung văn bản và thuộc tính data-src từ avatar, bao gồm URL của avatar.
Như đã minh họa, mã này:
page.goto để điều hướng đến trang mong muốn.waitForSelector để chờ cho đến khi nút mục tiêu được hiển thị đúng.page.$eval để lấy phần tử khớp đầu tiên và trích xuất các thuộc tính cụ thể thông qua một hàm callback.await page.waitForSelector('div[data-hook="review"]');
const reviewList = await page.$$('div[data-hook="review"]');
Tiếp theo, chúng ta cần duyệt qua danh sách các phần tử đánh giá và lấy thông tin cần thiết từ từng phần tử đánh giá.
Trong đoạn mã sau, chúng ta có thể lấy được tiêu đề, xếp hạng, tên người dùng và nội dung của bài đánh giá, cũng như giá trị thuộc tính data-src từ phần tử ảnh đại diện, tức là địa chỉ URL của ảnh đại diện.
for (const review of reviewList) {
const title = await review.$eval(
'a[data-hook="review-title"] > span:nth-of-type(2)',
node => node.textContent,
);
const rate = await review.$eval(
'i[data-hook="review-star-rating"] .a-icon-alt',
node => node.textContent,
);
const username = await review.$eval(
'div[data-hook="genome-widget"] .a-profile-name',
node => node.textContent,
);
const avatar = await review.$eval(
'div[data-hook="genome-widget"] .a-profile-avatar img',
node => node.getAttribute('data-src'),
);
const content = await review.$eval(
'span[data-hook="review-body"] span',
node => node.textContent,
);
console.log('[log]===>', { title, rate, username, avatar, content });
}
Sau khi chạy đoạn mã trên, bạn sẽ thấy đầu ra của thông tin nhật ký trong terminal.
Nếu bạn muốn lưu trữ dữ liệu này, bạn có thể sử dụng mô-đun Node.js cơ bản fs để ghi dữ liệu vào tệp JSON cho các phân tích dữ liệu sau này. Dưới đây là một hàm công cụ đơn giản:
import fs from 'fs';
// Lưu dưới dạng tệp JSON
function saveObjectToJson(obj, filename) {
const jsonString = JSON.stringify(obj, null, 2);
fs.writeFile(filename, jsonString, 'utf8', (err) => {
err ? console.error(err) : console.log(`Đã lưu tệp thành công: ${filename}`);
});
}
Mã hoàn chỉnh như sau. Sau khi chạy, bạn có thể tìm thấy tệp amazon_reviews_log.json trong đường dẫn thực thi của script hiện tại, trong đó ghi lại tất cả kết quả thu thập!
import { chromium } from 'playwright';
import fs from 'fs';
// Khởi chạy trình duyệt
const browser = await chromium.launch();
const page = await browser.newPage();
// Truy cập trang
await page.goto(
`https://www.amazon.com/Apple-Generation-Cancelling-Transparency-Personalized/product-reviews/B0CHWRXH8B/ref=cm_cr_dp_d_show_all_btm?ie=UTF8&reviewerType=all_reviews`
);
// Đợi phần tử đánh giá tải xong
await page.waitForSelector('div[data-hook="review"]');
// Lấy tất cả các phần tử đánh giá
const reviewList = await page.$$('div[data-hook="review"]');
const reviewLog = [];
// Duyệt qua danh sách phần tử đánh giá
for (const review of reviewList) {
const title = await review.$eval(
'a[data-hook="review-title"] > span:nth-of-type(2)',
node => node.textContent.trim()
);
const rate = await review.$eval(
'i[data-hook="review-star-rating"] .a-icon-alt',
node => node.textContent.trim()
);
const username = await review.$eval(
'div[data-hook="genome-widget"] .a-profile-name',
node => node.textContent.trim()
);
const avatar = await review.$eval(
'div[data-hook="genome-widget"] .a-profile-avatar img',
node => node.getAttribute('data-src')
);
const content = await review.$eval(
'span[data-hook="review-body"] span',
node => node.textContent.trim()
);
console.log('[log]===>', { title, rate, username, avatar, content });
reviewLog.push({ title, rate, username, avatar, content });
}
// Lưu dưới dạng tệp JSON
function saveObjectToJson(obj, filename) {
const jsonString = JSON.stringify(obj, null, 2);
fs.writeFile(filename, jsonString, 'utf8', (err) => {
err ? console.error(err) : console.log(`Đã lưu tệp thành công: ${filename}`);
});
}
saveObjectToJson(reviewLog, 'amazon_reviews_log.json');
await browser.close();
Nhấp vào một nút với page.click và đặt độ trễ để làm cho thao tác giống như con người hơn. Dưới đây là một ví dụ đơn giản.
import { chromium } from 'playwright'
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com/'); // Truy cập vào URL chỉ định
await page.waitForTimeout(3000)
await page.click('p > a', { delay: 200 })
Trong page.evaluate, rất tiện lợi để đặt vị trí của thanh cuộn bằng cách gọi API của Window. Page.evaluate là một API rất hữu ích:
import { chromium } from 'playwright'
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://www.nstbrowser.io/'); // Truy cập vào URL chỉ định
// Cuộn xuống cuối trang
await page.evaluate(() => {
window.scrollTo(0, document.documentElement.scrollHeight);
});
Để lấy nhiều phần tử, chúng ta có thể sử dụng page.$$eval, có thể lấy tất cả các phần tử phù hợp với bộ chọn chỉ định, và cuối cùng duyệt qua các phần tử này trong hàm callback để lấy các thuộc tính cụ thể.
import { chromium } from 'playwright'
// Khởi chạy trình duyệt
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com/');
await page.waitForSelector('.titleline > a')
// Lấy tiêu đề bài báo
const titles = await page.$$eval('.titleline > a', elements =>
elements.map(el => el.innerText)
);
// Xuất tiêu đề bài báo đã lấy
console.log('Tiêu đề bài báo:');
titles.forEach((title, index) => console.log(`${index + 1}: ${title}`));
Phương thức page.route được sử dụng để chặn các yêu cầu trên trang. '**/*' là ký tự đại diện, có nghĩa là khớp tất cả các yêu cầu. Sau đó, tất cả các yêu cầu có thể được xử lý trong hàm callback. Tham số route được sử dụng để đặt xem yêu cầu có được thực hiện bình thường hay bị gián đoạn, và cũng có thể được sử dụng để viết lại phản hồi.
import { chromium } from 'playwright'
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.route('**/*', (route) => {
const request = route.request();
// Chặn và chặn các yêu cầu phông chữ
if (request.url().includes('https://fonts.gstatic.com/')) {
route.fulfill({
status: 404,
contentType: 'image/x-icon',
body: ''
});
console.log('Yêu cầu biểu tượng đã bị chặn');
// Chặn và chặn các yêu cầu stylesheet
} else if (request.resourceType() === 'stylesheet') {
route.abort();
console.log('Yêu cầu stylesheet đã bị chặn');
// Chặn và chặn các yêu cầu hình ảnh
} else if (request.resourceType() === 'image') {
route.abort();
console.log('Yêu cầu hình ảnh đã bị chặn');
// Cho phép các yêu cầu khác tiếp tục
} else {
route.continue();
}
});
await page.goto('https://www.youtube.com/');
Playwright cung cấp một API chụp ảnh màn hình sẵn có, là một tính năng rất thực tế. Bạn có thể kiểm soát chất lượng của tệp ảnh chụp màn hình thông qua chất lượng và cắt ảnh thông qua clip. Nếu bạn có yêu cầu về tỷ lệ ảnh chụp màn hình, bạn có thể đặt viewport để đạt được điều đó.
import { chromium } from 'playwright';
const browser = await chromium.launch({ viewport: { width: 1920, height: 1080 } });
const page = await browser.newPage();
await page.goto('https://www.youtube.com/');
// Chụp toàn bộ trang
await page.screenshot({ path: 'screenshot1.png' });
// Chụp ảnh JPEG, đặt chất lượng thành 50
await page.screenshot({ path: 'screenshot2.jpeg', quality: 50 });
// Cắt ảnh, chỉ định khu vực cắt
await page.screenshot({ path: 'screenshot3.jpeg', clip: { x: 0, y: 0, width: 150, height: 150 } });
console.log('Ảnh chụp màn hình đã được lưu');
await browser.close();
Chắc chắn, bạn có thể thực hiện tất cả các tác vụ này bằng nhiều công cụ khác nhau. Ví dụ, RPA của Nstbrowser có thể tăng tốc quá trình quét web của bạn!
Bước 1. Truy cập Trang chủ của Nstbrowser, sau đó điều hướng đến RPA/Workflow > tạo workflow.

Bước 2. Khi bạn đang ở trang chỉnh sửa workflow, bạn có thể dễ dàng sao chép các chức năng trên bằng cách kéo và thả chuột.
Các Nodes bên trái bao gồm hầu hết các nhu cầu quét web và tự động hóa của bạn, và chúng tương thích chặt chẽ với API của Playwright.
Bạn có thể điều chỉnh thứ tự thực thi của các node này bằng cách liên kết chúng, tương tự như cách bạn thực thi mã JavaScript không đồng bộ. Nếu bạn đã quen thuộc với Playwright, bạn sẽ thấy việc sử dụng tính năng RPA của Nstbrowser trở nên dễ dàng—những gì bạn thấy là những gì bạn nhận được.

Bước 3. Mỗi Node có thể được cấu hình riêng lẻ, với các thiết lập tương tự như Playwright.





| Tiêu chí | Playwright | Puppeteer | Selenium |
|---|---|---|---|
| Hỗ trợ trình duyệt | Chromium, Firefox, và WebKit | Trình duyệt dựa trên Chromium | Chrome, Firefox, Safari, Internet Explorer, và Edge |
| Hỗ trợ ngôn ngữ | TypeScript, JavaScript, Python, .NET, và Java | Node.js | Java, Python, C#, JavaScript, Ruby, Perl, PHP, Typescript |
| Hệ điều hành | Windows, macOS, Linux | Windows và OS X | Windows, macOS, Linux, Solaris |
| Cộng đồng và Hệ sinh thái | Cộng đồng đang phát triển với sự hỗ trợ mạnh mẽ và phát triển liên tục bởi Microsoft | Được Google hỗ trợ với cộng đồng mạnh mẽ, đặc biệt dành cho những người tập trung vào Chromium | Cộng đồng lớn và hoạt động tích cực, cùng hệ sinh thái rộng lớn, bao gồm các plugin và tích hợp |
| Hỗ trợ tích hợp CI/CD | Có | Có | Có |
| Hỗ trợ Ghi lại và Phát lại | Trong bảng Điều khiển DevTools của Chrome | Playwright CodeGen | Selenium IDE |
| Khác biệt trong quét web | Với các tính năng hiện đại và tốc độ, tốt cho việc quét trên các trình duyệt khác nhau | Tuyệt vời trong Chrome và rất nhanh | Linh hoạt cho quét web nhưng có thể chậm hơn |
| Chế độ không đầu | Hỗ trợ chế độ không đầu cho tất cả các trình duyệt được hỗ trợ | Hỗ trợ chế độ không đầu nhưng chỉ dành cho các trình duyệt dựa trên Chromium | Hỗ trợ chế độ không đầu, nhưng việc triển khai khác nhau tùy thuộc vào trình điều khiển trình duyệt |
| Ảnh chụp màn hình | Hỗ trợ chụp ảnh PDF và hình ảnh, đặc biệt trong Chromium | Hỗ trợ chụp ảnh PDF và hình ảnh, dễ sử dụng | Không có tính năng chụp ảnh PDF tích hợp sẵn |
Playwright rất mạnh mẽ!
Nó cung cấp một bộ công cụ quét web mạnh mẽ và đa năng. Ngoài ra, tài liệu xuất sắc của Playwright và cộng đồng đang phát triển mang lại sự thuận tiện lớn cho các tác vụ tự động hóa của bạn.
Trong blog này, bạn đã có hiểu biết sâu hơn về Playwright:
Browserless của Nstbrowser đầy đủ các tính năng mạnh mẽ trong Docker. Bạn muốn giải phóng dung lượng lưu trữ và loại bỏ các hạn chế trên thiết bị địa phương? Hãy đạt được quản lý toàn bộ trên Đám mây với Nstbrowser ngay bây giờ!