Haystack pipeline tài liệu web: tách fetch, parse và export
Haystack pipeline tài liệu web là cách ghép các component của Haystack thành một chuỗi xử lý: tải trang, chuyển HTML thành tài liệu, lọc tài liệu kém chất lượng và ghi kết quả ra tệp. Mỗi component có cổng vào và cổng ra với kiểu dữ liệu khai báo rõ, gọi là socket. Pipeline kiểm kiểu khi nối, chạy theo đồ thị và dừng khi một component lỗi. ProxyVN dựng một pipeline năm component với haystack-ai 3.4.1 ngày 03/11/2026, chạy trên máy chủ fixture cục bộ, rồi cố ý làm hỏng từng phần để xem pipeline phản ứng ra sao.
Haystack pipeline tài liệu web: mục tiêu và phạm vi không lặp
Phần đầu chốt bài toán, đầu ra và những gì bài không làm.
Bài toán
Một nhóm cần lấy nội dung vài chục trang tài liệu công khai, làm sạch và lưu ra tệp JSONL để đội khác dùng tiếp. Họ đã có code viết liền một khối: vòng lặp tải trang, gọi thư viện trích nội dung, lọc, ghi tệp. Code chạy được, nhưng mỗi lần có trang lỗi thì không ai biết trang đó rơi ở bước nào.
Haystack tách việc này thành component riêng, mỗi component một trách nhiệm. Câu hỏi của bài là tách như thế nào để biết chính xác trang nào đi qua bước nào, và khi một bước hỏng thì phần còn lại của pipeline ra sao.
Đầu ra nghiệm thu
Đầu ra gồm ba thứ. Một là đồ thị pipeline ở dạng danh sách kết nối và tệp YAML. Hai là fixture gồm các trang có nội dung, trang chỉ có menu và trang 404. Ba là ma trận kết quả: với mỗi URL, component nào đã xử lý, component nào loại, và lỗi nào làm pipeline dừng.
Ranh giới với các bài gần
Bài không dựng RAG, không dùng vector store hay retriever, không gọi model ngôn ngữ. Đã có bài về LlamaIndex cho nhu cầu đọc web rồi đưa vào chỉ mục, đọc ở bài LlamaIndex web scraping. Bài này chỉ bàn tầng tải và xử lý: hợp đồng dữ liệu giữa các component và đường đi của dữ liệu khi có lỗi.
Giới hạn của phép thử
Mọi kết quả trong bài đến từ lab chạy thật trên Windows với Python 3.12.10. Website nguồn là máy chủ http.server cục bộ trên cổng 9521, không gửi request nào ra Internet. Lab không đo hiệu năng với hàng nghìn trang, không thử AsyncPipeline và không vẽ đồ thị bằng dịch vụ Mermaid trực tuyến.
Ai nên đọc
Người đã dùng Haystack cho tìm kiếm hay hỏi đáp và muốn dùng lại khung pipeline cho việc thu thập tài liệu. Người viết component riêng và chưa chắc về cách khai báo kiểu đầu ra. Người cần giải thích cho đội vận hành vì sao một URL có trong danh sách đầu vào mà không có trong tệp kết quả.
Tách component tải web và xử lý trong Haystack pipeline tài liệu web
Phần này giải thích khái niệm theo tài liệu và cách chia việc.
Pipeline và component theo tài liệu
Trang Pipelines của Haystack mô tả pipeline là đồ thị có hướng các component. Mỗi component nhận dữ liệu từ socket đầu vào, xử lý và trả dữ liệu ra socket đầu ra. Pipeline có thể rẽ nhánh, gộp nhánh và chạy vòng lặp. Khi nối hai component, Haystack kiểm kiểu của socket gửi và socket nhận.
Haystack 3 và code mẫu cũ
Bản cài trong lab là haystack-ai 3.4.1. Nhiều bài hướng dẫn trên mạng viết cho bản 1.x với tên gói farm-haystack, hoặc cho bản 2.x. Bản 1.x dùng khái niệm node và cách nối khác hẳn. Khi đọc code mẫu, kiểm tên gói và cách import trước. Code dùng from haystack import component và Pipeline.connect theo dạng tên.socket là cách viết của các bản mới.
Lab không so sánh giữa các bản. Mọi hành vi ghi trong bài đúng cho 3.4.1 trên máy lab, có thể khác ở bản khác.
Năm component của lab
Pipeline lab gồm năm component. fetch là LinkContentFetcher có sẵn, nhận danh sách URL và trả danh sách ByteStream. parse là HTMLToDocument có sẵn, chuyển ByteStream thành Document. gate là component tự viết, chia tài liệu thành nhánh đạt và nhánh loại theo độ dài nội dung. export là component tự viết, ghi nhánh đạt ra JSONL. rejects là component tự viết, ghi lại URL của nhánh loại.
Vì sao tách fetch khỏi parse
Tải mạng và xử lý nội dung có hai kiểu lỗi khác hẳn nhau. Tải có thể lỗi do mạng, do máy chủ trả 404 hay quá thời gian. Xử lý có thể lỗi do HTML lạ, mã hóa sai hay trang không có nội dung chính. Tách ra, ta biết lỗi thuộc về đâu, và có thể chạy lại phần xử lý trên dữ liệu đã tải mà không tải lại.
Tách cũng cho phép thay từng phần. Hôm nay parse dùng HTMLToDocument, mai đổi sang một trình trích khác, fetch và export không phải sửa.
Vì sao có component gate
Không phải trang nào tải được cũng có nội dung. Trang render bằng JavaScript thường chỉ trả khung rỗng với menu. Không có gate, những tài liệu rỗng này đi thẳng vào tệp kết quả và làm nhiễu dữ liệu phía sau. gate biến việc lọc thành một bước có tên, có ngưỡng và có đầu ra riêng cho phần bị loại.
Nhánh loại cũng là đầu ra
Một lỗi thiết kế hay gặp là chỉ giữ nhánh đạt. Khi đó tài liệu bị loại biến mất không dấu vết. Lab nối nhánh rejected vào component rejects, để mỗi lần chạy đều có danh sách URL bị loại. Danh sách này là thứ đội vận hành cần nhất khi điều tra.
Chia component fetch, parse và export với socket đầu vào/ra trong Haystack pipeline tài liệu web
Phần này là code các component tự viết.
Phiên bản lab
Thành phần |
Phiên bản |
|---|---|
Python |
3.12.10, venv riêng, Windows 10 |
haystack-ai |
3.4.1 |
trafilatura |
2.3.1 |
lxml |
6.1.3 |
Component gate
from haystack import component, Document
@component
class QualityGate:
def __init__(self, min_chars: int = 120):
self.min_chars = min_chars
@component.output_types(passed=list[Document], rejected=list[Document])
def run(self, documents: list[Document]):
ok, bad = [], []
for d in documents:
n = len(d.content or "")
d.meta["content_chars"] = n
(ok if n >= self.min_chars else bad).append(d)
return {"passed": ok, "rejected": bad}
Decorator component đăng ký lớp với Haystack. Tham số của phương thức run trở thành socket đầu vào, ở đây là documents với kiểu danh sách Document. Decorator output_types khai báo hai socket đầu ra passed và rejected. Giá trị trả về là dict có đúng hai khóa này.
Component export
import json, hashlib, datetime
from pathlib import Path
@component
class JsonlExporter:
def __init__(self, path: str):
self.path = path
@component.output_types(path=str, count=int)
def run(self, documents: list[Document]):
p = Path(self.path)
with p.open("w", encoding="utf-8") as f:
for d in documents:
f.write(json.dumps({"url": d.meta.get("url"), "chars": d.meta.get("content_chars"),
"sha1": hashlib.sha1((d.content or "").encode()).hexdigest()[:12],
"exported_at": datetime.datetime.now().isoformat(timespec="seconds")},
ensure_ascii=False) + "\n")
return {"path": str(p), "count": len(documents)}
export trả về đường dẫn và số dòng, để người gọi pipeline biết kết quả nằm đâu mà không phải đoán. Bản trong lab còn ghi trường title, nhưng trường này luôn null, lý do nằm ở phần sau.
Component không nên giữ trạng thái giữa các lần chạy
Mỗi lần pipeline.run, component có thể được gọi lại trên cùng một đối tượng. Nếu component lưu danh sách vào thuộc tính của lớp và cộng dồn, lần chạy thứ hai sẽ thấy dữ liệu của lần đầu. Các component trong lab chỉ dùng biến cục bộ trong run, và trả mọi thứ qua giá trị trả về.
Ngoại lệ hợp lý là tài nguyên dùng lại như kết nối cơ sở dữ liệu. Những thứ đó nên mở trong warm_up và đóng trong close, theo vòng đời mà Pipeline đã có sẵn phương thức gọi.
Component rejects
rejects nhận danh sách Document và trả danh sách URL lấy từ meta. Component này ngắn, nhưng nó biến nhánh loại thành một đầu ra của pipeline. Khi gọi pipeline.outputs, Haystack liệt kê hai đầu ra cuối: export với path và count, rejects với urls.
Cấu hình nằm ở init, dữ liệu nằm ở run
Ngưỡng min_chars và đường dẫn tệp là tham số khởi tạo. Danh sách tài liệu là tham số của run. Quy ước này giúp pipeline được lưu ra YAML với cấu hình đầy đủ, và dữ liệu chỉ truyền vào lúc chạy. Không nên để đường dẫn tệp đầu ra là tham số của run nếu nó cố định cho mỗi lần triển khai.
LinkContentFetcher và tham số của nó
LinkContentFetcher trong bản 3.4.1 nhận raise_on_failure mặc định True, user_agents, retry_attempts mặc định 2, timeout mặc định 3 giây, http2, client_kwargs và request_headers. Lab đặt raise_on_failure False, retry_attempts 0 và timeout 2 để lỗi hiện ra nhanh và không thử lại trên fixture.
HTMLToDocument dùng trafilatura
HTMLToDocument dựa trên trafilatura để trích nội dung chính. Nó nhận sources là danh sách ByteStream hoặc đường dẫn, kèm meta và extraction_kwargs tùy chọn. Khi gọi pipeline.inputs, Haystack liệt kê meta và extraction_kwargs của parse là đầu vào không bắt buộc, còn urls của fetch là đầu vào bắt buộc.
Nối component và kiểm kiểu dữ liệu truyền qua Haystack pipeline tài liệu web
Phần này đi qua bước nối và lỗi kiểu.
Lệnh nối pipeline
from haystack import Pipeline
from haystack.components.fetchers import LinkContentFetcher
from haystack.components.converters import HTMLToDocument
p = Pipeline()
p.add_component("fetch", LinkContentFetcher(raise_on_failure=False, retry_attempts=0, timeout=2))
p.add_component("parse", HTMLToDocument())
p.add_component("gate", QualityGate(min_chars=120))
p.add_component("export", JsonlExporter("out.jsonl"))
p.add_component("rejects", RejectLog())
p.connect("fetch.streams", "parse.sources")
p.connect("parse.documents", "gate.documents")
p.connect("gate.passed", "export.documents")
p.connect("gate.rejected", "rejects.documents")
Mỗi lệnh connect ghi tên component, dấu chấm và tên socket. Khi component chỉ có một socket phù hợp, có thể bỏ tên socket, nhưng ghi rõ giúp đọc code dễ hơn.
Lỗi kiểu khi nối sai

