Dify + Scrapeless: Cung Cấp Dữ Liệu Web Trực Tiếp Cho Các Đại Lý Của Bạn Với Một Công Cụ Tùy Chỉnh
Advanced Data Extraction Specialist
TL;DR:
- Plugin Deep SerpApi trong Dify Marketplace chỉ cung cấp một công cụ với một tham số,
query, vì vậy bất kỳ yêu cầu nào cần một kết quả dọc, bù trừ trang, hoặc một trang web khác phải đến từ nơi khác. - Một công cụ tùy chỉnh là một tệp OpenAPI. Dify phân tích nó thành một hoạt động duy nhất,
scraperRequest, kết nối với toàn bộ gia đình diễn viên Scrapelessscraper.*thông qua một điểm đầu cuối. - Dify tự động điền hai trường xác thực với các giá trị mà API này từ chối: tên tiêu đề mặc định là
Authorizationvà tiền tố tiêu đề mặc định làBasic. Cả hai giá trị mặc định đều trả về401với{"code":14404,"message":"invalid access token"}. - Dify gán đối tượng lồng
inputdưới dạng tham số chuỗi, vì vậy một nút Code phát ra văn bản JSON là cách đáng tin cậy để xây dựng nó bên trong một Workflow. - Một cuộc gọi sản phẩm Amazon trả về khoảng 2.2 MB, trong đó 1.9 MB là
htmlthô. Chọnresulttrong một nút Code trước khi tải trọng đến một mô hình. - Một tài khoản Scrapeless miễn phí bao phủ mọi yêu cầu trong hướng dẫn này.
Một tác nhân Dify không có công cụ web trả lời từ trọng số mô hình của nó và bất cứ điều gì bạn đã tải lên vào cơ sở kiến thức của nó. Hãy yêu cầu nó cung cấp các trang đứng đầu hiện tại, giá cả hiện tại của một đối thủ cạnh tranh, hoặc những thợ sửa ống nước đang hoạt động tại một thành phố cụ thể, và nó sẽ sản xuất thứ gì đó trôi chảy và lỗi thời.
Dify giải quyết vấn đề đó bằng các công cụ, và có hai cách để thêm một cái. Hướng dẫn này đề cập đến cách thứ hai: một công cụ tùy chỉnh được xây dựng từ một tệp OpenAPI, biến Scrapeless Scraping API thành một hành động có thể gọi trong mọi tác nhân và quy trình làm việc trong không gian làm việc của bạn.
Những Gì Một Công Cụ Tùy Chỉnh Thêm Vào Mà Plugin Không Có
Danh sách chính thức Deep SerpApi trong Dify Marketplace cung cấp một công cụ với một tham số yêu cầu duy nhất, query, và một trường xác thực cho khóa API. Nếu một truy vấn Google đơn giản là tất cả những gì quy trình làm việc của bạn cần, hãy cài đặt nó và dừng đọc — chỉ cần hai cú nhấp là đủ và nó hoạt động, và báo cáo tin tức doanh nghiệp được xây dựng trên Dify cho thấy một quy trình làm việc đầy đủ được lắp ráp xung quanh nó.
Điểm đầu cuối HTTP Scrapeless đứng sau nó chấp nhận nhiều hơn một chuỗi truy vấn. Hình dạng yêu cầu tương tự có thể chọn gói địa phương thay vì kết quả web, bù đắp đến trang thứ hai của những kết quả đó, hoặc hoàn toàn chuyển sang một danh sách Amazon. Không có điều gì trong số đó có thể đạt được thông qua một trường query duy nhất.
Một công cụ tùy chỉnh đóng khoảng cách đó lại. Bạn dán một tài liệu OpenAPI, Dify đọc các hoạt động từ đó, và toàn bộ gia đình diễn viên trở thành một công cụ có thể gắn vào. Không có gì để cài đặt và không có gì để triển khai, và tệp giống nhau hoạt động trên Dify Cloud và trên một phiên bản tự lưu trữ.
Những Gì API Scraping Trả Về
Một điểm đầu cuối tiếp nhận mọi yêu cầu: POST https://api.scrapeless.com/api/v1/scraper/request. Thân yêu cầu mang theo hai trường — actor tên máy quét, và input chứa các tham số của máy quét đó.
Phản hồi là JSON đã phân tích chứ không phải HTML. Một cuộc gọi scraper.google.search đặt organic_results lên cấp cao nhất bên cạnh metadata, pagination, và search_information. Thêm tbm: lcl vào cùng một diễn viên sẽ hoán đổi nó cho local_results.places, khối doanh nghiệp với xếp hạng, số điện thoại và địa chỉ. Một cuộc gọi scraper.amazon lồng sản phẩm đã phân tích dưới result.
Thiết kế hình dạng đơn này là lý do mà một hoạt động OpenAPI là đủ. Chi tiết về các tham số của mọi diễn viên nằm trong tài liệu API Scraping.
Điều Kiện Tiên Quyết
- Một không gian làm việc Dify — Cloud, hoặc tự lưu trữ trên phiên bản 1.0.0 trở lên. Hành vi được mô tả ở đây được đo trên một phiên bản tự lưu trữ 1.16.1.
- Một khóa API Scrapeless từ bảng điều khiển.
- Quyền không gian làm việc để thêm công cụ. Dify giới hạn các điểm cuối công cụ tùy chỉnh cho quản trị viên và chủ sở hữu không gian làm việc.
Bước 1: Nhập Lược Đồ OpenAPI
Trong Dify, mở Công cụ → Tùy chỉnh → Tạo Công cụ Tùy chỉnh và dán tài liệu bên dưới. Nó hợp lệ theo cụ thể OpenAPI 3.0.3, phiên bản mà phân tích viên của Dify mong đợi.
yaml
openapi: 3.0.3
info:
title: Scrapeless Scraper API
version: "1.0.0"
servers:
- url: https://api.scrapeless.com
paths:
/api/v1/scraper/request:
post:
operationId: scraperRequest
summary: Run a scraper actor and return structured data
security:
- ApiTokenAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [actor, input]
properties:
actor:
type: string
description: Which scraper to run.
enum: [scraper.google.search, scraper.amazon]
example: scraper.google.search
input:
type: object
description: Actor parameters. Keys depend on the actor.
additionalProperties: true
examples:
googleSearch:
summary: Google SERP
value:
actor: scraper.google.search
input:
q: web scraping api
googleLocalPack:
summary: Google local pack
value:
actor: scraper.google.search
input:
q: plumbers in Austin, TX
tbm: lcl
amazonProduct:
summary: Amazon product by URL
value:
actor: scraper.amazon
input:
action: product
url: https://www.amazon.com/dp/B09B8V1LZ3
responses:
'200':
description: Parsed result. Shape depends on the actor.
content:
application/json:
schema:
type: object
additionalProperties: true
components:
securitySchemes:
ApiTokenAuth:
type: apiKey
in: header
name: x-api-token
Dify phân tích điều đó thành chính xác một công cụ. Tên đến từ operationId, vì vậy công cụ được gọi là scraperRequest, và nó nhận hai tham số: actor và input. Ba ví dụ có tên xuất hiện trong trình xây dựng yêu cầu, giúp tiết kiệm việc gõ URL Amazon bằng tay.
Bước 2: Điền Tất Cả Bốn Trường Xác Thực
Chọn xác thực Khóa API và thiết lập mọi trường. Hai trong bốn trường được điền sẵn với các giá trị mà API này từ chối:
| Trường | Những gì cần thiết lập | Những gì Dify tự động điền |
|---|---|---|
| Kiểu xác thực | API Key (được lưu trữ dưới dạng api_key_header) |
None |
| Tên tiêu đề | x-api-token |
Authorization |
| Giá trị | Khóa API Scrapeless của bạn | trống |
| Tiền tố tiêu đề | Custom |
Basic |
Trường tiền tố là điều khiến người dùng bối rối. Dify nối nó vào giá trị, vì vậy nếu để Basic thì tiêu đề x-api-token: Basic <your-key> sẽ được gửi. Điều đó không có nghĩa là chế độ xác thực HTTP cơ bản — một thông tin xác thực cơ bản thực sự là một cặp được mã hóa base64 user:password — và Scrapeless yêu cầu khóa thuần túy, vì vậy yêu cầu sẽ bị từ chối. Bearer cũng thất bại tương tự. Chỉ Custom mới truyền giá trị mà không bị thay đổi.
Việc để tên tiêu đề trên Authorization cũng thất bại theo cách tương tự, vì lý do tương tự: khóa không bao giờ xuất hiện trong tiêu đề mà API đọc.
Cả hai sai lầm tạo ra một phản hồi, và bạn có thể tái tạo bất kỳ điều nào từ một terminal trước khi chạm vào Dify:
bash
# Correct: bare key in x-api-token
curl -s -o /dev/null -w 'bare key -> %{http_code}\n' \
-X POST https://api.scrapeless.com/api/v1/scraper/request \
-H "Content-Type: application/json" \
-H "x-api-token: $SCRAPELESS_API_KEY" \
-d '{"actor":"scraper.google.search","input":{"q":"web scraping api"}}'
# What Dify sends with the default prefix
curl -s -w '\nBasic prefix -> %{http_code}\n' \
-X POST https://api.scrapeless.com/api/v1/scraper/request \
-H "Content-Type: application/json" \
-H "x-api-token: Basic $SCRAPELESS_API_KEY" \
-d '{"actor":"scraper.google.search","input":{"q":"web scraping api"}}'
# What Dify sends with the default header name
curl -s -w '\nAuthorization -> %{http_code}\n' \
-X POST https://api.scrapeless.com/api/v1/scraper/request \
-H "Content-Type: application/json" \
-H "Authorization: $SCRAPELESS_API_KEY" \
-d '{"actor":"scraper.google.search","input":{"q":"web scraping api"}}'
text
bare key -> 200
{"code":14404,"message":"invalid access token"}
Basic prefix -> 401
{"code":14404,"message":"invalid access token"}
Authorization -> 401
Một 401 ở đây là máy chủ cho bạn biết rằng thông tin xác thực mà nó nhận được không phải là một cái mà nó chấp nhận, điều này hoàn toàn giống như khuyến nghị về ngữ nghĩa HTTP dành trạng thái đó. Thân bài thu hẹp hơn nữa: mã 14404 cụ thể là một mã thông báo không thể sử dụng, không phải một yêu cầu bị sai cú pháp.
Bước 3: Chạy Kiểm Tra Tích Hợp Sẵn
Bảng kiểm tra của Dify gọi điểm cuối với thông tin xác thực mà bạn vừa nhập. Điền hai tham số:
json
{
"actor": "scraper.google.search",
"input": "{\"q\": \"web scraping api\"}"
}
Một cấu hình hoạt động trả về khoảng 15 KB JSON SERP. Một tiền tố bị hỏng trả về một chuỗi lỗi duy nhất mang theo thân upstream một cách nguyên văn: Request failed with status code 401 and {"code":14404,"message":"invalid access token"}.
Lưu ý đến việc trích dẫn trong tải trọng kiểm tra. Dify làm phẳng các thuộc tính body yêu cầu lồng nhau, vì vậy input được đăng ký như một tham số chuỗi thay vì một đối tượng — lược đồ đã phân tích báo cáo actor và input đều là string, đều là bắt buộc. Một đối tượng JSON thực sự cũng hoạt động trong bảng vì Dify chuẩn hóa cả hai dạng thành đối tượng mà API yêu cầu. Việc chuyển đổi đó quan trọng: một yêu cầu được xây dựng bằng tay đối với điểm cuối phải gửi một đối tượng, và một chuỗi ở đó trở lại như 400 {"message":"invalid input body"}.
Lưu nhà cung cấp sau khi bài kiểm tra trả về dữ liệu. scraperRequest sau đó xuất hiện trong danh sách công cụ cho mọi ứng dụng trong không gian làm việc.
Xây dựng điều này trên một kế hoạch miễn phí? Tạo một tài khoản Scrapeless và các yêu cầu trong hướng dẫn này chạy trên hạn mức miễn phí.
Những Gì Trở Lại
Bì thư phụ thuộc vào tác nhân, và mỗi hình dạng cần xử lý khác nhau ở phía dưới.
Tìm kiếm web. scraper.google.search với {"q": "web scraping api"} trả về tám organic_results trong một phản hồi 15 KB, cùng với metadata, pagination, search_information, related_searches, và một khối inline_videos. Mỗi kết quả mang title, link, snippet, source, position, và snippet_highlighted_words.
Gói địa phương. Thêm tbm: lcl thay thế organic_results bằng local_results.places — 20 doanh nghiệp mỗi yêu cầu. Đặt start: 20 trả về trang tiếp theo; qua hai trang liên tiếp của một truy vấn, 37 trong số 40 hồ sơ là khác nhau, vì vậy một luồng lưu trữ cả hai trang nên dựa vào một thứ gì đó ổn định hơn là giả định không có sự lặp lại.
Các trường trong gói địa phương cần một lượt dọn dẹp trước khi đến CRM hoặc bảng tính:
phone,type, vàhoursđến với một khoảng cách dẫn đầu, và một số chuỗi giờ sử dụng một khoảng cách không ngắt quãng hẹp thay vì khoảng cách bình thường.phoneghi giữ một giá trị hình điện thoại trong 15 trong 20 hồ sơ trong một lần chụp; phần còn lại mang giờ mở cửa hoặc một nhãn dịch vụ nhưOnline estimates.place_id,place_id_search,lsig, vàthumbnailđều trống trong tất cả 20 hồ sơ.gps_coordinatescó mặt nhưng đọc{"latitude": 0, "longitude": 0}, vì vậy nó vượt qua một kiểm tra tính đúng đắn trong khi không mang theo vị trí nào.
Amazon. scraper.amazon với action: product đã trả về 2,226,755 byte. Sản phẩm đã phân tích dưới result là 4,608 byte qua 63 trường; phần còn lại 1,960,588 byte là html thô của danh sách. Giao toàn bộ tải trọng đó cho một mô hình là tốn kém và vô nghĩa.
Cắt Giảm Phản Hồi Trước Khi Nó Đến Mô Hình
Đặt một nút Code ngay sau nút Tool. Nó chạy Python 3 hoặc JavaScript, lấy đầu ra công cụ làm biến đầu vào, và trả về một dict mà các nút sau đọc theo khóa. Lựa chọn các trường ở đó không tốn chi phí gì và giữ cho ngữ cảnh của mô hình nhỏ:
python
def main(response: dict) -> dict:
places = (response.get("local_results") or {}).get("places") or []
rows = []
for place in places:
contact = (place.get("phone") or "").strip()
digits = sum(character.isdigit() for character in contact)
rows.append({
"name": (place.get("title") or "").strip(),
"category": (place.get("type") or "").strip(),
"rating": place.get("rating"),
"reviews": place.get("reviews") or 0,
"phone": contact if digits >= 10 else None,
"note": None if digits >= 10 else contact,
"address": (place.get("address") or "").strip(),
})
return {"rows": rows, "count": len(rows)}
# Local check against a live response. Leave everything below out of the Code node.
if __name__ == "__main__":
import json, os, urllib.request
body = json.dumps({
"actor": "scraper.google.search",
"input": {"q": "plumbers in Austin, TX", "tbm": "lcl"},
}).encode()
call = urllib.request.Request(
"https://api.scrapeless.com/api/v1/scraper/request",
data=body,
headers={"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
)
with urllib.request.urlopen(call, timeout=180) as reply:
cleaned = main(json.load(reply))
print(cleaned["count"], "rows")
print(json.dumps(cleaned["rows"][0], ensure_ascii=False))
Khối trên cũng có thể được sử dụng như một kiểm tra cục bộ: chạy nó với khóa của bạn trong môi trường và nó sẽ lấy một gói địa phương trực tiếp, áp dụng cùng một hàm, và in hàng đầu tiên đã được làm sạch. Lưu ý rằng một cuộc gọi trực tiếp gửi input dưới dạng một đối tượng — API trả về một chuỗi với 400 {"message":"invalid input body"}. Dify chuyển đổi dạng chuỗi cho bạn khi ra ngoài, đó là lý do tại sao cùng một giá trị hoạt động ở cả hai nơi.
Quá trình làm sạch biến 20 bản ghi thô thành 20 bản ghi có thể sử dụng: tên và danh mục không có khoảng trắng lẻ, một số thực trong phone khi trường giữ một số, và văn bản giờ mở cửa được di chuyển đến note thay vì được ghi vào cột điện thoại.
Đối với hình dạng Amazon, cùng một nút là một dòng đơn — return {"product": response["result"]} — và nó giảm 99% tải trọng.
Gắn Nó Vào Một Đại Lý Hoặc Một Quy Trình
Cả hai bề mặt đều sử dụng cùng một công cụ đã lưu, và sự lựa chọn là về người chọn các tham số.
Trong một Đại Lý, mô hình quyết định khi nào gọi scraperRequest và đặt gì vào actor và input. Điều đó hoạt động khi hướng dẫn đặt tên công cụ và điều kiện dữ liệu một cách rõ ràng:
text
When a question depends on current web content, call scraperRequest with
actor "scraper.google.search" and input {"q": "<the search terms>"}, read the
organic_results, and answer from those. Do not answer from memory when the
question is about current prices, rankings, or availability.
Trong một Quy Trình, bạn ghim actor vào nút Công cụ và để một nút upstream cung cấp chỉ câu truy vấn. Bởi vì input là một tham số chuỗi, mẫu đáng tin cậy là một nút Code xây dựng văn bản JSON:
python
def main(query: str) -> dict:
import json
return {"payload": json.dumps({"q": query, "tbm": "lcl"})}
Kết nối payload vào trường input của nút Công cụ. Tài liệu tài liệu công cụ của Dify bao quát việc kết nối nút xung quanh một cách sâu hơn.
Nếu Bạn Tự Lưu Trữ Dify
Các phiên bản tự lưu trữ định tuyến HTTP công cụ thông qua một ssrf_proxy container chuyên dụng thay vì để cho container API tiếp cận internet trực tiếp. Khi dịch vụ đó không chạy, các cuộc gọi công cụ thất bại với lỗi DNS — [Errno -3] Temporary failure in name resolution — mà đọc như một URL bị hỏng thay vì một container bị thiếu. Khởi động stack compose đầy đủ, không chỉ api và web, và cùng một công cụ hoạt động giống hệt như trên Cloud.
Hành vi trong hướng dẫn này được đo lường trên một phiên bản tự lưu trữ 1.16.1: lược đồ đã phân tích thành một công cụ, bài kiểm tra xác thực trả về 15,648 byte JSON SERP với Custom là tiền tố và một chuỗi 401 với Basic, và nhà cung cấp đã lưu liệt kê scraperRequest là một công cụ có thể gắn vào.
Kết Luận
Plugin Marketplace bao phủ một chuỗi truy vấn. Một công cụ tùy chỉnh bao phủ điểm cuối phía sau nó, đó là những gì một luồng dẫn cần khi nó bắt đầu đọc các gói địa phương, phân trang qua chúng, và làm sạch các trường trước khi chúng đến bất cứ đâu.
Chi phí thiết lập là một tệp OpenAPI và bốn trường xác thực — hai trong số đó Dify điền sai mặc định. Đảm bảo những điều đó đúng và mọi diễn viên trong gia đình trở nên có sẵn cho mọi ứng dụng trong không gian làm việc, với một nút Code thực hiện việc định hình giữ cho tải trọng nhỏ và các cột sạch sẽ.
Sẵn sàng để kết nối chưa? Bắt đầu với một tài khoản Scrapeless miễn phí, lấy khóa API của bạn, và dán lược đồ trên vào không gian làm việc của bạn. Giới hạn về sử dụng và kế hoạch được liệt kê trên trang giá Scrapeless.
Câu Hỏi Thường Gặp
Q: Tôi có nên sử dụng plugin Deep SerpApi hay một công cụ tùy chỉnh?
Sử dụng plugin khi một truy vấn Google đơn giản là tất cả những gì bạn cần — nó mở ra một công cụ với một tham số query đơn. Sử dụng một công cụ tùy chỉnh khi bạn cần gói địa phương, độ lệch trang, danh sách Amazon, hoặc bất kỳ diễn viên nào khác, vì những tham số đó không thể truy cập qua trường đơn đó.
Q: Tại sao công cụ tùy chỉnh Dify của tôi trả về 401 khi cùng một khóa hoạt động trên curl?
Hai giá trị mặc định của Dify gửi khóa ở một dạng mà API không đọc. Tên tiêu đề mặc định là Authorization thay vì x-api-token, và tiền tố tiêu đề mặc định là Basic, khiến Dify gửi x-api-token: Basic <key>. Đặt tên tiêu đề thành x-api-token và tiền tố thành Custom.
Q: Tại sao trường input là một chuỗi thay vì một đối tượng?
Dify làm phẳng các thuộc tính body yêu cầu lồng nhau khi nó phân tích một tài liệu OpenAPI, vì vậy một đối tượng lồng nhau trở thành một tham số chuỗi. Dify chấp nhận cả hai dạng và chuẩn hóa nó trước khi yêu cầu được gửi đi, vì vậy một nút Code phát ra json.dumps(...) là cách đáng tin cậy để tạo nó trong một Quy Trình. Một cuộc gọi trực tiếp đến điểm cuối nghiêm ngặt hơn và yêu cầu một đối tượng.
Q: Điều này có hoạt động trên Dify Cloud cũng như tự lưu trữ không?
Có. Công cụ tùy chỉnh là một tài liệu OpenAPI cộng với các thông tin xác thực, không cần cài đặt gì ở cả hai bên. Các phiên bản tự lưu trữ có một yêu cầu bổ sung: container ssrf_proxy phải đang chạy, vì HTTP egress của công cụ được định tuyến qua nó.
Q: Một yêu cầu trả về bao nhiêu kết quả?
Một tìm kiếm trên web đã trả về tám kết quả tự nhiên trong quá trình chụp được sử dụng cho hướng dẫn này, và số lượng kết quả thay đổi theo truy vấn. Gói địa phương trả về 20 địa điểm mỗi yêu cầu, và start: 20 lấy trang tiếp theo; các trang liên tiếp của một truy vấn chồng chéo nhau một chút, vì vậy hãy loại bỏ trùng lặp khi ghi.
Q: Làm thế nào để tôi ngăn chặn phản hồi từ Amazon làm ngập ngụt ngữ cảnh của mô hình?
Chọn result trong một nút Code được đặt sau nút Tool. Một cuộc gọi sản phẩm đã trả về 2.226.755 byte, trong đó 1.960.588 là trường html thô và chỉ 4.608 là sản phẩm đã phân tích, vì vậy việc trả về {"product": response["result"]} giữ mọi thứ hữu ích và loại bỏ phần còn lại.
Q: Một công cụ tùy chỉnh có thể bao phủ nhiều diễn viên không?
Có, và đó là mục đích của thiết kế. Điểm cuối nhận actor cộng với input, vì vậy một hoạt động scraperRequest đơn lẻ tiếp cận mọi diễn viên mà tài khoản của bạn có quyền truy cập. Thêm một vào enum trong sơ đồ sẽ hiển thị nó trong trình tạo yêu cầu mà không cần một công cụ thứ hai.
Q: API key nên được lưu ở đâu?
Trong trường thông tin xác thực của nhà cung cấp công cụ, mà Dify lưu trữ như một bí mật và tiêm vào thời điểm gọi. Giữ nó ở đó thay vì trong tham số nút có nghĩa là một quy trình xuất khẩu hoặc một ứng dụng sao chép sẽ không mang theo khóa cùng với nó.
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.



