Tích hợp A-Parser với Redis: API nâng cao
So sánh với HTTP API
A-Parser Redis API được phát triển để thay thế các phương thức oneRequest và bulkRequest nhằm triển khai hiệu suất cao hơn và hỗ trợ các kịch bản sử dụng bổ sung:
- Redis đóng vai trò là máy chủ truy vấn và kết quả
- khả năng yêu cầu kết quả không đồng bộ hoặc ở chế độ chặn (blocking)
- khả năng kết nối nhiều công cụ cào dữ liệu (trên cùng một hoặc các máy chủ khác nhau) để xử lý truy vấn với một điểm đầu vào duy nhất
- khả năng thiết lập số luồng để xử lý truy vấn và xem nhật ký hoạt động
- khả năng tổ chức thời gian chờ (timeout) cho các hoạt động
- tự động Expire các kết quả không được yêu cầu
Chủ đề thảo luận trên diễn đàn
Thiết lập sơ bộ
Khác với A-Parser HTTP API, để sử dụng Redis API, bạn cần cấu hình trước và chạy một tác vụ với công cụ cào dữ liệu
API::Server::Redis:
- cài đặt và chạy máy chủ Redis (cục bộ hoặc từ xa)
- tạo một bản thiết lập sẵn (preset) cho công cụ cào dữ liệu
API::Server::Redis, chỉ định:Redis Host- địa chỉ máy chủ Redis, mặc định là127.0.0.1Redis Port- cổng máy chủ Redis, mặc định là6379Redis Queue Key- tên khóa để trao đổi dữ liệu với A-Parser, mặc định làaparser_redis_api, bạn có thể tạo các hàng đợi riêng biệt và xử lý chúng bằng các tác vụ khác nhau hoặc các bản sao A-Parser khác nhauResult Expire(TTL)- thời gian sống của kết quả tính bằng giây, dùng để tự động kiểm soát và xóa các kết quả không được yêu cầu, mặc định là3600giây (1 giờ)
- thêm một tác vụ với công cụ cào dữ liệu
API::Server::Redis- trong phần truy vấn cần chỉ định
{num:1:N}, trong đóNphải tương ứng với số luồng được chỉ định trong tác vụ - bạn cũng có thể bật tùy chọn ghi nhật ký, nhờ đó sẽ có thể xem nhật ký cho từng truy vấn
- trong phần truy vấn cần chỉ định
Ví dụ cấu hình tác vụ với
API::Server::Redis

Khởi chạy A-Parser cùng với Redis bằng docker-compose
Với phương pháp khởi chạy này, thay vì địa chỉ IP, bạn có thể chỉ định tên dịch vụ làm địa chỉ máy chủ Redis (Redis Host), trong các ví dụ dưới đây là redis
Nếu A-Parser chưa từng được chạy qua docker-compose trước đây
- Tải xuống và giải nén bộ cài đặt (trước tiên cần lấy liên kết một lần trong Khu vực Thành viên, như được mô tả tại đây):
curl -O https://a-parser.com/members/onetime/ce42f308eaa577b5/aparser.tar.gz
tar zxf aparser.tar.gz
rm -f aparser.tar.gz
Tạo tệp
docker-compose.ymlvà đặt nội dung sau vào đó:- Phương án cơ bản không có mật khẩu và không mở cổng, Redis sẽ chỉ khả dụng bên trong mạng Docker
version: '3'
services:
a-parser:
image: aparser/runtime:latest
command: ./aparser
restart: always
volumes:
- ./aparser:/app
ports:
- 9091:9091
redis:
image: redis:latest
restart: always- Phương án có mật khẩu và mở cổng, Redis sẽ khả dụng từ bên ngoài, vì vậy chúng tôi thực sự khuyên bạn nên sử dụng mật khẩu
version: '3'
services:
a-parser:
image: aparser/runtime:latest
command: ./aparser
restart: always
volumes:
- ./aparser:/app
ports:
- 9091:9091
redis:
image: redis:latest
restart: always
command: redis-server --requirepass TUY_CHON_MAT_KHAU_REDIS
ports:
- 6379:6379Thay vì MAT_KHAU_REDIS_TAI_DAY, hãy nghĩ ra và chỉ định mật khẩu sẽ được sử dụng khi xác thực vào Redis.
Khởi chạy các container:
docker compose up -d
Nếu A-Parser đã được chạy qua docker-compose trước đó
Chỉnh sửa tệp
docker-compose.ymlbằng cách thêm nội dung sau vào cuối:- Phương án cơ bản không có mật khẩu và không mở cổng, Redis sẽ chỉ khả dụng bên trong mạng Docker
redis:
image: redis:latest
restart: always- Phương án có mật khẩu và mở cổng, Redis sẽ khả dụng từ bên ngoài, vì vậy chúng tôi thực sự khuyên bạn nên sử dụng mật khẩu
redis:
image: redis:latest
restart: always
command: redis-server --requirepass TUY_CHON_MAT_KHAU_REDIS
ports:
- 6379:6379Thay vì MAT_KHAU_REDIS_TAI_DAY, hãy nghĩ ra và chỉ định mật khẩu sẽ được sử dụng khi xác thực vào Redis.
Khởi chạy các container:
docker compose up -d
Nếu A-Parser đã được chạy và cấu hình của nó không thay đổi, nó sẽ không được khởi động lại, mà Docker sẽ chỉ thêm và chạy Redis.
Thực hiện truy vấn
Hoạt động của Redis API dựa trên Redis Lists (danh sách), các thao tác trên danh sách cho phép thêm vào hàng đợi số lượng truy vấn không giới hạn (bị giới hạn bởi bộ nhớ RAM), cũng như nhận kết quả ở chế độ chặn với thời gian chờ (blpop) hoặc ở chế độ không đồng bộ (lpop).
- tất cả các cài đặt, ngoại trừ
useproxy,proxyCheckervàproxybannedcleanupđược lấy từ mẫu (preset) của công cụ cào dữ liệu được gọi +overrideOpts - các cài đặt
useproxy,proxyCheckervàproxybannedcleanupđược lấy từ preset
API::Server::Redis + overrideOpts
Truy vấn được thêm vào Redis bằng lệnh lpush, mỗi truy vấn bao gồm một mảng [queryId, parser, preset, query, overrideOpts, apiOpts] được tuần tự hóa bằng JSON:
parser,preset,querytương ứng với các tham số tương tự cho truy vấn APIoneRequestqueryId- được tạo cùng với truy vấn, chúng tôi khuyên bạn nên sử dụng số thứ tự từ cơ sở dữ liệu của bạn hoặc một số ngẫu nhiên tốt, dựa trên ID này bạn có thể nhận được kết quảoverrideOpts- ghi đè các cài đặt cho mẫu của công cụ cào dữ liệuapiOpts- các tham số xử lý API bổ sung
Khi truy vấn qua Redis, bước định dạng kết quả sẽ bị bỏ qua, vì toàn bộ kết quả được truyền dưới dạng JSON để xử lý lập trình tiếp theo.
redis-cli
Ví dụ thực hiện truy vấn, để kiểm tra bạn có thể sử dụng redis-cli:
127.0.0.1:6379> lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru"]'
(integer) 1
127.0.0.1:6379> blpop aparser_redis_api:some_unique_id 0
1) "aparser_redis_api:some_unique_id"
2) "{\"data\":\"<!DOCTYPE html><html.....
Các trường hợp sử dụng
Kiểm tra sự tồn tại của kết quả không đồng bộ
lpop aparser_redis_api:some_unique_id
Sẽ trả về kết quả nếu nó đã được xử lý hoặc nil nếu truy vấn vẫn đang trong quá trình xử lý
Nhận kết quả ở chế độ chặn
blpop aparser_redis_api:some_unique_id 0
Truy vấn này sẽ bị chặn cho đến khi nhận được kết quả, bạn cũng có thể chỉ định thời gian chờ tối đa để nhận kết quả, sau đó lệnh sẽ trả về nil
Lưu kết quả vào một hàng đợi duy nhất
Theo mặc định, A-Parser lưu kết quả cho mỗi truy vấn dưới khóa duy nhất của nó aparser_redis_api:query_id, cho phép tổ chức xử lý đa luồng, gửi truy vấn và nhận kết quả riêng biệt cho mỗi luồng
Trong một số trường hợp, cần xử lý kết quả trong một luồng khi chúng đến, trong trường hợp này sẽ thuận tiện hơn khi lưu kết quả vào một hàng đợi kết quả duy nhất (khóa phải khác với khóa cho các truy vấn)
Để làm điều này, cần chỉ định khóa output_queue cho apiOpts:
lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru", {}, {"output_queue": "aparser_results"}]'
Nhận kết quả từ hàng đợi chung:
127.0.0.1:6379> blpop aparser_results 0
1) "aparser_results"
2) "{\"queryId\":\"some_unique_id\",\"results\":{\"data\":\"<!DOCTYPE html><html class=...
Ví dụ triển khai (trường hợp SpySERP)
Giả sử chúng ta đang tạo một dịch vụ SaaS thực hiện đánh giá các tham số của tên miền, để đơn giản chúng ta sẽ kiểm tra ngày đăng ký tên miền
Dịch vụ của chúng ta gồm 2 trang:
/index.php- trang landing, trên đó có biểu mẫu nhập tên miền/results.php?domain=google.com- trang hiển thị kết quả hoạt động của dịch vụ
Để cải thiện trải nghiệm người dùng, chúng ta muốn các trang của dịch vụ tải ngay lập tức, và quá trình chờ đợi dữ liệu trông tự nhiên và hiển thị trình tải (loader)
Khi có yêu cầu tới results.php, trước tiên chúng ta thực hiện yêu cầu tới A-Parser Redis API, tạo một request_id duy nhất:
lpush aparser_redis_api '["request-1", "Net::Whois", "default", "google.com", {}, {}]'
Sau đó, chúng ta có thể hiển thị trang cho người dùng và hiển thị trình tải trên khu vực hiển thị dữ liệu, nhờ việc không có độ trễ, phản hồi của máy chủ sẽ chỉ bị giới hạn bởi tốc độ kết nối Redis (thường trong khoảng 10ms)
A-Parser sẽ bắt đầu xử lý truy vấn ngay cả trước khi trình duyệt của người dùng nhận được nội dung đầu tiên, sau khi trình duyệt tải xong tất cả các tài nguyên và tập lệnh cần thiết, chúng ta có thể hiển thị kết quả, để làm điều này chúng ta gửi yêu cầu AJAX để lấy dữ liệu:
/get-results.php?request_id=request-1
Tập lệnh get-results.php thực hiện truy vấn chặn tới Redis với thời gian chờ 15 giây:
blpop aparser_redis_api:request-1 15
Và trả về phản hồi ngay khi nó được nhận từ A-Parser, nếu chúng ta nhận được kết quả bằng không do hết thời gian chờ, chúng ta có thể hiển thị lỗi lấy dữ liệu cho người dùng
Do đó, bằng cách gửi yêu cầu tới A-Parser khi mở trang lần đầu (/results.php), chúng ta rút ngắn thời gian chờ đợi dữ liệu cần thiết cho người dùng (/get-results.php) bằng khoảng thời gian mà trình duyệt của người dùng dành để chờ đợi nội dung, tải các tập lệnh và thực hiện yêu cầu AJAX