Activepieces + Scrapeless: Dòng Lãnh Đạo Địa Phương Không Mã
Web Data Collection Specialist
Tóm tắt:
- Activepieces đạt được dữ liệu tìm kiếm trực tiếp với phần HTTP tích hợp sẵn, vì vậy một quy trình dẫn không cần phần tùy chỉnh, không cần gói đã công bố và không cần dịch vụ để lưu trữ.
- Diễn viên tìm kiếm Google trả về khoảng 20 doanh nghiệp địa phương mỗi yêu cầu — các ghi chú được hạ cánh vào 20, 21 và 22 — vì vậy một quy trình địa phương thường chỉ cần một cuộc gọi cộng thêm một khóa loại bỏ trùng lặp thay vì một vòng lặp phân trang.
- Phản hồi đã phân tích nằm dưới
body, điều này làm{{step_1.body.local_results.places}}trở thành tham chiếu hoạt động; bỏbodyvà vòng lặp chạy không lần nào bên trong một quy trình vẫn báo cáo thành công. - Trường
phonegiữ một số điện thoại chỉ trong khoảng một nửa các bản ghi — phần còn lại mang giờ mở cửa hoặc nhãn dịch vụ — vì vậy một phần Code phải xác thực nó, không chỉ cắt bớt. - Lưu trữ khóa API như một giá trị cấp dự án thay vì nhập nó vào trường tiêu đề, vì các quy trình được xuất khẩu và chia sẻ.
Điều gì mà quy trình này mang lại cho bạn
Một quy trình Activepieces hoạt động biến một danh mục và một thành phố thành các hàng doanh nghiệp địa phương — tên, danh mục, xếp hạng, số lượng đánh giá và điện thoại — sẵn sàng cho một CRM, một bảng tính hoặc một cơ sở dữ liệu.
Activepieces tổ chức các ứng dụng tốt và không lấy các trang. Kết quả tìm kiếm đến từ Deep SerpApi thông qua diễn viên scraper.google.search, diễn viên này trả về gói địa phương đã phân tích dưới dạng JSON. Quy trình dưới đây được xây dựng trên một phiên bản Activepieces 0.82.0 tự lưu trữ với piece-http 0.11.18.
Điều kiện tiên quyết
- Một phiên bản Activepieces, đám mây hoặc tự lưu trữ
- Một khóa API Scrapeless — tạo một tài khoản miễn phí
- Một phần đích cho các hàng: Google Sheets, Airtable, Postgres, hoặc CRM của bạn
Đặt khóa vào giá trị cấp dự án hoặc kết nối, không phải trong trường tiêu đề của bước. Định nghĩa quy trình mang các giá trị trường của nó, và các quy trình được xuất khẩu, sao chép và chia sẻ giữa các dự án.
Cấu hình bước HTTP
Thêm HTTP → Gửi yêu cầu HTTP và điền vào năm trường:
| Trường | Giá trị |
|---|---|
| Phương thức | POST |
| URL | https://api.scrapeless.com/api/v1/scraper/request |
| Tiêu đề | x-api-token → khóa của bạn |
| Loại nội dung | JSON |
| Nội dung | đối tượng bên dưới |
json
{
"actor": "scraper.google.search",
"input": {
"q": "plumbers in Austin, TX",
"tbm": "lcl"
}
}
tbm được đặt thành lcl là cái trả về doanh nghiệp thay vì các trang web. Truy vấn cần ý định địa phương: "plumbers in Austin, TX" trả về một gói địa phương, trong khi "plumbing" trống thường không.
Trước khi đấu dây phần còn lại của quy trình, xác nhận yêu cầu bên ngoài trình tạo. Gọi giống như từ một shell cho biết liệu một kết quả trống là lỗi của truy vấn hay của quy trình:
bash
curl -sS -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":"plumbers in Austin, TX","tbm":"lcl"}}' \
| python3 -c 'import json, sys
data = json.load(sys.stdin)
places = (data.get("local_results") or {}).get("places") or []
print(len(places), "places")
if places:
print("raw phone:", repr(places[0]["phone"]), "| raw type:", repr(places[0]["type"]))
else:
print("no local pack in this response; top-level keys were", sorted(data))'
Điều đó in số lượng địa điểm và bản ghi đầu tiên của phone và type - hai trường đến lớp bên ngoài. Đọc các khóa trên nhánh else thay vì lập chỉ mục trực tiếp vào local_results là thói quen mà quy trình cần: kiểm tra rằng hình dạng bạn mong đợi có mặt trước khi bạn xử lý vào nó.
Điều gì được trả lại
Một lần chạy thành công trả về khoảng 20 địa điểm dưới local_results.places, mỗi cái mang title, type, rating, reviews, phone, và address. Những chuyển khoản đã hạ cánh vào 20, 21 và 22 địa điểm cho cùng một truy vấn, vì vậy hãy coi kích thước trang là gần đúng thay vì cố định: thêm "start": 20 vào đối tượng input cho trang tiếp theo, và loại bỏ trùng lặp dựa trên tên cộng thêm số điện thoại thay vì giả định giới hạn trang chính xác.
Với tbm được đặt thành lcl, phong bì là local_results, metadata, pagination, và search_information - không organic_results và không related_searches. Một cuộc gọi bị từ chối trả về một phong bì mang code và message thay vì bất kỳ kết quả nào, đó là lý do mà quy trình nên phân nhánh theo sự hiện diện của local_results thay vì chỉ dựa trên trạng thái HTTP.
Đường dẫn tham chiếu là phần đáng được chính xác. Trong Activepieces, JSON đã phân tích sống dưới body:
| Tham chiếu | Kết quả |
|---|---|
{{step_1.body.local_results.places}} |
mảng các địa điểm |
{{step_1.body.organic_results}} |
kết quả web, khi tbm bị bỏ qua |
{{step_1.organic_results}} |
không có gì — không có lỗi, không có cảnh báo |
Hàng cuối cùng là cái đắt giá. Một tham chiếu thiếu đoạn body giải quyết thành không có gì, bước Lặp trên các mục lặp qua không lần nào, và lần chạy vẫn kết thúc thành công. Một bảng đích trống trông giống hệt nhau mặc dù truy vấn trả về không có gì hoặc tham chiếu sai, vì vậy hãy kiểm tra đường dẫn trước.
Thêm Lặp trên các mục trên {{step_1.body.local_results.places}} để mỗi doanh nghiệp được xử lý như một mục riêng biệt thay vì một khối viết vào một ô duy nhất.
Xây dựng điều này trên gói miễn phí là đủ để đạt được phản hồi đầy đủ từ local-pack — bắt đầu với một tài khoản Scrapeless và giữ khóa trong giá trị dự án.
Chuẩn hóa Trước Khi Lưu Trữ
Hai hành vi quyết định liệu các hàng của bạn có sử dụng được hay không, và hành vi thứ hai là lý do tại sao một luồng khách hàng cần mã hóa.
Chuỗi đến với khoảng trắng. phone, type, và hours có một khoảng trắng ở đầu — " Plumber", " (512) 690-4935". Điều đó không phải là thẩm mỹ: một số điện thoại có khoảng trắng dùng làm khóa loại bỏ trùng lặp tạo ra một bản ghi thứ hai cho cùng một doanh nghiệp trong lần chạy tiếp theo, và một bộ lọc danh mục trên "Plumber" không khớp gì cả. khuyến nghị kế hoạch đánh số ITU-T là lý do để chuẩn hóa một số điện thoại thành dạng chuẩn trước khi nó trở thành một định danh.
Nhiều trường có mặt nhưng không mang lại giá trị sử dụng. Trong cùng một lần thu thập, place_id, thumbnail, và lsig đều trống rỗng trong tất cả 20 bản ghi. gps_coordinates là cái bẫy: nó có mặt dưới dạng {"latitude": 0, "longitude": 0}, vì vậy một kiểm tra tính xác thực đã vượt qua và một bước ánh xạ đã vẽ mỗi doanh nghiệp tại cùng một điểm trên đường xích đạo. Lấy vị trí từ address và xem cặp tọa độ là vắng mặt trừ khi cả hai giá trị đều khác không.
Trường phone không phải lúc nào cũng là số điện thoại. Trong một lần thu thập 20 vị trí cho "plumbers in Austin, TX", chỉ có 11 bản ghi mang giá trị hình dạng số điện thoại. Chín bản còn lại chứa văn bản giờ mở cửa như " Closes 6 PM " hoặc nhãn dịch vụ như "Online estimates". Ánh xạ trường đó thẳng vào một cột CRM và gần một nửa các hàng đến mà không sử dụng được, mà không có lỗi nào trong luồng. Một số chuỗi giờ đó cũng chứa khoảng trắng không ngắt (U+202F) thay vì khoảng trắng bình thường, vì vậy một phép chia thô trên " " hoạt động một cách không mong đợi ngay cả sau khi cắt bỏ.
Xác thực trường thay vì tin tưởng vào tên của nó, và giữ lại văn bản bị loại bỏ thay vì vứt bỏ nó:
Thêm một Mã vào giữa yêu cầu và đích đến. Activepieces gói nội dung cơ thể dưới dạng export const code = async (inputs) => { … }; logic bên trong là JavaScript đơn giản:
javascript
// `phone` sometimes carries opening hours or a service label instead of a number,
// so the value is validated before it becomes a contact field.
const PHONE = /\(?\d{3}\)?[ -]?\d{3}-?\d{4}/;
const code = async (inputs) => {
const clean = (value) => (typeof value === 'string' ? value.trim() : value);
const places = inputs.response?.local_results?.places ?? [];
return places.map((place) => {
const contact = clean(place.phone) ?? '';
const isPhone = PHONE.test(contact);
return {
name: clean(place.title),
category: clean(place.type),
rating: place.rating ?? null,
reviews: place.reviews ?? 0,
phone: isPhone ? contact : null,
phone_field_note: isPhone ? null : contact,
address_snippet: clean(place.address),
};
});
};
const sample = {
response: {
local_results: {
places: [
{
title: 'Radiant Plumbing, Air Conditioning, & Electrical',
type: ' Plumber',
rating: 4.8,
reviews: 18000,
phone: ' (512) 690-4935',
address: '25+ years in business \u00b7 Austin, TX',
},
{
title: 'Beyond Wow Plumbing & Drains',
type: ' Plumber',
rating: 4.9,
phone: ' Closes 6\u202fPM ',
address: 'Austin, TX',
},
],
},
},
};
code(sample).then((rows) => console.log(JSON.stringify(rows, null, 2)));
Chuyển {{step_1.body}} vào đầu vào response của phần. Hai chi tiết quan trọng ở đây. Giá trị mặc định ?? 0 tồn tại vì một doanh nghiệp không có đánh giá không có khóa reviews nào cả, và một cột đích số từ chối undefined trong khi chấp nhận 0. Và phone_field_note giữ bất cứ thứ gì đã chiếm trường khi nó không phải là số, vì vậy một nhà điều hành có thể thấy rằng một hàng có giờ mở cửa thay vì một số điện thoại bị thiếu.
Điểm số và số lượng đánh giá là hai trường đáng giữ ở dạng số. Mọi thứ khác là văn bản, và nếu luồng kết thúc trong việc xuất bảng tính thay vì cơ sở dữ liệu, đặc tả định dạng giá trị phân tách bằng phẩy quyết định cách mà tên doanh nghiệp chứa dấu phẩy tồn tại trong chuyến đi vòng.
Xử Lý Dữ Liệu Liên Hệ Doanh Nghiệp Một Cách Có Trách Nhiệm
Luồng này thu thập thông tin liên hệ doanh nghiệp, vì vậy một vài nghĩa vụ đi kèm với nó. Chỉ thu thập từ kết quả tìm kiếm công khai và chỉ những trường mà quy trình làm việc cần. Giữ một cơ sở hợp pháp để lưu trữ dữ liệu liên hệ và tôn trọng yêu cầu từ chối, vì số điện thoại doanh nghiệp vẫn có thể xác định một hộ kinh doanh cá thể như một cá nhân — Quy định Bảo vệ Dữ liệu Chung áp dụng cho dữ liệu cá nhân ngay cả trong bối cảnh thương mại, và các quy tắc tương đương tồn tại ở các khu vực pháp lý khác. Tôn trọng các điều khoản của từng nền tảng đích cho khách hàng nhập khẩu, đặt một khoảng thời gian lưu giữ thay vì giữ các hàng mãi mãi, và tuân theo các quy tắc đồng ý về tiếp thị của quốc gia mà bạn đang liên lạc. Không điều nào trong số này là tư vấn pháp lý; kiểm tra các nghĩa vụ của bạn trước khi bạn thực hiện liên hệ.
Kết Luận
Ba phần tạo nên toàn bộ luồng: HTTP để gọi tác nhân, Mã để cắt giảm và mặc định các trường, Vòng lặp trên Các Mục để viết một hàng cho mỗi doanh nghiệp. Chế độ thất bại cần theo dõi nằm trong đường dẫn tham chiếu: bỏ body và một lần chạy thành công ghi một bảng trống.
Từ đây, hoán đổi truy vấn cho một danh sách các thành phố và cùng một luồng trở thành một xây dựng lãnh thổ. Hướng dẫn tích hợp Make đề cập cùng một yêu cầu từ một công cụ không mã khác, và xây dựng giám sát Dify cho thấy phiên bản do tác nhân điều khiển của cùng một tác nhân.
Sẵn sàng để xây dựng nó? Xem tài liệu Deep SerpApi để biết toàn bộ tập tham số, so sánh các gói và khối lượng được bao gồm, và bắt đầu với gói miễn phí.
Câu hỏi thường gặp
H: Tôi có cần một phần Activepieces tùy chỉnh để sử dụng Scrapeless không?
Không. Phần HTTP có sẵn bao trùm mọi tác nhân, vì API chỉ cần một POST với một trường actor và một đối tượng input. Một phần tùy chỉnh chỉ hữu ích nếu bạn muốn một bước mang thương hiệu với các trường kiểu cho một nhóm không nên thấy yêu cầu thô, và đó là một quyết định đóng gói thay vì một khả năng.
H: Tại sao bước Lặp trên Mục của tôi lặp lại về số lần bằng không khi bước HTTP thành công?
Phản hồi đã phân tích được lồng dưới body, vì vậy {{step_1.local_results.places}} không có giá trị trong khi {{step_1.body.local_results.places}} có giá trị là mảng. Một tham chiếu bị thiếu không gây ra lỗi, vì vậy dòng chảy báo cáo thành công mà không có vòng lặp. Kiểm tra đường dẫn tham chiếu trước khi điều tra truy vấn.
H: Một yêu cầu trả về bao nhiêu kết quả, và làm thế nào để tôi có được nhiều hơn?
Một yêu cầu gói địa phương trả về khoảng 20 địa điểm; các lần lặp lại của một truy vấn trả về 20, 21 và 22. Thêm "start": 20 vào đối tượng input cho trang tiếp theo, "start": 40 cho trang tiếp theo nữa, và cứ thế. Vì kích thước trang không hoàn toàn cố định, hãy loại bỏ trùng lặp dựa trên tên cộng với số điện thoại thay vì tin tưởng vào các bù trừ, và xem một trang cuối ngắn như là kết thúc của tập hợp.
H: Tại sao place_id và gps_coordinates không thể sử dụng trên kết quả địa phương?
place_id, thumbnail, và lsig đều quay về trống trên mỗi bản ghi gói địa phương, vì vậy một dòng cần place_id sẽ loại bỏ tất cả 20 kết quả. gps_coordinates hoạt động khác và nguy hiểm hơn: nó được điền với {"latitude": 0, "longitude": 0}, cái mà sống sót qua kiểm tra trống trong khi chỉ vào cùng một tọa độ. Sử dụng address cho vị trí và chỉ tin tưởng vào cặp tọa độ khi cả hai số đều khác không.
H: API key nên được đặt ở đâu trong một dòng Activepieces?
Trong một giá trị cấp dự án hoặc một kết nối, được tham chiếu từ trường tiêu đề. Các định nghĩa dòng chảy mang các giá trị trường tĩnh và được xuất và sao chép giữa các dự án, vì vậy một khóa nhập trực tiếp vào bước sẽ theo mọi bản sao.
H: Dòng này có thể chạy theo lịch thay vì webhook không?
Có. Thay thế kích hoạt bằng Lịch và phần còn lại của dòng chảy không thay đổi, đó là hình dạng thông thường cho một lần làm mới lãnh thổ. Giữ tần suất chạy khớp với tần suất mà thứ hạng địa phương thực sự di chuyển; hàng ngày là đủ cho hầu hết các danh mục, và một nhịp điệu chậm hơn giúp khối lượng trở nên dễ đoán.
H: Dòng chảy giống như vậy có hoạt động cho kết quả web thay vì doanh nghiệp không?
Có. Bỏ tbm từ đối tượng input và kết quả sẽ xuất hiện dưới {{step_1.body.organic_results}} thay thế, mỗi cái với title, link, và snippet. Bộ mã cần được cập nhật đường dẫn để phù hợp, và việc cắt bớt là không cần thiết trên các kết quả web.
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.