Socket và kiểu
Lab thử nối thẳng fetch.streams vào export.documents, bỏ qua bước parse. Haystack báo PipelineConnectError ngay ở lệnh connect, trước khi chạy. Thông báo nói không nối được vì kiểu khai báo của đầu vào và đầu ra không khớp, kèm danh sách socket: fetch có streams kiểu danh sách ByteStream, export có documents kiểu danh sách Document.
Lỗi bị bắt lúc dựng pipeline, không phải lúc chạy với dữ liệu thật. Đây là lợi ích lớn nhất của việc khai báo kiểu cho socket: sai hợp đồng giữa hai bước lộ ra ngay khi lắp ráp.
Kiểu khai báo là hợp đồng, không phải kiểm tra dữ liệu
Haystack kiểm kiểu của socket, không kiểm nội dung. Một danh sách Document rỗng hay chứa tài liệu toàn menu vẫn hợp lệ về kiểu. Vì vậy cần gate để kiểm nội dung. Hai lớp kiểm tra bổ sung cho nhau: connect bắt sai cấu trúc, gate bắt sai chất lượng.
Đồ thị pipeline ở dạng dữ liệu
pipeline.to_dict trả về khóa connections là danh sách cặp sender, receiver. Lab in ra bốn kết nối: fetch.streams tới parse.sources, parse.documents tới gate.documents, gate.passed tới export.documents, gate.rejected tới rejects.documents. pipeline.dumps ghi toàn bộ pipeline ra YAML, gồm lớp và tham số khởi tạo của từng component.
Lưu tệp YAML cạnh mã nguồn. Khi so hai phiên bản pipeline, so tệp YAML cho thấy ngay component nào đổi tham số hay kết nối nào mới thêm.
Kiểm đầu vào trước khi chạy
Pipeline có phương thức validate_input, kiểm dữ liệu truyền vào run có đủ đầu vào bắt buộc không. Gọi run thiếu urls cho fetch sẽ bị báo lỗi trước khi component nào chạy. Kết hợp với kiểm kiểu lúc connect, hai lớp này bắt phần lớn lỗi lắp ráp trước khi tốn một request mạng nào.
Vẽ đồ thị
Pipeline có phương thức show và draw để vẽ đồ thị. Theo mã nguồn bản 3.4.1, hai phương thức này mặc định gửi định nghĩa đồ thị tới một máy chủ Mermaid để render. Lab không gọi vì không muốn gửi cấu trúc pipeline ra ngoài. Danh sách connections và tệp YAML đủ để vẽ tay hoặc dựng máy chủ Mermaid nội bộ.
Cho một component lỗi để xem nhánh xử lý của Haystack pipeline tài liệu web dừng ở đâu
Phần này là ba phép thử lỗi chính.
Fixture
Máy chủ http.server trên 127.0.0.1 cổng 9521 có bốn URL. /a và /b là trang bài viết có thẻ nav, article và footer. /empty là trang chỉ có menu, một thẻ div rỗng và một đoạn script, mô phỏng trang render bằng JavaScript. /khong-co trả 404.
Lần chạy bình thường
Chạy pipeline với bốn URL và yêu cầu giữ đầu ra của fetch, parse, gate. fetch trả bốn ByteStream: /a 605 byte, /b 528 byte, /empty 135 byte, /khong-co 0 byte. parse trả ba Document: /a 426 ký tự, /b 360 ký tự, /empty 19 ký tự. gate cho /a và /b vào nhánh đạt, /empty vào nhánh loại. export ghi 2 dòng, rejects trả một URL là /empty.
Lần chạy đầu tiên mất 2,37 giây, lần sau 0,84 giây. Chênh lệch chủ yếu do nạp thư viện lần đầu, không phải do mạng. Con số chỉ để tham khảo, không phải đo hiệu năng.
URL 404 biến mất không dấu vết

