ScrapeGraphAI + Scrapeless: Nhắm SmartScraperGraph vào một Trình duyệt Đám mây
Advanced Data Extraction Specialist
TL;DR:
- ScrapeGraphAI lấy dữ liệu bằng một prompt thay vì selectors, nhưng việc lấy dữ liệu phía dưới là một trình duyệt Playwright thông thường được khởi động trên máy của bạn.
pip install scrapegraphaicung cấp cho bạn client Playwright và không có tệp nhị phân trình duyệt, vì vậy loader mặc định sẽ thất bại khi cài đặt mới cho đến khi bạn cũng chạyplaywright install chromium.ChromiumLoaderchọn phương pháp lấy dữ liệu của mình bằnggetattr(self, f"ascrape_{self.backend}"), vì vậybackendchỉ định một phương pháp thay vì chọn từ một danh sách cố định — đó là nơi mà backend lấy dữ liệu tùy chỉnh tách biệt.- Một lớp con ngắn với một phương pháp
ascrape_scrapelesslấy dữ liệu qua Scrapeless Scraping Browser qua một kết nốiwss://CDP và không cần cài đặt trình duyệt cục bộ. FetchNodenhậpChromiumLoadertheo tên, vì vậy việc tái liên kếtfetch_node.ChromiumLoaderlà điều làm cho đồ thị thực sự sử dụng lớp con của bạn. Bỏ qua điều đó và một loader trông chính xác sẽ bị bỏ qua một cách im lặng.- Toàn bộ pipeline chạy trên một mô hình cục bộ:
SmartScraperGraphvớiollama/qwen2.5:0.5btrả về các cặp tác giả và trích dẫn có cấu trúc mà không cần khoá mô hình đám mây. - Bắt đầu trên gói miễn phí Scrapeless và chuyển việc lấy dữ liệu ra khỏi máy tính xách tay của bạn.
Scrapeless Scraping Browser là một trình duyệt đám mây mà bạn kết nối thay vì khởi động. Nó lắng nghe trên một điểm cuối WebSocket CDP an toàn, điều này quan trọng ở đây vì lớp lấy dữ liệu của ScrapeGraphAI là Playwright phía dưới và Playwright có thể kết nối với một trình duyệt mà nó không khởi động.
ScrapeGraphAI là phần trong pipeline mà mọi người bàn luận: mô tả những gì bạn muốn trong một câu, và một đồ thị các nút biến một trang thành JSON có cấu trúc mà không cần một CSS selector nào. Phần mà không ai bàn đến là nút đầu tiên. Trước khi bất kỳ mô hình nào thấy bất cứ điều gì, FetchNode phải tạo ra HTML, và nó làm điều đó bằng cách khởi động Chromium trên bất kỳ máy nào mà script đang chạy. Mỗi hướng dẫn trên trang đầu tiên của kết quả tìm kiếm cấu hình nút đó theo một cách duy nhất, với từ điển proxy, và dừng lại ở đó.
Hướng dẫn này đi vào lớp lấy dữ liệu thay vì: nơi nó tồn tại, điểm mở rộng thực tế là gì, và cách định tuyến nó thông qua một trình duyệt đám mây. Mỗi khối bên dưới đã chạy trực tiếp, bao gồm cả việc lấy dữ liệu.
Nơi Lớp Lấy Dữ Liệu Của ScrapeGraphAI Thực Sự Tồn Tại
FetchNode là nút đầu vào của gần như mọi đồ thị, và nó kết thúc ở một trong một vài nhánh. Nếu bạn thiết lập browser_base, scrape_do, hoặc plasmate trong cấu hình nút, nó chuyển giao cho một vendor loader trong scrapegraphai/docloaders/. Ngược lại, nó rớt xuống ChromiumLoader, đây là con đường mặc định và là con đường mà hầu hết mọi người sử dụng.
Sự rơi xuống đó quan trọng vì hai lý do. Các backend lấy dữ liệu của nhà cung cấp đã là một hình dạng đã thiết lập trong mã này chứ không phải điều gì bạn đang phát minh ra — browser_base.py và scrape_do.py đã được gửi trong repo. Và ChromiumLoader chọn phương pháp lấy dữ liệu của riêng mình theo tên:
python
scraping_fn = getattr(self, f"ascrape_{self.backend}")
backend không được xác thực chống lại một enum cố định. Nó là một chuỗi nội suy vào một tra cứu thuộc tính, vì vậy bất kỳ phương pháp nào được gọi là ascrape_<something> trở nên có thể truy cập bằng cách thiết lập backend thành <something>. Đó là điểm tách.
ascrape_playwright mặc định gọi p.chromium.launch(...), điều này khởi động một quy trình trình duyệt cục bộ. Thay đổi điều đó cho kết nối WebSocket tới một trình duyệt đang chạy là một sự thay đổi của một cuộc gọi.
Các yêu cầu tiên quyết
- Python 3.10 trở lên.
- Một khoá API Scrapeless từ bảng điều khiển, được xuất ra dưới dạng
SCRAPELESS_KEY. - Ollama chạy cục bộ với một mô hình đã kéo, nếu bạn muốn làm theo bước lấy dữ liệu mà không cần khoá mô hình đám mây.
- Không cần tệp nhị phân trình duyệt cục bộ cho con đường đám mây. Bạn chỉ cần một cái nếu bạn cũng muốn chạy loader mặc định.
Cài đặt
bash
pip install "scrapegraphai==2.1.6" "langchain-ollama==1.1.0"
Playwright được cài đặt như một phụ thuộc, nhưng các trình duyệt của nó thì không. Sự phân biệt đó gây ra sự thất bại đầu tiên mà hầu hết mọi người gặp phải.
bash
export SCRAPELESS_KEY="your_api_key_here"
Một Cài Đặt Mới Thực Sự Lấy Gì
Chạy loader mặc định ngay sau khi cài đặt và nó không đến được trang một chút nào.
python
from scrapegraphai.docloaders import ChromiumLoader
try:
docs = ChromiumLoader(["https://quotes.toscrape.com/"], headless=True).load()
print("chars:", len(docs[0].page_content))
except Exception as exc:
print(f"{type(exc).__name__}: {str(exc).split(' at /')[0]}")
text
RuntimeError: Failed to scrape after 1 attempts: BrowserType.launch: Executable doesn't exist
Client Playwright đã được cài đặt; Chromium mà nó muốn khởi động thì không. playwright install chromium sửa chữa điều đó và tốn một vài trăm megabyte trên mỗi máy mà chạy đồ thị — một hình ảnh CI, một container, mỗi máy tính xách tay của nhà phát triển. Con đường đám mây bỏ qua hoàn toàn điều đó, vì trình duyệt mà nó điều khiển đã đang chạy ở nơi khác.
Hướng Đến Một Trình Duyệt Đám Mây
Tạo lớp con ChromiumLoader, thêm một phương pháp có tên cho backend bạn muốn, và tái liên kết self.backend sau khi super().__init__ đã chạy.
python
import os
from scrapegraphai.docloaders import ChromiumLoader
CDP = (
"wss://browser.scrapeless.com/api/v2/browser"
f"?token={os.environ['SCRAPELESS_KEY']}&sessionTTL=180&proxyCountry=ANY"
)
class ScrapelessLoader(ChromiumLoader):
"""Fetch through a remote CDP browser instead of launching one locally."""
def __init__(self, urls, **kwargs):
kwargs.pop("backend", None)
super().__init__(urls, backend="playwright", **kwargs)
self.backend = "scrapeless"
async def ascrape_scrapeless(self, url: str, browser_name: str = "chromium") -> str:
from playwright.async_api import async_playwright
async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(CDP)
page = await browser.new_page()
await page.goto(url, wait_until=self.load_state)
html = await page.content()
await browser.close()
return html
loader = ScrapelessLoader(["https://quotes.toscrape.com/"])
print("dispatches to:", getattr(loader, f"ascrape_{loader.backend}").__name__)
docs = loader.load()
print("chars:", len(docs[0].page_content))
print("Einstein present:", "Einstein" in docs[0].page_content)
Hai chi tiết thực hiện công việc. super().__init__ được gọi với backend="playwright" vì hàm khởi tạo chạy một kiểm tra nhập vào chuỗi đó, và playwright là tên được giải quyết; self.backend sau đó được gán lại để việc chuyển phát trong lazy_load tìm thấy ascrape_scrapeless. Giữ browser_name trong chữ ký với một giá trị mặc định — bộ phân phối gọi phương thức với URL một mình.
text
dispatches to: ascrape_scrapeless
chars: 10968
Einstein present: True
Trang web trở lại được hiển thị đầy đủ từ một trình duyệt chưa từng tồn tại trên máy này. proxyCountry chấp nhận một mã hai ký tự khi bạn cần yêu cầu xuất phát từ một quốc gia cụ thể, và sessionTTL xác định thời gian phiên từ xa mở.
Làm cho Đồ Thị Sử Dụng Nó
Khởi tạo lớp con bằng chính bạn chứng minh việc truy xuất hoạt động, nhưng đồ thị sẽ không tự động nhận nó. FetchNode làm from ..docloaders import ChromiumLoader và sau đó gọi tên đó trực tiếp, vì vậy lớp mà đồ thị sử dụng là lớp được gán trong không gian tên mô-đun của nút. Gán lại trước khi xây dựng đồ thị.
python
import scrapegraphai.nodes.fetch_node as fetch_node
fetch_node.ChromiumLoader = ScrapelessLoader
Đây là bước quyết định xem bất kỳ điều gì ở trên có hiệu ứng hay không. Một lớp con được viết chính xác nhưng không bao giờ được gán tạo ra một đồ thị hoạt động, thành công và nhẹ nhàng truy xuất qua trình duyệt cục bộ suốt thời gian.
Bởi vì thay thế giữ nguyên chữ ký hàm khởi tạo, mọi thứ FetchNode đã vượt qua — headless, storage_state, và bất cứ điều gì bạn đưa vào loader_kwargs — tiếp tục đến nguyên vẹn.
Sẵn sàng di chuyển việc truy xuất ra khỏi máy của bạn? Tạo một tài khoản Scrapeless miễn phí và chỉ định đồ thị đầu tiên của bạn vào đó.
Chạy Toàn Bộ Đồ Thị trên Mô Hình Cục Bộ
Với bộ tải được gán, SmartScraperGraph hoạt động bình thường. Chỉ định khối llm tại Ollama giữ toàn bộ quy trình ra khỏi API trả phí, điều này làm cho lớp truy xuất rẻ để lặp lại.
python
import os
import scrapegraphai.nodes.fetch_node as fetch_node
from scrapegraphai.docloaders import ChromiumLoader
from scrapegraphai.graphs import SmartScraperGraph
CDP = (
"wss://browser.scrapeless.com/api/v2/browser"
f"?token={os.environ['SCRAPELESS_KEY']}&sessionTTL=180&proxyCountry=ANY"
)
class ScrapelessLoader(ChromiumLoader):
def __init__(self, urls, **kwargs):
kwargs.pop("backend", None)
super().__init__(urls, backend="playwright", **kwargs)
self.backend = "scrapeless"
async def ascrape_scrapeless(self, url: str, browser_name: str = "chromium") -> str:
from playwright.async_api import async_playwright
async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(CDP)
page = await browser.new_page()
await page.goto(url, wait_until=self.load_state)
html = await page.content()
await browser.close()
return html
fetch_node.ChromiumLoader = ScrapelessLoader
graph = SmartScraperGraph(
prompt="List the quote authors on this page.",
source="https://quotes.toscrape.com/",
config={
"llm": {
"model": "ollama/qwen2.5:0.5b",
"temperature": 0,
"format": "json",
"model_tokens": 4096,
},
"verbose": False,
"headless": True,
},
)
result = graph.run()
print("keys:", sorted(result))
print("authors:", [item["author"] for item in result["content"]][:4])
text
keys: ['content']
authors: ['Albert Einstein', 'J.K. Rowling', 'Jane Austen', 'Marilyn Monroe']
Các tác giả trở lại chính xác và cấu trúc là đúng. Văn bản trích dẫn từ mô hình này ít đáng tin cậy hơn — một mô hình tham số 0.5B cắt và hợp nhất các chuỗi trên một danh sách dài — nhưng lớp truy xuất đã cung cấp toàn bộ trang, và mô hình là yếu tố giới hạn thay vì quy trình. Di chuyển khóa model đến một mô hình cục bộ lớn hơn hoặc một mô hình lưu trữ và cùng một đồ thị tạo ra văn bản rõ ràng hơn thông qua cùng một bộ tải.
Đầu ra có cấu trúc ở đây là điều quan trọng: đồ thị đọc tài liệu HTML đã phân tích mà trình duyệt từ xa đã hiển thị, không phải là đánh dấu thô mà một khách hàng HTTP đơn giản sẽ nhận được. Đặt format thành json yêu cầu mô hình đầu ra tuân theo định dạng trao đổi JSON, điều này làm cho kết quả có thể được chỉ định trực tiếp thay vì một chuỗi mà bạn phải phân tích.
Kết Luận
Lớp truy xuất của ScrapeGraphAI có tính cấu hình cao hơn những gì các hướng dẫn gợi ý, và điểm cấu hình không phải là loader_kwargs — đó là chuỗi backend, mà giải quyết thành một tên phương thức. Một lớp con với một phương thức ascrape_scrapeless di chuyển việc truy xuất đến một trình duyệt đám mây, và một lần gán lại fetch_node.ChromiumLoader khiến đồ thị sử dụng nó.
Kiểm tra lần gán lại trước nếu các kết quả trông giống như không thay đổi. Một lớp con không bao giờ được gán sẽ im lặng thất bại thay vì ồn ào, và triệu chứng là một đồ thị hoạt động chính xác như trước đây. Xác nhận bộ tải một mình, như trong bước giữa ở trên, phân tách một vấn đề truy xuất khỏi một vấn đề mô hình trong một lần chạy.
Đối với nơi điều khiển trình duyệt đang hướng tới như một tiêu chuẩn, đặc tả WebDriver BiDi là điều đáng theo dõi. Hướng dẫn Playwright và Scraping Browser đề cập đến kết nối này một cách chi tiết hơn, chi tiết kế hoạch có trên trang giá cả của Scrapeless, và các thông số phiên có trong tài liệu Scrapeless.
Câu Hỏi Thường Gặp
Q: Tôi có cần cài đặt một trình duyệt để sử dụng đường dẫn đám mây không?
Không. pip install scrapegraphai cung cấp khách hàng Playwright, đó là tất cả những gì connect_over_cdp cần, vì trình duyệt đang được điều khiển đã chạy từ xa. Bạn chỉ cần playwright install chromium nếu bạn cũng muốn chạy bộ tải cục bộ gốc.
Q: Tại sao bộ tải tùy chỉnh của tôi bị đồ thị bỏ qua?
Hầu như luôn luôn vì fetch_node.ChromiumLoader chưa bao giờ được liên kết lại. FetchNode nhập lớp theo tên và gọi tên đó, vì vậy việc kế thừa đơn thuần không thay đổi gì — nút tiếp tục xây dựng lớp gốc. Liên kết lại thuộc tính trên mô-đun trước khi bạn xây dựng đồ thị.
Q: Tôi có thể sử dụng loader_kwargs thay vì một lớp con không?
Đối với các proxy và tùy chọn khởi động trình duyệt, có — loader_kwargs chảy thẳng vào ChromiumLoader. Tuy nhiên, nó không thể chuyển hướng việc fetch đến một trình duyệt từ xa, vì phương pháp mặc định gọi chromium.launch(), phương pháp này luôn bắt đầu một quá trình cục bộ. Thay đổi đích đến có nghĩa là thay đổi phương pháp, điều này có nghĩa là một lớp con.
Q: Điều này có hoạt động với các đồ thị khác ngoài SmartScraperGraph không?
Có. Việc liên kết lại diễn ra ở cấp độ nút, và FetchNode là nút đầu vào cho các loại đồ thị khác, vì vậy bất kỳ đồ thị nào lấy một URL đều đi qua cùng một loader một khi thuộc tính được liên kết.
Q: sessionTTL kiểm soát điều gì?
Thời gian mà phiên trình duyệt từ xa vẫn mở, tính bằng giây. Đặt nó thoải mái ở mức cao hơn thời gian mà một fetch đơn lẻ mất; phiên sẽ đóng lại khi kết nối kết thúc hoặc cửa sổ hết hạn, cái nào đến trước.
Q: Tôi có thể giữ cookie hoặc một phiên đang đăng nhập qua các lần fetch không?
storage_state đã được truyền qua bởi FetchNode và đến nhà xây dựng lớp con mà không thay đổi, vì vậy tệp trạng thái lưu trữ chuẩn của Playwright hoạt động. Áp dụng nó khi tạo ngữ cảnh trên trình duyệt từ xa thay vì khi khởi động, vì trình duyệt từ xa không được khởi động bởi mã của bạn.
Q: Một mô hình cục bộ 0.5B có đủ tốt cho việc trích xuất thực sự không?
Đối với các trang ngắn với hình dạng đơn giản, nó tạo ra cấu trúc có thể sử dụng, như ở trên. Các trang dài hơn và các sơ đồ lồng ghép là nơi nó giảm xuống — văn bản bị cắt và các trường bị gộp lại. Xem một mô hình cục bộ nhỏ là một cách để lặp lại trên lớp fetch một cách tiết kiệm, sau đó chuyển model khóa cho các lượt sản xuất.
Tại Scrapless, chúng tôi chỉ truy cập dữ liệu có sẵn công khai trong khi tuân thủ nghiêm ngặt các luật, quy định và chính sách bảo mật trang web hiện hành. Nội dung trong blog này chỉ nhằm mục đích trình diễn và không liên quan đến bất kỳ hoạt động bất hợp pháp hoặc vi phạm nào. Chúng tôi không đảm bảo và từ chối mọi trách nhiệm đối với việc sử dụng thông tin từ blog này hoặc các liên kết của bên thứ ba. Trước khi tham gia vào bất kỳ hoạt động cạo nào, hãy tham khảo ý kiến cố vấn pháp lý của bạn và xem xét các điều khoản dịch vụ của trang web mục tiêu hoặc có được các quyền cần thiết.



