BIẾT A.I CHƯA?SELF HOSTING

Hướng dẫn toàn diện về Browserless – Công cụ tự động hóa trình duyệt

Browserless là một công cụ mã nguồn mở (open-source) tuyệt vời cho phép bạn chạy các trình duyệt headless (không giao diện) trong Docker. Nó hoạt động như một máy chủ độc lập, cho phép các ứng dụng Node.js của bạn kết nối và điều khiển trình duyệt thông qua WebSocket hoặc REST API.

Browserless hoạt động bằng cách:

  • Lắng nghe các kết nối WebSocket từ các thư viện như Puppeteer hoặc Playwright
  • Khởi động Chrome/Chromium và chuyển tiếp yêu cầu của bạn
  • Quản lý tự động các tác vụ như tải font, xử lý session, và giải phóng tài nguyên
  • Cung cấp REST API cho các tác vụ phổ biến (tạo PDF, chụp ảnh, lấy HTML)

Nói một cách đơn giản, Browserless giống như một dịch vụ web cho trình duyệt – bạn gửi yêu cầu, nó trả lại kết quả.

Lợi ích chính

Browserless mang lại nhiều lợi ích so với việc chạy Puppeteer trực tiếp:

  • Tách biệt cơ sở hạ tầng: Trình duyệt chạy riêng biệt, không phụ thuộc vào ứng dụng chính
  • Quản lý tài nguyên tốt hơn: Tự động queue các yêu cầu, kiểm soát số lượng session đồng thời
  • Hỗ trợ nhiều thư viện: Tương thích với Puppeteer, Playwright, và các thư viện khác
  • Dễ deploy: Chỉ cần chạy Docker image, không cần cấu hình phức tạp
  • Debugger tích hợp: Công cụ UI để theo dõi và gỡ lỗi các session hiện tại

Tại sao nên sử dụng Browserless

So sánh: Puppeteer trực tiếp vs. Browserless

Tiêu ChíPuppeteer Trực TiếpBrowserless
Cài đặtCần cài Chrome/PuppeteerChỉ Docker
Quản lý tài nguyênManualTự động
ScalingPhức tạpĐơn giản
Độc lậpGắn chặt với appHoàn toàn độc lập
DebuggerCơ bảnNâng cao với UI
REST APIKhông cóCó sẵn

Trường hợp sử dụng lý tưởng

Browserless là lựa chọn hoàn hảo cho:

  • Web scraping: Lấy dữ liệu từ các trang web có JavaScript
  • Kiểm thử tự động: Chạy các test E2E trên các trình duyệt
  • Sinh PDF: Chuyển đổi HTML thành PDF với định dạng đẹp
  • Chụp ảnh: Tạo screenshot tự động của trang web
  • Tự động hóa quy trình: Đăng nhập, điền form, nhấp button tự động

Yêu cầu hệ thống

Trước khi bắt đầu, hãy chắc chắn bạn có:

  1. Docker cài đặt (phiên bản 19.03 hoặc cao hơn)
    • Windows: Docker Desktop
    • macOS: Docker Desktop (hỗ trợ Apple Silicon M1/M2)
    • Linux: Docker Engine
  2. Node.js (phiên bản 14 hoặc cao hơn) – để chạy script Puppeteer
  3. RAM tối thiểu: 2GB (khuyến nghị 4GB trở lên)
  4. Không gian đĩa: 2-3GB cho Docker image

Kiểm tra xem Docker đã cài chưa bằng:

docker --version
node --version

Nếu chưa, có thể xem bài này: Hướng dẫn cài đặt Docker, Docker Compose trên Ubuntu

Cài đặt Browserless

Bước 1: Khởi động Docker Container

Lệnh cơ bản nhất để chạy Browserless:

docker run -p 3000:3000 ghcr.io/browserless/chromium

Điều này sẽ:

  • Tải image browserless/chromium từ GitHub Container Registry
  • Ánh xạ cổng 3000 bên trong container tới cổng 3000 trên máy host
  • Khởi chạy Browserless sẵn sàng nhận yêu cầu

Bước 2: Xác minh cài đặt

Mở trình duyệt và truy cập:

http://localhost:3000/docs

Bạn sẽ thấy trang OpenAPI với tài liệu API đầy đủ và UI để thử nghiệm các endpoint.

Bước 3: (Tùy chọn) Sử dụng Docker Compose

Để dễ quản lý, tạo file docker-compose.yml:

version: '3.8'

services:
  browserless:
    image: ghcr.io/browserless/chromium
    ports:
      - "3000:3000"
    environment:
      - TIMEOUT=30000
      - MAX_CONCURRENT_SESSIONS=5
    restart: unless-stopped

Sau đó chạy:

docker-compose up -d

Cấu hình và tùy chỉnh

Browserless có nhiều biến môi trường mà bạn có thể tùy chỉnh:

Các biến môi trường quan trọng

docker run -p 3000:3000 \
  -e PORT=3000 \
  -e TIMEOUT=30000 \
  -e MAX_CONCURRENT_SESSIONS=5 \
  -e ENABLE_CORS=true \
  -e TOKEN=your-secret-token \
  ghcr.io/browserless/chromium
BiếnMô TảMặc Định
PORTCổng nội bộ Browserless3000
TIMEOUTThời gian timeout cho mỗi session (ms)30000
MAX_CONCURRENT_SESSIONSSố lượng session đồng thời tối đa10
ENABLE_CORSKích hoạt CORStrue
TOKENToken xác thực API(không có)
DEBUGBật chế độ debugfalse

Ví dụ: Cấu hình cho Production

docker run -p 8080:3000 \
  -e PORT=3000 \
  -e TIMEOUT=60000 \
  -e MAX_CONCURRENT_SESSIONS=20 \
  -e TOKEN=abc123xyz789 \
  -e ENABLE_CORS=false \
  -m 2g \
  --restart always \
  ghcr.io/browserless/chromium

Giải thích:

  • -m 2g: Giới hạn bộ nhớ ở 2GB
  • --restart always: Tự động khởi động lại container nếu bị dừng
  • TOKEN: Yêu cầu xác thực cho tất cả các yêu cầu API
  • Timeout dài hơn cho các tác vụ phức tạp

Sử dụng với Puppeteer

Bước 1: Thiết lập dự án Node.js

Tạo thư mục mới và khởi tạo Node.js:

mkdir browserless-example
cd browserless-example
npm init -y

Bước 2: Cài đặt Puppeteer

npm install puppeteer

Bước 3: Tạo script kết nối tới Browserless

Thay vì chạy Puppeteer cục bộ, chúng ta sẽ kết nối tới Browserless server:

Cách cũ (Puppeteer Cục Bộ):

const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();

Cách mới (Với Browserless):

const puppeteer = require('puppeteer');

const browser = await puppeteer.connect({
  browserWSEndpoint: 'ws://localhost:3000',
});

Đó là tất cả! Chỉ thay đổi một dòng code.

Ví dụ thực tế

Ví dụ 1: Lấy tiêu đề trang web

Tạo file get-title.js:

const puppeteer = require('puppeteer');

async function getTitle() {
  const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://localhost:3000',
  });

  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { 
      waitUntil: 'networkidle2' 
    });

    const title = await page.title();
    console.log('Tiêu đề trang:', title);

  } catch (error) {
    console.error('Lỗi:', error);
  }
}

getTitle();

Chạy:

node get-title.js

Ví dụ 2: Chụp ảnh toàn trang

Tạo file screenshot.js:

const puppeteer = require('puppeteer');

async function takeScreenshot() {
  const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://localhost:3000',
  });

  try {
    const page = await browser.newPage();
    await page.setViewport({ width: 1280, height: 720 });
    await page.goto('https://example.com', { 
      waitUntil: 'networkidle2' 
    });

    await page.screenshot({ path: 'screenshot.png', fullPage: true });
    console.log('Chụp ảnh lưu tại: screenshot.png');

  } catch (error) {
    console.error('Lỗi:', error);
  }
}

takeScreenshot();

Ví dụ 3: Tạo file PDF

Tạo file generate-pdf.js:

const puppeteer = require('puppeteer');

async function generatePDF() {
  const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://localhost:3000',
  });

  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { 
      waitUntil: 'networkidle2' 
    });

    await page.pdf({ path: 'document.pdf', format: 'A4' });
    console.log('PDF được lưu tại: document.pdf');

  } catch (error) {
    console.error('Lỗi:', error);
  }
}

generatePDF();

Ví dụ 4: Web Scraping (Lấy dữ liệu)

Tạo file scrape.js:

const puppeteer = require('puppeteer');

async function scrapeData() {
  const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://localhost:3000',
  });

  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { 
      waitUntil: 'networkidle2' 
    });

    // Lấy tất cả các heading
    const headings = await page.$$eval('h1', elements => 
      elements.map(el => el.textContent)
    );

    console.log('Các tiêu đề tìm thấy:', headings);

  } catch (error) {
    console.error('Lỗi:', error);
  }
}

scrapeData();

Ví dụ 5: Đăng nhập và tự động hóa

Tạo file automate-login.js:

const puppeteer = require('puppeteer');

async function autoLogin() {
  const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://localhost:3000',
  });

  try {
    const page = await browser.newPage();
    await page.goto('https://example.com/login', { 
      waitUntil: 'networkidle2' 
    });

    // Điền email
    await page.type('input[name="email"]', '[email protected]');

    // Điền mật khẩu
    await page.type('input[name="password"]', 'password123');

    // Nhấp nút Login
    await Promise.all([
      page.click('button[type="submit"]'),
      page.waitForNavigation({ waitUntil: 'networkidle2' })
    ]);

    console.log('Đã đăng nhập thành công!');

    // Lấy dữ liệu sau khi đăng nhập
    const content = await page.content();
    console.log('Trang sau đăng nhập được tải');

  } catch (error) {
    console.error('Lỗi:', error);
  }
}

autoLogin();