URL 404 biến mất
Đây là phát hiện quan trọng nhất của lab. Với raise_on_failure False, URL /khong-co trả về một ByteStream rỗng, meta chỉ có content_type text/html và url. Không có mã trạng thái 404 trong meta. HTMLToDocument ghi một dòng cảnh báo rằng ByteStream rỗng bị bỏ qua.
Kết quả cuối cùng: /khong-co không có trong export, cũng không có trong rejects. Ai chỉ đọc đầu ra pipeline sẽ thấy ba URL được xử lý trên bốn URL đầu vào, mà không có dòng nào nói URL thứ tư đi đâu. Chỉ log cảnh báo của parse còn lưu dấu.
Vì sao không có mã trạng thái
ByteStream là kiểu dữ liệu chung cho mọi loại nội dung nhị phân, không riêng cho HTTP. Meta của nó do component tạo ra quyết định. LinkContentFetcher bản 3.4.1 ghi url và content_type, và khi tải lỗi với raise_on_failure False thì tạo ByteStream rỗng với cùng meta. Thông tin về lỗi chỉ nằm trong log của fetcher, không nằm trong dữ liệu đi tiếp.
Thiết kế này hợp lý cho trường hợp muốn pipeline chạy tiếp bất chấp lỗi lẻ tẻ. Nó không hợp khi cần kiểm toán từng URL. Biết trước hành vi này thì tự bổ sung được, không biết thì sẽ mất dữ liệu mà không hay.
Cách vá: đối chiếu đầu vào với đầu ra
Cách đơn giản nhất là đối chiếu sau khi chạy: tập URL đầu vào trừ tập URL trong export và rejects. Phần còn lại là URL rơi mất ở fetch hoặc parse. Lab tính ra đúng một URL, /khong-co.
Cách chặt hơn là viết một component kiểm tra ngay sau fetch, đưa ByteStream rỗng vào nhánh lỗi riêng có URL. Cách này cần thêm một component nhưng giữ mọi URL trong đầu ra của pipeline.
Ca một URL với raise_on_failure True
Chạy pipeline với đúng một URL /khong-co và raise_on_failure True. Pipeline ném PipelineRuntimeError với component_name là fetch, thông báo cuối có đường dẫn tài liệu MDN về mã 404. Mã nguồn ghi rõ: chỉ khi danh sách có đúng một URL và raise_on_failure True thì lỗi mới được ném ra. Với nhiều URL, lỗi được bắt lại.
Nghĩa là cùng một cấu hình, pipeline cư xử khác nhau tùy số URL đầu vào. Bộ test với một URL sẽ thấy exception, còn chạy thật với danh sách dài sẽ không. Ghi chú này nên nằm trong tài liệu nội bộ của nhóm.
Ca component export lỗi

