12 KiB
n8n-nodes-scrapling
Community node dla n8n integrujący bibliotekę Scrapling — szybki, adaptacyjny scraper stron internetowych z obsługą zwykłego HTTP, trybu stealth (TLS fingerprint impersonation) oraz pełnej przeglądarki Playwright.
Architektura
n8n (Node.js / TypeScript)
│
│ HTTP POST /scrape
▼
Scrapling Service (Python / FastAPI)
│
├── Fetcher — szybkie żądania HTTP
├── StealthyFetcher — impersonacja TLS (curl-impersonate)
└── PlayWrightFetcher — pełna przeglądarka Chromium
n8n node komunikuje się z Scrapling Service przez HTTP. Serwis Python zarządza instancjami scraperów i zwraca ustrukturyzowane JSON.
Wymagania
| Komponent | Wersja |
|---|---|
| n8n | ≥ 1.0 |
| Node.js | ≥ 18 |
| Python | ≥ 3.11 |
| Docker | opcjonalnie |
Instalacja
Opcja A — Docker Compose (zalecana)
Uruchamia n8n oraz Scrapling Service w jednym poleceniu.
# Skopiuj i uzupełnij zmienne środowiskowe
cp .env.test.example .env
# Zbuduj i uruchom
docker compose up -d
n8n dostępne pod adresem: http://localhost:5678
Scrapling Service: http://localhost:8765
Opcja B — Ręczna instalacja
1. Zainstaluj zależności n8n node:
npm install
npm run build
2. Zainstaluj serwis Python:
cd service
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/scrapling install # pobiera przeglądarki Playwright
3. Uruchom serwis:
.venv/bin/uvicorn service.main:app --host 0.0.0.0 --port 8765
4. Zainstaluj node w n8n:
Skopiuj katalog dist/ do katalogu community nodes n8n:
# Domyślna ścieżka dla n8n instalowanego przez npm
cp -r dist ~/.n8n/nodes/node_modules/n8n-nodes-scrapling
Następnie zrestartuj n8n.
Konfiguracja credentials
W n8n dodaj nowy credential typu Scrapling API:
| Pole | Opis | Domyślnie |
|---|---|---|
| Service URL | URL Scrapling Service (bez trailing slash) | http://localhost:8765 |
| API Key | Opcjonalny klucz autoryzacyjny (header X-API-Key) |
(puste) |
Jeśli API_KEY w serwisie jest pusty, autoryzacja jest wyłączona.
Użycie node
Resource: Page
Służy do pobierania całych stron. Zwraca URL, status HTTP, czas pobierania i (opcjonalnie) surowy HTML.
Operacje
| Operacja | Fetcher | Opis |
|---|---|---|
| Fetch | Fetcher |
Szybkie żądanie HTTP. Najszybsza opcja dla statycznych stron. |
| Fetch Stealth | StealthyFetcher |
Impersonacja TLS (curl-impersonate). Omija podstawowe anti-bot. |
| Fetch Dynamic | PlayWrightFetcher |
Pełna przeglądarka Chromium (Playwright). Dla SPA i stron wymagających JS. |
Przykładowy output:
{
"url": "https://example.com",
"status_code": 200,
"html": "<html>...</html>",
"data": {},
"fetcher_used": "http",
"elapsed_ms": 312.5
}
Resource: Data
Służy do ekstrakcji ustrukturyzowanych danych z pobranych stron.
Operacje
| Operacja | Opis |
|---|---|
| Extract | Pobiera stronę i wyciąga dane za pomocą selektorów CSS lub XPath. |
| Extract Tables | Pobiera stronę i zwraca wszystkie tabele HTML jako tablice JSON. |
Konfiguracja selektorów (Extract)
Każdy selektor definiuje pole w wyjściowym obiekcie data:
| Pole | Opis |
|---|---|
| Field Name | Nazwa klucza w wyjściowym JSON |
| Selector | Wyrażenie CSS lub XPath, np. h1.title lub //h1[@class="title"] |
| Type | css lub xpath |
| Attribute | Atrybut HTML do pobrania (np. href, src). Puste = tekst. |
| Return Multiple | Zwróć tablicę wszystkich pasujących elementów |
Przykładowy output dla Extract:
{
"url": "https://news.ycombinator.com",
"status_code": 200,
"data": {
"titles": ["Show HN: ...", "Ask HN: ...", "..."],
"top_link": "https://..."
},
"fetcher_used": "http",
"elapsed_ms": 187.2
}
Opcje wspólne
| Opcja | Opis | Domyślnie |
|---|---|---|
| Return Raw HTML | Dołącz surowy HTML do odpowiedzi | false |
| Timeout (ms) | Maksymalny czas żądania (1000–120000 ms) | 30000 |
| Proxy | URL proxy, np. http://user:pass@proxy.example.com:8080 |
(puste) |
| Extra Headers | Dodatkowe nagłówki HTTP jako JSON, np. {"Accept-Language": "pl"} |
{} |
| Wait for Selector | CSS selector, na który czeka Playwright przed ekstrakcją | (puste) |
| Wait for Network Idle | Czekaj na zakończenie aktywności sieciowej (Playwright) | false |
| Headless Browser | Uruchom Playwright bez GUI | true |
Opcje Wait for Selector, Wait for Network Idle i Headless Browser działają tylko z fetcherem
dynamic.
CLI Runner
Do testowania bez uruchamiania n8n:
# Podstawowe użycie
npx ts-node scripts/scrapling-run.ts https://example.com
# Tryb stealth
npx ts-node scripts/scrapling-run.ts https://example.com --fetcher stealth
# Ekstrakcja danych
npx ts-node scripts/scrapling-run.ts https://news.ycombinator.com \
--selector "titles:.titleline a" \
--fetcher http \
--format json
# Playwright — czekaj na element
npx ts-node scripts/scrapling-run.ts https://spa.example.com \
--fetcher dynamic \
--wait "#content" \
--html
# Lub przez Taskfile
task scrape URL=https://example.com FETCHER=stealth
task scrape:dynamic URL=https://spa.example.com
Credentials CLI pobiera z pliku .env.test lub zmiennych środowiskowych:
SCRAPLING_SERVICE_URL=http://localhost:8765
SCRAPLING_API_KEY= # opcjonalnie
Taskfile
| Task | Opis |
|---|---|
task setup |
Instalacja npm + kopiowanie .env.test.example |
task build |
Kompilacja TypeScript → dist/ |
task dev |
Watch mode |
task test |
Uruchom testy jednostkowe |
task test:coverage |
Testy z raportem pokrycia |
task lint |
ESLint |
task check |
Lint + test (pre-push) |
task service:install |
Instalacja serwisu Python w .venv |
task service:start |
Start serwisu na porcie 8765 |
task service:health |
Sprawdź health endpoint |
task scrape |
CLI scraper [URL=...] [FETCHER=...] [FORMAT=...] |
task scrape:stealth |
Scrape w trybie stealth |
task scrape:dynamic |
Scrape z przeglądarką |
task docker:up |
Start Docker Compose (n8n + serwis) |
task docker:down |
Stop Docker Compose |
task docker:logs |
Tail logów |
API Scrapling Service
POST /scrape
Pobiera stronę i opcjonalnie ekstrahuje dane.
Request body:
{
"url": "https://example.com",
"fetcher_type": "http",
"selectors": [
{
"name": "title",
"selector": "h1",
"selector_type": "css",
"attribute": null,
"multiple": false
}
],
"return_html": false,
"timeout": 30000,
"proxy": null,
"headers": {},
"wait_selector": null,
"network_idle": false,
"headless": true
}
Response:
{
"url": "https://example.com",
"status_code": 200,
"html": null,
"data": {
"title": "Example Domain"
},
"fetcher_used": "http",
"elapsed_ms": 245.3,
"error": null
}
W przypadku błędu serwis zwraca HTTP 200 z wypełnionym polem error (zamiast rzucać wyjątek) — pozwala to n8n obsłużyć błąd przez opcję Continue On Fail.
GET /health
{
"status": "ok",
"version": "0.1.0",
"dynamic_session_ready": true
}
Autoryzacja: jeśli zmienna API_KEY jest ustawiona w serwisie, każdy request do /scrape wymaga nagłówka X-API-Key.
Zmienne środowiskowe
Scrapling Service
| Zmienna | Opis | Domyślnie |
|---|---|---|
API_KEY |
Klucz API do autoryzacji requestów | (puste — wyłączone) |
Docker Compose
| Zmienna | Opis | Domyślnie |
|---|---|---|
SCRAPLING_API_KEY |
API key serwisu (przekazywany) | (puste) |
N8N_USER |
Login do n8n basic auth | admin |
N8N_PASSWORD |
Hasło do n8n basic auth | changeme |
Struktura projektu
scrapling_n8n/
├── src/
│ ├── credentials/
│ │ └── ScraplingApi.credentials.ts # Credentials: serviceUrl + apiKey
│ └── nodes/Scrapling/
│ ├── Scrapling.node.ts # Główny node n8n
│ ├── helpers.ts # HTTP client + typy
│ ├── scrapling.svg # Ikona node
│ └── __tests__/
│ ├── helpers.test.ts # Testy helpera
│ └── Scrapling.node.test.ts # Testy node (z mock)
├── service/ # Python FastAPI microservice
│ ├── main.py # Entry point + autoryzacja
│ ├── routers/
│ │ ├── scrape.py # POST /scrape
│ │ └── health.py # GET /health
│ ├── scrapers/
│ │ ├── base.py # Abstrakcja + apply_selectors()
│ │ ├── fetcher.py # Wrapper Fetcher
│ │ ├── stealthy.py # Wrapper StealthyFetcher
│ │ └── dynamic.py # Wrapper PlayWrightFetcher
│ ├── models/
│ │ ├── request.py # Pydantic ScrapeRequest
│ │ └── response.py # Pydantic ScrapeResponse
│ ├── pyproject.toml # Zależności Python
│ └── Dockerfile
├── scripts/
│ └── scrapling-run.ts # CLI runner (bez n8n)
├── dist/ # Skompilowany JS (po npm run build)
├── docker-compose.yml
├── package.json
├── tsconfig.json
├── jest.config.js
├── Taskfile.yml
└── .env.test.example
Rozwój
# Instalacja
task setup
# Tryb watch (TypeScript)
task dev
# Testy
task test
task test:coverage
# Lint
task lint
# Uruchomienie serwisu lokalnie
task service:install
task service:start
# Szybki test end-to-end
task scrape URL=https://httpbin.org/html
Licencja
MIT