Xử lý lỗi phổ biến

Lỗi 1: Không thể kết nối tới Browserless

Lỗi:

Error: connect ECONNREFUSED 127.0.0.1:3000

Nguyên Nhân: Container Docker không chạy hoặc cổng không đúng

Giải pháp:

# Kiểm tra container đang chạy
docker ps

# Nếu chưa chạy, khởi động lại
docker run -p 3000:3000 ghcr.io/browserless/chromium

Lỗi 2: Hết bộ nhớ (Out of Memory)

Lỗi:

Error: Cannot allocate memory

Giải pháp:

  • Giảm MAX_CONCURRENT_SESSIONS
  • Tăng RAM dành cho Docker
  • Đóng các trình duyệt không cần thiết
docker run -p 3000:3000 \
  -e MAX_CONCURRENT_SESSIONS=3 \
  -m 4g \
  ghcr.io/browserless/chromium

Lỗi 3: Timeout

Lỗi:

Error: Navigation timeout of 30000 ms exceeded

Giải pháp: Tăng timeout:

await page.goto('https://example.com', { 
  waitUntil: 'networkidle2',
  timeout: 60000  // 60 giây thay vì 30 giây
});

Lỗi 4: Session tạm dừng

Lỗi:

Error: Session exceeded max time

Giải pháp: Tăng biến TIMEOUT:

docker run -p 3000:3000 \
  -e TIMEOUT=60000 \
  ghcr.io/browserless/chromium

Mẹo tối ưu hóa

1. Sử dụng Connection Pooling

Tái sử dụng kết nối thay vì tạo mới mỗi lần:

let browser = null;

async function getBrowser() {
  if (!browser) {
    browser = await puppeteer.connect({
      browserWSEndpoint: 'ws://localhost:3000',
    });
  }
  return browser;
}

async function task1() {
  const browser = await getBrowser();
  const page = await browser.newPage();
  // ... công việc
  await page.close();  // Chỉ đóng page, không đóng browser
}

async function task2() {
  const browser = await getBrowser();
  const page = await browser.newPage();
  // ... công việc
  await page.close();
}

2. Đặt viewport cố định

Giảm bộ nhớ bằng cách giới hạn kích thước viewport:

await page.setViewport({ width: 1024, height: 768 });

3. Vô hiệu hóa hình ảnh

Tăng tốc độ bằng cách không tải hình ảnh:

await page.setRequestInterception(true);

page.on('request', (request) => {
  if (['image', 'stylesheet', 'font'].includes(request.resourceType())) {
    request.abort();
  } else {
    request.continue();
  }
});

4. Sử dụng Headless Mode thích hợp

Kiểm tra tài liệu Browserless để chọn image phù hợp:

# Chromium (nhẹ)
ghcr.io/browserless/chromium

# Chrome đầy đủ
ghcr.io/browserless/chrome

# Firefox
ghcr.io/browserless/firefox

# Tất cả các trình duyệt
ghcr.io/browserless/multi

5. Giám sát và logging

Bật debug mode để theo dõi hoạt động:

docker run -p 3000:3000 \
  -e DEBUG=true \
  ghcr.io/browserless/chromium

Câu hỏi thường gặp

Q: Browserless có miễn phí không?
A: Có, miễn phí cho mục đích không thương mại. Để sử dụng thương mại, bạn cần mua giấy phép.

Q: Tôi có thể sử dụng Playwright thay vì Puppeteer không?
A: Có, Browserless hỗ trợ cả Puppeteer và Playwright.

Q: Có thể chạy trên cloud không?
A: Có, Browserless có thể chạy trên bất kỳ nền tảng hỗ trợ Docker (AWS, Google Cloud, Azure, DigitalOcean, v.v.).

Q: Làm cách nào để giám sát hiệu suất?
A: Truy cập http://localhost:3000/docs để xem tài liệu API và trạng thái.


Browserless là công cụ tuyệt vời cho bất kỳ ai cần tự động hóa các tác vụ web. Nó cung cấp:

  • Sự linh hoạt: Chạy bất kỳ script Puppeteer/Playwright nào
  • Độ tin cậy: Quản lý tài nguyên tự động, không bị lỗi Chrome
  • Dễ triển khai: Chỉ cần Docker, không cần cấu hình phức tạp
  • Khả năng mở rộng: Hỗ trợ hàng loạt session đồng thời
  • Mã nguồn mở: Miễn phí cho mục đích không thương mại

Bước tiếp theo

  1. Cài đặt Browserless trên máy tính của bạn
  2. Thử các ví dụ trong bài viết này
  3. Khám phá tài liệu chính thức tại https://docs.browserless.io/
  4. Tham gia cộng đồng trên GitHub để nhận hỗ trợ
Duy Nghiện
Hãy làm khán giả, đừng làm nhân vật chính :)

You may also like

Nhận thông báo qua email
Nhận thông báo cho
guest

0 Bình luận
Mới nhất
Cũ nhất Nhiều like nhất
Phản hồi nội tuyến
Xem tất cả bình luận