Lỗi dừng cả nhánh
Lab đặt đường dẫn export vào thư mục không tồn tại. Pipeline chạy fetch, parse, gate bình thường, tới export thì lỗi không tìm thấy thư mục. Haystack ném PipelineRuntimeError, component_name là export, thông báo nêu tên component, lớp JsonlExporter và lỗi gốc của hệ điều hành.
Thông báo lỗi đủ để điều tra
Thông báo PipelineRuntimeError có ba dòng rõ ràng: component nào lỗi, lớp nào, lỗi gốc là gì. Thuộc tính component_name của exception cho phép code bắt lỗi phân loại theo component mà không phải phân tích chuỗi. Trong lab, component_name là export cho ca thư mục sai và fetch cho ca 404 đơn lẻ.
Nhánh độc lập cũng không chạy
Snapshot đính kèm exception cho biết số lần chạy của từng component: fetch, parse, gate mỗi cái một lần, export và rejects bằng không. rejects không phụ thuộc export, nhưng nó chưa kịp chạy khi export hỏng. Pipeline dừng toàn bộ ở lỗi đầu tiên.
Hệ quả: lỗi ở nhánh đạt làm mất luôn danh sách URL bị loại của lần chạy đó. Nếu danh sách loại quan trọng, nên cho component ghi đầu ra bắt lỗi của riêng nó, hoặc đọc đầu ra gate trong snapshot.
Snapshot giữ đầu ra đã có
Lần chạy lỗi có yêu cầu giữ đầu ra của gate. Snapshot chứa pipeline_outputs với dữ liệu đã tuần tự hóa của gate, gồm cả hai nhánh passed và rejected, mỗi Document có url, content_chars, id và content. Đường dẫn tệp snapshot là None, nghĩa là snapshot chỉ nằm trong exception, không tự ghi ra đĩa trong cấu hình mặc định.
Muốn giữ snapshot, bắt PipelineRuntimeError và tự lưu. Với pipeline chạy lâu, đây là cách không phải tải lại mọi trang chỉ vì bước cuối hỏng.
Xuất đồ thị Haystack pipeline tài liệu web cùng output và metadata từng công đoạn
Phần này nói về metadata và cách xem đầu ra trung gian.
include_outputs_from
Mặc định pipeline.run chỉ trả đầu ra của component cuối cùng, tức những socket không nối tiếp vào đâu. Tham số include_outputs_from nhận tập tên component muốn giữ đầu ra. Lab dùng tập fetch, parse, gate để in ma trận kết quả. Không có tham số này, chỉ thấy export và rejects.
Giữ đầu ra trung gian tốn bộ nhớ, vì mọi ByteStream và Document được giữ tới cuối lần chạy. Với vài chục trang thì không đáng kể. Với hàng nghìn trang, chỉ bật khi điều tra lỗi.
Metadata đi theo tài liệu
LinkContentFetcher ghi url và content_type vào meta của ByteStream. HTMLToDocument chép meta sang Document. gate thêm content_chars. Khi tới export, mỗi Document có đủ url, content_type và content_chars. Không có thời điểm tải, không có mã trạng thái, không có tiêu đề trang.
Tiêu đề trang không có trong meta
Tệp JSONL của lab có trường title luôn null. Lý do là HTMLToDocument trong cấu hình mặc định không đưa thẻ title vào meta. Nội dung trích có dòng đầu là tiêu đề bài viết vì nó nằm trong thẻ h1 của article. Muốn có tiêu đề trong meta, cần một component trích riêng hoặc truyền tham số cho trafilatura.
Nội dung trang chỉ có menu
Document từ /empty có nội dung đúng một dòng là chữ của thẻ nav, 19 ký tự. Trafilatura không tìm thấy nội dung chính nên lấy phần còn lại. Không có gate, dòng menu này sẽ nằm trong tệp kết quả như một tài liệu hợp lệ. Ngưỡng 120 ký tự của gate loại nó đúng.
Ngưỡng nên chọn theo dữ liệu thật. Trang tài liệu kỹ thuật thường dài hàng nghìn ký tự. Trang trạng thái dịch vụ có thể chỉ vài chục ký tự mà vẫn có giá trị. Đặt ngưỡng sai, gate loại nhầm trang tốt.
Mã băm nội dung
export ghi 12 ký tự đầu của SHA-1 nội dung. Hai lần chạy cách nhau một tuần, so mã băm cho biết trang nào đổi nội dung mà không phải so cả văn bản. Trong lab, /a có mã a611df2958af và /b có mã 57a3296eae80. Chạy lại cùng fixture cho cùng mã, vì nội dung không đổi.
Mã băm tính trên nội dung sau khi trích, không phải HTML gốc. Đổi phiên bản trafilatura có thể đổi nội dung trích và làm đổi mã băm dù trang không đổi. Ghi phiên bản thư viện cạnh dữ liệu để phân biệt hai nguyên nhân.
Thêm thời điểm tải và mã trạng thái
Lab thêm exported_at ở bước export, nhưng đó là thời điểm ghi, không phải thời điểm tải. Với nhu cầu truy vết, nên có một component bọc fetch, ghi fetched_at và mã HTTP vào meta. Cách này cũng giải quyết luôn vấn đề URL 404 không để lại dấu.
Đầu ra nghiệm thu: Pipeline graph, fixture và ma trận kết quả component thành công/thất bại của Haystack pipeline tài liệu web
Phần cuối gom bộ bàn giao và vai trò của proxy.
Ma trận kết quả
URL |
fetch |
parse |
gate |
export |
rejects |
|---|---|---|---|---|---|
/a |
605 byte |
426 ký tự |
đạt |
có |
không |
/b |
528 byte |
360 ký tự |
đạt |
có |
không |
/empty |
135 byte |
19 ký tự |
loại |
không |
có |
/khong-co (404) |
0 byte, không mã |
bỏ qua, cảnh báo |
không |
không |
không |
Ma trận lỗi
Phép thử |
Kết quả |
Component báo lỗi |
|---|---|---|
Nối fetch.streams vào export.documents |
PipelineConnectError lúc connect |
không chạy |
Một URL 404, raise_on_failure True |
PipelineRuntimeError |
fetch |
Nhiều URL có 404, raise_on_failure False |
không lỗi, URL biến mất |
không |
Thư mục export không tồn tại |
PipelineRuntimeError, rejects không chạy |
export |
Bộ bàn giao
Bộ bàn giao gồm tệp YAML của pipeline, mã ba component tự viết, fixture bốn URL, hai ma trận trên và tệp JSONL đầu ra. Kèm một đoạn ghi chú về hai hành vi cần nhớ: URL lỗi biến mất khi raise_on_failure False, và lỗi một component làm dừng cả nhánh độc lập.
Chạy lại phần xử lý không tải lại
Vì fetch tách riêng, có thể lưu ByteStream của fetch ra đĩa ở lần chạy đầu, rồi lần sau dựng một pipeline chỉ có parse, gate, export đọc từ đĩa. Khi chỉnh ngưỡng gate hay đổi trình trích nội dung, không phải gửi lại request tới website. Với website của bên thứ ba, đây cũng là cách giảm tải cho họ.
Ngưỡng nghiệm thu
Pipeline đạt khi mọi URL đầu vào có mặt ở export, rejects hoặc một danh sách lỗi riêng. Phép đối chiếu đầu vào với đầu ra phải ra tập rỗng. Nối sai kiểu phải lỗi lúc connect. Lỗi ở export phải nêu đúng tên component.
Khi nào cần proxy với Haystack pipeline tài liệu web
LinkContentFetcher dùng httpx và nhận client_kwargs để truyền tham số cho client, gồm cả cấu hình proxy. httpx cũng đọc biến môi trường HTTP_PROXY và HTTPS_PROXY. Cách viết URL proxy có trong bài định dạng proxy.
Proxy chỉ cần ở component fetch. parse, gate, export xử lý dữ liệu đã có trong bộ nhớ, không gửi request nào. Đây là lợi ích khác của việc tách fetch: chỉ một chỗ cần cấu hình mạng. Khi website tài liệu nội bộ chỉ mở cho một IP cố định, anh em có thể mua proxy tĩnh Việt Nam tại trang chủ ProxyVN. Proxy không cấp quyền thu thập và không sửa được trang chỉ có menu. Vai trò hợp lệ của proxy được phân tích trong bài Web Scraping proxy là gì.
Trích nội dung kỹ hơn
HTMLToDocument dựa trên trafilatura. Các tùy chọn của trafilatura, như giữ bảng hay giữ link, có trong bài Trafilatura web scraping. extraction_kwargs của HTMLToDocument là nơi truyền các tùy chọn đó.
Checklist Haystack pipeline tài liệu web

