Phiên bản: 2.0
Ngày cập nhật: 2025
Kiến trúc: Flow-Based Architecture
CrawlFlow 2.0 sử dụng Flow-Based Architecture - một kiến trúc mới hoàn toàn dựa trên visual flow để xác định quy trình crawl và xử lý dữ liệu. Thay vì sử dụng cấu trúc cũ (Tooth, Reception, Parser, FeedItem), hệ thống mới sử dụng các nodes và edges để xây dựng flow xử lý dữ liệu.
┌─────────────────────────────────────────────────────────────┐
│ CRAWFLOW FLOW │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ START │─────▶│ PROCESS │─────▶│COMPLETION│ │
│ │ NODE │ │ NODES │ │ NODE │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────┐ │
│ │ │EXTRACTOR │ │
│ │ │ NODES │ │
│ │ └──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ │
│ │REPOSITORY│◀─────│ WORKER │ │
│ │ NODE │ │ NODE │ │
│ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Mục đích: Entry point của flow, định nghĩa nguồn dữ liệu ban đầu
Types:
Output: URLs hoặc data items
Rake Mapping: Thay thế Tooth initialization, định nghĩa data source
Mục đích: Collect và lưu trữ tạm thời URLs/resources từ Start nodes
Features:
Output: Repository với collection of resources
Rake Mapping: Tương đương Resource collection trong Rake
Mục đích: Thực hiện click actions để navigate
Settings:
Input: URL từ Start hoặc Repository Output: URLs sau khi click/navigate
Rake Mapping: Navigation logic trong Tooth
Mục đích: Iterate qua một list of elements
Settings:
Input: URL với HTML content Output: Multiple URLs hoặc data items (một cho mỗi element)
Rake Mapping: Iterator logic trong Parser
Mục đích: Filter và validate URLs/resources trước khi vào Repository
Settings:
Input: URLs từ Start hoặc Click nodes Output: Filtered URLs
Rake Mapping: Tương đương ReceptionManager trong Rake cũ
Mục đích: Detect và process specific pages/resources
Settings:
Input: Repository (URLs) Output: Trigger Extractor nodes
Rake Mapping: ResourceWorker trong Rake cũ
Mục đích: Extract structured data từ content
Types:
Input: Content từ Worker node Output: Structured data items
Rake Mapping: Tương đương ParserManager và FeedItemBuilderManager
Mục đích: Process và output extracted data
Types:
Input: Extracted data từ Extractor nodes Output: Processed results
Rake Mapping: Tương đương ProcessorManager
Mục đích: End point của flow, đánh dấu flow hoàn thành
Features:
Mục đích: Diagram elements để visualize flow structure
Types: Rectangle, Circle, Ellipse, Frame, Package
Note: Không tham gia vào flow execution, chỉ để visualization
┌─────────────────────────────────────────────────────────┐
│ FLOW EXECUTION PIPELINE │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. INITIALIZATION │
│ ├─ Load flow configuration │
│ ├─ Validate flow integrity │
│ └─ Initialize Flow Engine │
│ │
│ 2. START PHASE │
│ ├─ Execute Start Nodes │
│ ├─ Collect URLs/resources │
│ └─ Populate Repository │
│ │
│ 3. RECEPTION PHASE │
│ ├─ Apply Reception Rules │
│ ├─ Filter URLs │
│ └─ Update Repository │
│ │
│ 4. NAVIGATION PHASE │
│ ├─ Execute Click Nodes │
│ ├─ Execute Loop Nodes │
│ └─ Collect new URLs │
│ │
│ 5. WORKER PHASE │
│ ├─ Worker detects matching resources │
│ ├─ Trigger Extractor Nodes │
│ └─ Extract data │
│ │
│ 6. PROCESSING PHASE │
│ ├─ Execute Processor Nodes │
│ ├─ Save/Transform data │
│ └─ Generate outputs │
│ │
│ 7. COMPLETION │
│ ├─ Cleanup resources │
│ ├─ Generate reports │
│ └─ Update flow status │
│ │
└─────────────────────────────────────────────────────────┘
Start Node
│
├─ URLs ────────────────────┐
│ │
▼ ▼
Reception Node Click/Loop Node
│ │
├─ Filtered URLs ───────────┤
│ │
▼ ▼
Repository ─────────────────────┘
│
▼
Worker Node
│
├─ Detect matching ─────────┐
│ │
▼ ▼
Extractor Node ────────────────┐
│ │
├─ Extracted Data ──────────┤
│ │
▼ ▼
Processor Node
│
▼
Completion Node
[
'id' => string,
'url' => string,
'type' => 'html' | 'api' | 'file',
'content' => string | array,
'metadata' => array,
'source_node_id' => string,
'timestamp' => datetime
]
[
'id' => string,
'resource_id' => string,
'data' => array, // Structured data
'extractor_id' => string,
'timestamp' => datetime
]
[
'id' => string,
'data_item_id' => string,
'processor_id' => string,
'status' => 'success' | 'failed',
'result' => mixed,
'timestamp' => datetime
]
| Rake Component | Flow Node | Notes |
|---|---|---|
| Tooth | Start Node | Entry point định nghĩa data source |
| ReceptionManager | Reception Node | Filter rules |
| ParserManager | Extractor Nodes | Parse content thành structured data |
| FeedItemBuilderManager | Extractor Nodes | Build data items |
| FeedItemManager | Repository Node | Manage collected items |
| ProcessorManager | Processor Node | Process data |
| ResourceWorker | Worker Node | Detect và process resources |
| Resource | Repository Node | Resource collection |
$tooth = new Tooth();
$tooth->registerReception($receptionRules);
$tooth->registerParser($parserRules);
$tooth->registerProcessor($processorRules);
{
"nodes": [
{
"id": "start-1",
"type": "start",
"data": {
"sourceType": "url",
"sourceValue": "https://example.com",
"urlSettings": { ... }
}
},
{
"id": "reception-1",
"type": "reception",
"data": {
"rules": [ ... ],
"logic": "and"
}
},
{
"id": "worker-1",
"type": "worker",
"data": {
"detectionRules": [ ... ],
"detectionLogic": "and"
}
},
{
"id": "extractor-1",
"type": "html-data-extractor",
"data": {
"customRules": [ ... ]
}
},
{
"id": "processor-1",
"type": "processor",
"data": {
"processorType": "save-to-database",
"settings": { ... }
}
}
],
"edges": [
{ "source": "start-1", "target": "reception-1" },
{ "source": "reception-1", "target": "repository-node" },
{ "source": "repository-node", "target": "worker-1" },
{ "source": "worker-1", "target": "extractor-1" },
{ "source": "extractor-1", "target": "processor-1" }
]
}
Hệ thống mới vẫn có thể load và convert configurations cũ:
class FlowExecutor
{
public function execute(FlowConfig $flow): ExecutionResult
{
// 1. Initialize
$context = new ExecutionContext($flow);
// 2. Execute Start nodes
$this->executeStartNodes($context);
// 3. Execute Reception nodes
$this->executeReceptionNodes($context);
// 4. Execute Navigation nodes
$this->executeNavigationNodes($context);
// 5. Execute Worker nodes
$this->executeWorkerNodes($context);
// 6. Execute Extractor nodes
$this->executeExtractorNodes($context);
// 7. Execute Processor nodes
$this->executeProcessorNodes($context);
// 8. Complete
$this->complete($context);
return $context->getResult();
}
}
interface NodeExecutorInterface
{
public function execute(NodeConfig $node, ExecutionContext $context): NodeResult;
public function supports(string $nodeType): bool;
}
class NodeRegistry
{
private array $executors = [];
public function register(string $nodeType, NodeExecutorInterface $executor): void
{
$this->executors[$nodeType] = $executor;
}
public function getExecutor(string $nodeType): NodeExecutorInterface
{
if (!isset($this->executors[$nodeType])) {
throw new NodeExecutorNotFoundException($nodeType);
}
return $this->executors[$nodeType];
}
}
Flow-Based Architecture mang lại sự linh hoạt và mạnh mẽ cho CrawlFlow 2.0. Thay vì bị giới hạn bởi cấu trúc cũ (Tooth, Reception, Parser), giờ đây users có thể tạo bất kỳ workflow nào họ muốn thông qua visual editor.
Hệ thống mới vẫn tương thích với Rake framework core (HttpClient, DatabaseDriver, EventBus) nhưng sử dụng flow-based approach để orchestrate các components này.