こんにちは、学生アルバイトのkoyamaです。 以前当ブログでchrome_remoteを使用してのスクレイピング方法を紹介しましたが、今回はそのchrome_remoteで特定の通信の内容をキャッチする方法を紹介したいと思います。 また、chrome_remoteについてはchrome_remoteという選択(脱Selenium大作戦)を参考にしてください。

特定の通信をキャッチする

まずは通信の内容を見るために通信の監視設定をオンにします。

@chrome.send_cmd("Network.enable")

ここで、通信が流れた際に反応するようにしてみましょう。通信が流れた際に何かしらの動作をさせたい場合には@chrome.on(Network.responseReceived)として、ブロック変数に取得した通信の内容を渡すことができます

@chrome.on("Network.responseReceived") do |params|
  pp params
end
sleep 1
@chrome.send_cmd("Page.navigate", url: "https://rooter.jp/")

このようにしてrooterのサイトを訪れた時に流れる通信を吐き出してやると以下のようなものが確認できました。

{"requestId"=>"CCAC91B20530D00755EA827F7F2B7E2E",
 "loaderId"=>"CCAC91B20530D00755EA827F7F2B7E2E",
 "timestamp"=>90819.631729,
 "type"=>"Document",
 "response"=>
  {"url"=>"https://rooter.jp/",
   "status"=>200,
   "statusText"=>"OK",
   "headers"=>...

無事、流れている通信を見ることができましたね。

特定の通信を再現して、レスポンスを得てみる

先ほどまでは流れた通信をみるだけでしたが、ここから通信を再現してみましょう。 rooterのサイトにアクセスすれば当然このサイトのhtmlが落ちてきます。今回はrooter.jpから来る通信を再現して、トップページのhtmlを取得してみます。

@chrome.on("Network.responseReceived") do |params|
  if params["response"]["url"] == "通信元の任意の条件"
    #何かしらの動作
  end
end

先ほど同様にして通信を受け取るようにし、条件式をparams["response"]["url"]で作れば特定の通信のみに反応するようにできます。今回はrooter.jpから来る通信のみを取得したいので、それに合わせて条件式を書き換えます。

@chrome.on("Network.responseReceived") do |params|
  if params["response"]["url"] == "https://rooter.jp/"
    response_body = nil
    while response_body.nil?
      sleep 1
      response_body = @chrome.send_cmd("Network.getResponseBody", requestId: params["requestId"])
    end
    p response_body
  end
end
sleep 1
@chrome.send_cmd("Page.navigate", url: "https://rooter.jp/")
sleep 1

このようにすると、rooterのサイトのhtmlが落ちてきていることが確認できました。

{"body"=>"\n\n\n\t\n\t(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\n\tnew Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\n\tj=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\n\t'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\n\t})(window,document,'script','dataLayer','GTM-NWQBH9M');\n\t\n\t\n\t\n\t\n\n\t株式会社ルーター – データクローリング・スクレイピングによるビッグデータ収集\n\n\n\n\n<link rel=\"alternate\" type=\"application/rss+xml\" title=\"株式会社ルーター » フィード\"...

通信をキャッチすることができればサイトの裏側で行われている操作を再現でき、スクレイピングの幅が大幅に広がります。 chrome_remoteを有効活用してスクレイピングライフを向上させていきましょう!

最後に

今回の記事で使用したソースコードです。chromeの起動はmacで行う前提ですので、環境に合わせて修正してください。

require 'chrome_remote'

IO.popen('/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=./tmp')
@chrome = ChromeRemote.client
@chrome.send_cmd("Network.enable")
@chrome.on("Network.responseReceived") do |params|
  if params["response"]["url"].include?("rooter")
    response_body = @chrome.send_cmd("Network.getResponseBody", requestId: params["requestId"])
    p response_body
  end
end
sleep 1
@chrome.send_cmd("Page.navigate", url: "https://rooter.jp/")
Pocket