メインコンテンツへスキップ

A-ParserとRedisの統合:高度なAPI

HTTP API との比較

A-Parser Redis API は、より高いパフォーマンスの実現と追加のユースケースをサポートするために、oneRequest および bulkRequest メソッドを置き換える目的で開発されました:

  • リクエストと結果のサーバーとして Redis が機能します
  • 結果を非同期またはブロッキングモードでリクエスト可能
  • 単一のエントリポイントでリクエストを処理するために、複数のスクレイパー(単一または複数のサーバー上)を接続可能
  • リクエスト処理用のスレッド数を設定し、動作ログを表示可能
  • 操作のタイムアウト設定が可能
  • 不要な結果の自動 Expire(有効期限切れ)

フォーラムのディスカッショントピック

事前設定

A-Parser HTTP APIとは異なり、Redis APIを使用するには、あらかじめスクレイパー API::Server::RedisAPI::Server::Redis を使用したタスクを設定し、実行しておく必要があります。

  • Redis サーバーをインストールして起動する(ローカルまたはリモート)
  • スクレイパー API::Server::RedisAPI::Server::Redis の設定プリセットを作成し、以下を指定します:
    • Redis Host - Redis サーバーのアドレス。デフォルトは 127.0.0.1
    • Redis Port - Redis サーバーのポート。デフォルトは 6379
    • Redis Queue Key - A-Parser とデータをやり取りするためのキー名。デフォルトは aparser_redis_api。個別のキューを作成し、異なるタスクや A-Parser の別コピーで処理することも可能です
    • Result Expire(TTL) - 結果の生存期間(秒)。不要な結果を自動的に管理・削除するために使用されます。デフォルトは 3600 秒(1時間)
  • スクレイパー API::Server::RedisAPI::Server::Redis を使用したタスクを追加します
    • クエリとして {num:1:N} を指定する必要があります。ここで N はタスクで指定されたスレッド数と一致させる必要があります
    • ログ記録オプションを有効にすることもでき、各リクエストごとのログを表示できるようになります

API::Server::RedisAPI::Server::Redis を使用したタスク設定の例

APIリクエストの取得

docker-compose を使用して A-Parser と Redis を一緒に起動する

この起動方法では、Redis サーバーのアドレス(Redis Host)として IP の代わりにサービス名を指定できます。以下の例では redis です。

A-Parser をこれまで docker-compose で起動したことがない場合

  1. ディストリビューションをダウンロードして解凍します(ワンタイムリンクは、こちらで説明されているように、あらかじめ会員エリアで取得しておく必要があります):
curl -O https://a-parser.com/members/onetime/ce42f308eaa577b5/aparser.tar.gz
tar zxf aparser.tar.gz
rm -f aparser.tar.gz
  1. docker-compose.yml ファイルを作成し、以下の内容を記述します:

    • パスワードなし・ポート開放なしの基本バリアント。Redis は 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
    • パスワードあり・ポート開放ありのバリアント。Redis が外部からアクセス可能になるため、パスワードの使用を強く推奨します。
    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 REDIS_PASSWORD_HERE
    ports:
    - 6379:6379

    REDIS_PASSWORD_HERE の部分には、Redis の認証に使用するパスワードを任意に設定してください。

  2. コンテナを起動します:

docker compose up -d

A-Parser が既に docker-compose で起動されている場合

  1. docker-compose.yml ファイルを編集し、末尾に以下の内容を追加します:

    • パスワードなし・ポート開放なしの基本バリアント。Redis は Docker ネットワーク内からのみアクセス可能です。
      redis:
    image: redis:latest
    restart: always
    • パスワードあり・ポート開放ありのバリアント。Redis が外部からアクセス可能になるため、パスワードの使用を強く推奨します。
      redis:
    image: redis:latest
    restart: always
    command: redis-server --requirepass REDIS_PASSWORD_HERE
    ports:
    - 6379:6379

    REDIS_PASSWORD_HERE の部分には、Redis の認証に使用するパスワードを任意に設定してください。

  2. コンテナを起動します:

docker compose up -d
注記

A-Parser が既に起動しており、その設定に変更がない場合、再起動は行われず、Docker は Redis のみを追加して起動します。

リクエストの実行

Redis API の動作は Redis Lists (リスト) に基づいています。リスト操作により、キューに無制限のリクエストを追加でき(メモリ容量に依存)、タイムアウト付きのブロッキングモード(blpop)または非同期モード(lpop)で結果を取得できます。

  • useproxyproxyCheckerproxybannedcleanup を除くすべての設定は、呼び出されるスクレイパーのプリセット + overrideOpts から取得されます。
  • useproxyproxyCheckerproxybannedcleanup の設定は、API::Server::RedisAPI::Server::Redis のプリセット + overrideOpts から取得されます

リクエストは Redis の lpush コマンドで追加されます。各リクエストは JSON でシリアル化された配列 JSON で構成されます:

  • parserpresetquery は API リクエスト oneRequest のものと同様です
  • queryId - リクエストと共に生成されます。データベースのシーケンス番号や適切なランダム値を使用することをお勧めします。この ID を使用して結果を取得できます
  • overrideOpts - スクレイパープリセットの設定の上書き
  • apiOpts - 追加の API 処理パラメータ
注記

Redis 経由のリクエストでは、結果のフォーマット段階はスキップされます。これは、後続のプログラム処理のためにすべての結果が JSON 形式で渡されるためです。

redis-cli

リクエスト実行の例(テストには 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.....

様々なケース

結果の有無の非同期確認

lpop aparser_redis_api:some_unique_id

結果が既に処理されていればそれを返し、リクエストがまだ処理中であれば nil を返します。

ブロッキングによる結果取得

blpop aparser_redis_api:some_unique_id 0

このリクエストは結果が得られるまでブロックされます。結果取得の最大タイムアウトを指定することもでき、その時間を過ぎるとコマンドは nil を返します。

単一のキューへの結果保存

デフォルトでは、A-Parser は各リクエストの結果を固有のキー aparser_redis_api:query_id で保存します。これにより、スレッドごとに個別にリクエストを送信し結果を取得するマルチスレッド処理が可能になります。

場合によっては、結果が届くたびに単一のスレッドで処理する必要があるかもしれません。その場合、結果を単一の結果キュー(リクエスト用とは異なるキー)に保存する方が便利です。

これを行うには、apiOptsoutput_queue キーを指定します:

lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru", {}, {"output_queue": "aparser_results"}]'

共通キューからの結果取得:

127.0.0.1:6379> blpop aparser_results 0
1) "aparser_results"
2) "{\"queryId\":\"some_unique_id\",\"results\":{\"data\":\"<!DOCTYPE html><html class=...

実装例 (SpySERP のケース)

ドメインのパラメータを評価する SaaS サービスを作成していると仮定します。簡単にするために、ドメインの登録日を確認することにします。

私たちのサービスは2つのページで構成されています:

  • /index.php - ドメイン入力フォームがあるランディングページ
  • /results.php?domain=google.com - サービスの実行結果を表示するページ

ユーザー体験を向上させるために、サービスのページが瞬時に読み込まれ、データ待機プロセスが自然に見えるようにローダーを表示したいと考えています。

results.php へのリクエスト時に、まず A-Parser Redis API へのリクエストを実行し、一意の request_id を生成します:

​lpush aparser_redis_api '["request-1", "Net::Whois", "default", "google.com", {}, {}]'

その後、ページをユーザーに表示し、データ表示エリアにローダーを表示できます。遅延がないため、サーバーのレスポンスは Redis の接続速度(通常 10ms 以内)のみに制限されます。

A-Parser は、ユーザーのブラウザが最初のコンテンツを受け取る前からリクエストの処理を開始します。ブラウザが必要なリソースとスクリプトをすべて読み込んだ後、結果を表示できます。そのために、データ取得用の AJAX リクエストを送信します:

/get-results.php?request_id=request-1

get-results.php スクリプトは、Redis に対して 15 秒のタイムアウトでブロッキングリクエストを実行します:

blpop aparser_redis_api:request-1 15

そして、A-Parser から結果を受け取り次第、すぐにレスポンスを返します。タイムアウトにより空の結果を受け取った場合は、ユーザーにデータ取得エラーを表示できます。

このように、最初のページ表示時 (/results.php) に A-Parser にリクエストを送信することで、ユーザーがデータを待つ必要のある時間 (/get-results.php) を、ブラウザがコンテンツの待機、スクリプトの読み込み、および AJAX リクエストの実行に費やす時間分だけ短縮できます。