MAGAZINE

ルーターマガジン

クローリング/スクレイピング

JavaScript描画のhtmlをrubyのgem:mini_racerを使ってスクレイピングする

2025.03.07
Pocket

近年ReactやVueなどクライアントサイドレンダリング(CSR)のサイトが多くなってきました。
それに伴い、NokogiriなどHTMLのDOMを参照するスクレイピングでは太刀打ちできないサイトが多くなりました。

今回は、そのようなサイトで有効的な、scriptタグ内のjavascriptの変数や関数を対象にスクレイピングする方法を紹介します。

mini_racerとは

rubyのスクリプトからJavaScriptを実行するためのgemです。Ruby on Railsでも利用されることのあるgemです。

mini_racerのrubygemのページは以下になります。

mini_racerのインストール

mini_racerはlibv8のJavaScriptエンジンを使用しています。
gem install mini_racerとした際に、libv8の依存ライブラリもインストールしてくれるため、これでmini_racerを使うことが可能になります。

使用するhtmlファイル

<!DOCTYPE html>
<html>
  <head>
    <title>mini_racer</title>
  </head>
  <body>
    <div class="articles"></div>
    <script class="load">
      function loadArticles() {
        var articles = [
          { id: 1, title: "タイトル1", content: "本文1" },
          { id: 2, title: "タイトル2", content: "本文2" }
        ];
        return articles;
      }
    </script>
    <script class="display">
      function displayArticles() {
        var articles = loadArticles();
        var articlesTag = document.querySelector('.articles');

        articles.forEach(function(article) {
          var articleElement = document.createElement("div");
          articleElement.innerHTML = `<h2>${article.title}</h2><p>${article.content}</p>`;
          articlesTag.appendChild(articleElement);
        });
      }
      displayArticles();
    </script>
  </body>
</html>

scriptタグの中にデータが入っており、JavaScriptを通してタグが生成され、テキストが画面に表示されるhtmlです。

実際にブラウザ上で開くと以下のように見えます。 画像

mini_racerによるスクレイピング

ではいよいよmini_racerによるスクレイピングです。比較のため、Nokogiriのat_cssメソッドにより取得できないことも確かめます。

require "nokogiri"
require "mini_racer"

html = File.read(File.expand_path("blog.html", __dir__))
doc = Nokogiri::HTML.parse(html)

# at_cssメソッドによる取得
p doc.at_css(".articles").text
# => ""

# mini_racerによる取得
context = MiniRacer::Context.new()
context.eval(doc.at_css("script.load").text)
p context.eval("loadArticles()")
# => [{"id"=>1, "title"=>"タイトル1", "content"=>"本文1"}, {"id"=>2, "title"=>"タイトル2", "content"=>"本文2"}]

mini_racerを使用する際はまずインスタンスを生成し、読み込ませたいJavaScriptのスクリプトをevalメソッドの引数に与えます。
また、同一インスタンスではevalで評価されたものは引き継がれます。

これによりmini_racerでのJavaScript描画の要素が取得可能になりました!

Pocket

CONTACT

お問い合わせ・ご依頼はこちらから