この記事はLIFULL Advent Calendar その3の遅れてきた1日目の記事です。
他のWEB企業でもそうだと思うのですが、SEO等のサイトの改善施策は「これをやれば当たる!」というのが最初から明確に分かるわけではありません。その際に、施策の弾数を増やすために参考となるベースラインとなるサイトをいくつか手動でチェックしていました。
ただ、WEBサイトのチェックには膨大な手間がかかってしまうため、時間や網羅性で問題がありました。そのため、簡単にできて対象サイトに負荷をかけない範囲で、ベースラインにしているサイトをクローリングして、サイトの変更を検知する処理をRubyで実装し、運用しています。
基本方針
実装方針は簡単で、基本的に以下の2つの処理を行っているにすぎません。
- CSSを取得してAWSのS3に保存する
- 前日に取得したCSSと比較して、差分があれば通知
CSSの差分を検知することで、テキストファイルの単純比較で変更数が検知できます。他の実装案にはこのようなものがあったのですが、実装や運用が難しかったため諦めました。
そのため、以下のような欠点(制限)があります。
- CSSに影響を与えない差分は検知できない
- A/Bテストを取り逃す可能性がある もしくはA/Bテストの期間中検知され続ける
- ただし、ベースラインとなるサイトではこの問題は起きていないので対応していません
- JavaScriptが多用されたサイト(PWAなど)には向かない
- ただ、これはHeadless Chromeなどで対応できると思います
①HTMLから不変の要素を取得する
HTMLから、idやclassのみを抽出して比較しようとしていました。ただ、特に商品一覧ページのような「同じ要素が複数あり、中身のタグ要素が微妙に違う場合のあるもの」を比較する際に、非常にややこしくなってしまったので諦めました。
また、ECサイトでは商品ページが数が多くSEOの観点では重要らしいのですが、商品ごとに表示項目が微妙に違って単純比較できない場合がありました。
②画面キャプチャを比較する
画像の差分を撮るのが非常に難しいので諦めました。
ハマりどころや工夫
発想自体は簡単なのですが、いくつか実装していく中で工夫した点を説明します。
商品が消える場合がある
前述のように商品ページはけっこう重要で定点観測したいものらしいのですが、たまに商品自体が消えてしまうことがあるため、ずっと同じページを観測することができません。
そこで、以下のような設定ファイルで記述できるようにし、商品一覧(list)のページをクロールする際に、「ページ内に存在するURLの中から最初に正規表現にマッチしたものを利用する」ように実装しました。
:devices:
pc: '****-bot'
sp: 'iPhoneのユーザーエージェント'
:robots:
pc: https://www.homes.co.jp/robots.txt
sp: https://www.homes.co.jp/robots.txt
:nodes:
- name: top
type: top
url:
pc: https://www.homes.co.jp/
sp: https://www.homes.co.jp/smp/
- name: chintai-top
type: top
url:
pc: https://www.homes.co.jp/chintai/
sp: https://www.homes.co.jp/smp/chintai/
- name: chintai-list
type: list
url:
pc: https://www.homes.co.jp/chintai/tokyo/list/
sp: https://www.homes.co.jp/smp/chintai/tokyo/list/
childs:
- name: chintai-detail
type: detail
url_regexp: !ruby/regexp /^https?:\/\/www.homes.co.jp\/chintai\/b-\d+\//
前述の通り、「yamlを簡単に記述できる実行ファイルとして利用する」という発想は、ワークフローエンジンのDigDagから得ました。
ちなみに、クローラーの実行前にテストコードを動かし、robots.txtを参照してクローリングが禁止されていないことをきちんとチェックしています。その際にrobotexというgemが便利でした。
baseタグのhref指定
CSSのパスに相対パスが指定されていた場合、そのページ自身のURIを基準としてページを取得します。ただし、baseタグの中で、相対パスの基準となるURIを指定することができるため、その対応を忘れないようにする必要があります。
diffのわかりやすい表示が難しい
当初、Rubyでうまく差分の通知を行おうと思っていたのですが、案外人間に読みやすい形で表現するのが難しかったです。結局シェルスクリプトのdiffコマンドに適当なオプションをつけて実行するようにしました。
キャッシュバスターの処理
CSS等の末尾に日付などの文字列が付加されている場合があり、これらをファイル名やファイルの内容からうまく除去した上でないと比較できません。これを除去するためにけっこう愚直で泥臭い実装をしています。
これはキャッシュを除去するために付加されているらしく、キャッシュバスターと呼ばれるそうです。
今後の展望
CSSの差分が検知され、変更箇所のヒントはあるものの、基本的にレポーティングは手動です。その運用やアナウンスもけっこう手間なので、少しずつ自動化していきたいと思っています。
当初、こういう要望があると聞いて業務の合間にサクッと作ってしまったのですが、意外に社内でも参考にしてもらえているようです。その際に他の人でもメンテナンスしやすいよう、社内で普及しているRubyを採用しました(が、システム面は結局自分がメンテナンスしてしまっています)。
例えば、レポーティングが簡単に行えるよう、画面キャプチャを撮って、前日分と左右に並べて保存することはそれなりに簡単にはできると思います。