Checklist pipeline
- Khóa phiên bản haystack-ai và trafilatura.
- Tách fetch, parse, gate, export thành component riêng.
- Khai báo output_types cho mọi component tự viết.
- Nối nhánh loại vào một đầu ra, không bỏ nhánh.
- Đối chiếu tập URL đầu vào với đầu ra sau mỗi lần chạy.
- Nhớ raise_on_failure chỉ ném lỗi khi có đúng một URL.
- Bắt PipelineRuntimeError và lưu snapshot nếu cần.
- Lưu pipeline ra YAML cạnh mã nguồn.
Câu hỏi thường gặp về Haystack pipeline tài liệu web
Tại sao URL 404 không có trong kết quả?
Với raise_on_failure False, fetch trả ByteStream rỗng không có mã trạng thái, parse bỏ qua kèm cảnh báo.
Nối sai kiểu có bị phát hiện lúc chạy không?
Không cần chờ chạy. Haystack báo PipelineConnectError ngay ở lệnh connect.
Một component lỗi thì các nhánh khác có chạy tiếp không?
Trong lab thì không. Export lỗi làm rejects không chạy dù không phụ thuộc nhau.
Làm sao xem đầu ra của bước giữa?
Truyền include_outputs_from với tên component khi gọi pipeline.run.
Tiêu đề trang có trong meta không?
Không với HTMLToDocument mặc định. Cần thêm bước trích riêng.
Proxy đặt ở component nào?
Chỉ ở fetch, qua client_kwargs hoặc biến môi trường của httpx.
Haystack pipeline tài liệu web và những điều cần nhớ
Haystack pipeline tài liệu web cho mỗi bước một hợp đồng kiểu rõ ràng, và bắt sai hợp đồng ngay lúc lắp ráp. Nhưng kiểu đúng không có nghĩa dữ liệu đúng. Lab cho thấy URL 404 có thể biến mất không dấu vết và lỗi ở một nhánh làm dừng nhánh khác. Thêm gate, giữ nhánh loại, đối chiếu đầu vào với đầu ra. Cần IP tĩnh cho bước fetch của Haystack pipeline tài liệu web, liên hệ Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam.