2020/01/28

Duadua というユーザエージェント解析器

ユーザエージェント解析器のデフォルトと言えば Woothee だと思われますが、ちょっと思うところあって、2019の年末から2020にかけて、自分のやりたいことを全部詰め込んだ Yet Another ユーザエージェント解析器を書いていた。

Duadua というライブラリで、もともとは Detect User Agent を略して Dua という名前だったのだけど、うっかり CPAN にあげてみたらその名前はすでに存在していたので、Duadua に変名した。

まだちょっと最適化とか細かいことをいろいろやりたいのだけど、CPANにはあげてしまおうかなあというところまでできてきたので、一回何やりたかったのか、まとめることにした。

  • 端的に速い
    • ユーザエージェントの訪問実態に沿った処理順で解析して高速化
    • Parserがクライアント種別ごとに分離していて、必要のないものはスキップしてさらに高速化できる
    • 必要最低限のパース以外はオプションにしている
  • 本当に結果が必要になるまで Parse しない
  • Woothee と同じようにテストケースは YAML で書かれている
  • 対応状況が新しい

ユーザエージェントの訪問実態に沿った処理順で解析

一般的なユーザエージェントのシェアには偏りがあり、支配的なシェアをもつブラウザを早く明らかにしてしまえば全体的な処理の最適化がはかれます。したがって、ユーザエージェントごとの解析する順番をブラウザやボットのシェアに準じたものにすることで最適化を行っています。

必要のない解析はスキップしてさらに高速化

アプリケーションサーバの前段で、ユーザエージェントを見てアクセスを弾いたりする処理をしていて、アプリケーションレイヤでの解析処理が必要ない場面もあるかと思います。例えば、FeaturePhone の訪問はないことが明らかである場合など、そうした場合は、FeaturePhone の解析処理をスキップすることを可能にしています。この機構により、ライブラリがサポートするユーザエージェント文字列を多くして、利用者側で必要なものを選択してパフォーマンスを担保できるようにしています。

必要最低限のこと以外はオプションにしている

速さを実現するため、必要最低限のこと以外はオプションにしています。例えば、vender や category がセットされますが、Duadua ではユーザエージェント名とOSしか通常解析しません。ユーザエージェントのバージョンは、オプションでフラグを立てると解析します。また、OSについては、昨今OS自体による処理の分岐は必要になるものの、そのバージョンによる差分はかなりなくなってきていて、常時必要になることが少ないと判断しました。

本当に結果が必要になるまで Parse しない

例えば、 Plack::Middleware::Woothee は、Woothee を Plackアプリに組み込む middleware ですが、アプリケーションではいつでも必ず解析結果が必要になるわけではないので、本当に必要になるまで解析を遅延させる工夫がされています。Duadua においては、同様のことが、そもそもモジュールの実装時点で考慮されるようになっていて、オブジェクトを生成する時点では Parse せず、parse メソッドが呼ばれるか、解析結果にアクセスするためのメソッドが呼ばれたときにはじめて解析をします。

テストケースは YAML

woothee にならって、テストケースは YAML ベースで記述されていて、そのうち他の言語に展開するかもしれません。キラキラネームなのはそれを考慮している。

対応状況が新しい

最近のブラウザ、アプリブラウザ、Bot の実態が反映された解析結果を目指しました。あと、特に bot はかなりいろいろ取り揃えています。

まとめ

そもそもUA自体が終わるかもって話もあるけど、ユーザエージェント文字列の解析アプローチは、そろそろAIで特徴算出してモデルにして解析とかそういうのになるんではなかろうかとか思ったりしている(どんどん複雑化していくなら)。まあとはいえまだしばらくはこの手の解析器が必要なのではないかと思っている。

サイト内検索