Rate this post

Hướng dẫn triển khai workflow scraping web với Docker: n8n + FastAPI + Python + Puppeteer

Mục tiêu

  • Tạo một Docker image chứa:

    • n8n: để xây dựng workflow tự động.

    • FastAPI: để xây dựng API backend hỗ trợ scraping hoặc xử lý dữ liệu.

    • Python: để viết các đoạn script xử lý hoặc tương tác.

    • Puppeteer/Playwright: để scraping dữ liệu web sử dụng trình duyệt headless (Chromium).


⚙️ 1. Cài đặt công cụ cần thiết

Bạn cần cài sẵn:

  • Docker

  • Trình soạn thảo như VS Code


2. Tạo cấu trúc dự án


project-root/
│
├── Dockerfile
├── requirements.txt
├── docker-compose.yml
├── src/
│   ├── main.py             # FastAPI entrypoint
│   ├── scraper.py          # Puppeteer/playwright script
│   └── workflow_helper.py  # Các tool cho n8n

* Nội dung “docker-compose.yml”


version: '3.8'

services:
  app:
    build:
      context: .
    container_name: n8n_fastapi_app
    ports:
      - "5678:5678"   # n8n
      - "8000:8000"   # FastAPI
    volumes:
      - ./src:/app/src
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=admin123
      - N8N_HOST=localhost
      - N8N_PORT=5678
      - N8N_PROTOCOL=http
    depends_on:
      - postgres

  postgres:
    image: postgres:14
    container_name: n8n_postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: n8npass
      POSTGRES_DB: n8n

  # Optional: Add pgadmin if you want
  pgadmin:
    image: dpage/pgadmin4
    container_name: pgadmin
    ports:
      - "5050:80"
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@example.com
      PGADMIN_DEFAULT_PASSWORD: admin123

3. Viết Dockerfile


FROM node:20-bullseye-slim

RUN apt-get update && apt-get install -y \
    python3 python3-pip python3-venv \
    build-essential \
    curl \
    git \
    gnupg \
    ca-certificates \
    fonts-liberation \
    libappindicator3-1 \
    libasound2 \
    libatk-bridge2.0-0 \
    libatk1.0-0 \
    libcups2 \
    libdbus-1-3 \
    libgdk-pixbuf2.0-0 \
    libnspr4 \
    libnss3 \
    libx11-xcb1 \
    libxcomposite1 \
    libxdamage1 \
    libxrandr2 \
    xdg-utils \
    wget \
    && apt-get clean

# Chrome để Puppeteer hoạt động
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google.gpg && \
    sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list' && \
    apt-get update && \
    apt-get install -y google-chrome-stable

ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable

# Làm việc trong thư mục app
WORKDIR /app

# Cài Python packages
COPY requirements.txt .
RUN pip3 install --upgrade pip && pip3 install -r requirements.txt

# Cài n8n
RUN npm install --location=global n8n

# Copy mã nguồn FastAPI và scraper
COPY ./src ./src

# Mở port cho FastAPI và n8n
EXPOSE 5678 8000

# Chạy n8n và FastAPI song song
CMD ["sh", "-c", "n8n & uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload"]

4. Viết “requirements.txt”


fastapi
uvicorn[standard]
requests
beautifulsoup4
pydantic
httpx
playwright

Lưu ý: Dùng playwright thay cho puppeteer trong Python vì nó hiện đại hơn và hỗ trợ Chromium tốt hơn.

5. Tạo API FastAPI

File: src/main.py


from fastapi import FastAPI
from src.scraper import run_scraper

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "API is running"}

@app.get("/scrape")
def scrape(url: str):
    content = run_scraper(url)
    return {"url": url, "html": content}

6. Viết mã scraping với Playwright

File: src/scraper.py


from playwright.sync_api import sync_playwright

def run_scraper(url: str) -> str:
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(url, timeout=60000)
        content = page.content()
        browser.close()
        return content

* Viết mã “workflow_helper.py”


from bs4 import BeautifulSoup
import re

def extract_links(html: str) -> list:
    """Trích xuất toàn bộ liên kết (href) từ HTML"""
    soup = BeautifulSoup(html, "html.parser")
    links = [a['href'] for a in soup.find_all('a', href=True)]
    return links

def extract_text_by_tag(html: str, tag: str) -> list:
    """Trích xuất nội dung văn bản theo tag (ví dụ: p, h1)"""
    soup = BeautifulSoup(html, "html.parser")
    return [el.get_text(strip=True) for el in soup.find_all(tag)]

def clean_html(html: str) -> str:
    """Xoá hết thẻ HTML, chỉ giữ nội dung văn bản"""
    soup = BeautifulSoup(html, "html.parser")
    return soup.get_text(separator=' ', strip=True)

def find_emails(text: str) -> list:
    """Tìm địa chỉ email trong văn bản"""
    pattern = r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+'
    return re.findall(pattern, text)

* Viết mã “scraper.py”


from playwright.sync_api import sync_playwright

def run_scraper(url: str) -> str:
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(url)
        content = page.content()
        browser.close()
        return content

* Viết mã “main.py”


from fastapi import FastAPI
from src.scraper import run_scraper
from src.workflow_helper import extract_links, clean_html

app = FastAPI()

@app.get("/")
def read_root():
    return {"status": "running"}

@app.get("/scrape")
def scrape(url: str):
    data = run_scraper(url)
    return {"data": data}

@app.post("/parse/links")
def parse_links_from_html(data: dict):
    html = data.get("html", "")
    return {"links": extract_links(html)}

@app.post("/parse/text")
def parse_text(data: dict):
    html = data.get("html", "")
    return {"text": clean_html(html)}

7. Build và chạy Docker container

✅ Build image:

Mở CMD từ folder chứa file hoặc Teminal trong Docker.Desktop:
docker-compose build

8. Truy cập hệ thống

  • http://localhost:5678: Giao diện n8n

  • http://localhost:8000: FastAPI Docs (OpenAPI)

  • http://localhost:8000/scrape?url=https://example.com: Test scraping


⚙️ 9. Kết nối n8n với API

Trong n8n, bạn có thể dùng node HTTP Request để gọi API scraping:

  • Method: GET

  • URL: http://localhost:8000/scrape?url=https://example.com

  • Sau đó xử lý html trả về bằng các node khác (Code, Function, Google Sheets,…)


✅ Tổng kết

Bạn đã có một môi trường all-in-one để:

  • Viết các API xử lý scraping bằng Python (FastAPI + Playwright).

  • Tự động hóa scraping bằng workflow của n8n.

  • Dễ dàng deploy với Docker.

Thông tin liên quan:

SẢN PHẨM HOT TẠI RainbowTechVN:

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *