Integracja A-Parser z Redis: zaawansowane API
Porównanie z HTTP API
A-Parser Redis API został opracowany w celu zastąpienia metod oneRequest i bulkRequest dla bardziej wydajnej implementacji i wsparcia dodatkowych scenariuszy użycia:
- jako serwer zapytań i wyników występuje Redis
- możliwość odpytywania o wyniki asynchronicznie lub w trybie blokującym
- możliwość podłączenia wielu scraperów (zarówno na jednym, jak i na różnych serwerach) do przetwarzania zapytań z jednym punktem wejścia
- możliwość ustawienia liczby wątków do przetwarzania zapytań i przeglądania logów pracy
- możliwość organizacji timeoutów dla operacji
- automatyczne wygasanie (Expire) nieodebranych wyników
Przedwstępna konfiguracja
W przeciwieństwie do A-Parser HTTP API, aby korzystać z Redis API, należy wcześniej skonfigurować i uruchomić zadanie ze scraperem
API::Server::Redis:
- zainstalować i uruchomić serwer Redis (lokalnie lub zdalnie)
- utworzyć preset ustawień dla scrapera
API::Server::Redis, wskazując:Redis Host- adres serwera Redis, domyślnie127.0.0.1Redis Port- port serwera Redis, domyślnie6379Redis Queue Key- nazwa klucza do wymiany danych z A-Parser, domyślnieaparser_redis_api, możesz tworzyć oddzielne kolejki i przetwarzać je różnymi zadaniami lub różnymi kopiami A-ParserResult Expire(TTL)- czas życia wyniku w sekundach, służy do automatycznej kontroli i usuwania nieodebranych wyników, domyślnie3600sekund (1 godzina)
- dodać zadanie ze scraperem
API::Server::Redis- jako zapytania należy podać
{num:1:N}, gdzieNpowinno odpowiadać liczbie wątków wskazanej w zadaniu - możesz również włączyć opcję prowadzenia logu, dzięki czemu dostępna będzie możliwość przeglądania logu dla każdego zapytania
- jako zapytania należy podać
Przykład konfiguracji zadania z
API::Server::Redis

Uruchomienie A-Parser wraz z Redis używając docker-compose
Przy takim sposobie uruchomienia jako adres serwera Redis (Redis Host) zamiast IP można podać nazwę usługi, w poniższych przykładach jest to redis
Jeśli A-Parser nie był wcześniej uruchamiany przez docker-compose
- Pobierz i rozpakuj dystrybucję (jednorazowy link należy wcześniej pobrać ze Strefy użytkownika, jak opisano tutaj):
curl -O https://a-parser.com/members/onetime/ce42f308eaa577b5/aparser.tar.gz
tar zxf aparser.tar.gz
rm -f aparser.tar.gz
Utwórz plik
docker-compose.ymli umieść w nim następującą treść:- Podstawowy wariant bez hasła i otwierania portu, Redis będzie dostępny tylko wewnątrz sieci 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- Wariant z hasłem i otwieraniem portu, Redis będzie dostępny z zewnątrz, dlatego zdecydowanie zaleca się użycie hasła
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 TU_HASŁO_DLA_REDIS
ports:
- 6379:6379Zamiast TU_HASŁO_DLA_REDIS wymyśl i podaj hasło, które będzie używane przy autoryzacji w Redis.
Uruchom kontenery:
docker compose up -d
Jeśli A-Parser był już wcześniej uruchomiony przez docker-compose
Edytuj plik
docker-compose.ymldodając na końcu następującą treść:- Podstawowy wariant bez hasła i otwierania portu, Redis będzie dostępny tylko wewnątrz sieci Docker
redis:
image: redis:latest
restart: always- Wariant z hasłem i otwieraniem portu, Redis będzie dostępny z zewnątrz, dlatego zdecydowanie zaleca się użycie hasła
redis:
image: redis:latest
restart: always
command: redis-server --requirepass TU_HASŁO_DLA_REDIS
ports:
- 6379:6379Zamiast TU_HASŁO_DLA_REDIS wymyśl i podaj hasło, które będzie używane przy autoryzacji w Redis.
Uruchom kontenery:
docker compose up -d
Jeśli A-Parser został już uruchomiony i jego konfiguracja się nie zmieniła, nie zostanie on zrestartowany, a Docker po prostu doda i uruchomi Redis.
Wykonywanie zapytań
Działanie Redis API opiera się na Redis Lists (listach), operacje na listach pozwalają dodawać do kolejki nieograniczoną liczbę zapytań (ograniczoną pamięcią RAM), a także odbierać wyniki w trybie blokującym z timeoutem (blpop) lub w trybie asynchronicznym (lpop).
- wszystkie ustawienia, oprócz
useproxy,proxyCheckeriproxybannedcleanupsą pobierane z presetu wywoływanego scrapera +overrideOpts - ustawienia
useproxy,proxyCheckeriproxybannedcleanupsą pobierane z presetu
API::Server::Redis + overrideOpts
Zapytanie dodaje się do Redis komendą lpush, każde zapytanie składa się z tablicy [queryId, parser, preset, query, overrideOpts, apiOpts] zserializowanej za pomocą JSON:
parser,preset,queryodpowiadają analogicznym parametrom dla zapytania APIoneRequestqueryId- tworzone wraz z zapytaniem, zalecamy użycie numeru porządkowego z bazy danych lub dobrego generatora losowego, na podstawie tego ID będzie można odebrać wynikoverrideOpts- nadpisywanie ustawień dla presetu scraperaapiOpts- dodatkowe parametry przetwarzania API
Przy zapytaniach przez Redis etap formatowania wyniku jest pomijany, ponieważ cały wynik jest przekazywany w formacie JSON do dalszego przetwarzania programowego.
redis-cli
Przykład wykonywania zapytań, do testowania można użyć 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.....
Różne przypadki użycia
Asynchroniczne sprawdzanie dostępności wyniku
lpop aparser_redis_api:some_unique_id
Zwróci wynik, jeśli został już przetworzony, lub nil, jeśli zapytanie jest nadal w trakcie przetwarzania
Blokujące odbieranie wyniku
blpop aparser_redis_api:some_unique_id 0
To zapytanie zostanie zablokowane do momentu otrzymania wyniku, możesz również określić maksymalny timeout na otrzymanie wyniku, po którym komenda zwróci nil
Zapisywanie wyników do wspólnej kolejki
Domyślnie A-Parser zapisuje wynik dla każdego zapytania pod jego unikalnym kluczem aparser_redis_api:query_id, co pozwala na organizację wielowątkowego przetwarzania, wysyłając zapytania i odbierając wyniki oddzielnie dla każdego wątku
W niektórych przypadkach konieczne jest przetwarzanie wyników w jednym wątku w miarę ich napływania, w takim przypadku wygodniej jest zapisywać wyniki do wspólnej kolejki wyników (klucz musi różnić się od klucza dla zapytań)
W tym celu należy podać klucz output_queue dla apiOpts:
lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru", {}, {"output_queue": "aparser_results"}]'
Odbieranie wyniku ze wspólnej kolejki:
127.0.0.1:6379> blpop aparser_results 0
1) "aparser_results"
2) "{\"queryId\":\"some_unique_id\",\"results\":{\"data\":\"<!DOCTYPE html><html class=...
Przykład implementacji (przypadek SpySERP)
Załóżmy, że tworzymy serwis SaaS, który dokonuje oceny parametrów domen, dla uproszczenia będziemy sprawdzać datę rejestracji domeny
Nasz serwis składa się z 2 stron:
/index.php- strona landing page, na której znajduje się formularz wprowadzania domeny/results.php?domain=google.com- strona z wynikami działania serwisu
Dla poprawy doświadczenia użytkownika chcemy, aby strony naszego serwisu ładowały się błyskawicznie, a proces oczekiwania na dane wyglądał naturalnie i wyświetlał loader
Przy zapytaniu do results.php w pierwszej kolejności wykonujemy zapytanie do A-Parser Redis API, tworząc unikalny request_id:
lpush aparser_redis_api '["request-1", "Net::Whois", "default", "google.com", {}, {}]'
Następnie możemy wyświetlić stronę użytkownikowi i pokazać loader w obszarze wyświetlania danych, dzięki brakowi opóźnień odpowiedź serwera będzie ograniczona tylko prędkością połączenia Redis (zazwyczaj w granicach 10ms)
A-Parser rozpocznie przetwarzanie zapytania jeszcze zanim przeglądarka użytkownika otrzyma pierwszą treść, po tym jak przeglądarka załaduje wszystkie niezbędne zasoby i skrypty, możemy wyświetlić wynik, w tym celu wysyłamy zapytanie AJAX po dane:
/get-results.php?request_id=request-1
Skrypt get-results.php wykonuje blokujące zapytanie do Redis z timeoutem 15 sekund:
blpop aparser_redis_api:request-1 15
I zwraca odpowiedź natychmiast po jej otrzymaniu od A-Parser, jeśli otrzymaliśmy pusty wynik po upływie timeoutu, możemy wyświetlić użytkownikowi błąd pobierania danych
W ten sposób, wysyłając zapytanie do A-Parser przy pierwszym otwarciu strony (/results.php), skracamy niezbędny czas oczekiwania na dane dla użytkownika (/get-results.php) o czas, który przeglądarka użytkownika spędza na oczekiwaniu na treść, ładowaniu skryptów i wykonywaniu zapytania AJAX