2014年5月23日金曜日

Selenium webdriver: chromeで全画面をキャプチャする方法

見えている範囲だけをキャプチャすることはできたので、多少強引だが
  1. Javascriptを使って見えてる範囲の高さと画面全体の高さを取得
  2. スクロールしながらキャプチャ
  3. 最後の一枚のみ重複ができるのでImageMagickを使ってカット
  4. ImageMagickを使って全ての画像を結合
という流れで全体のキャプチャを実現出来た。
以下rubyの場合。
def chrome_capture(webdriver, fname_prefix)
  #1. Javascriptで画面のサイズを取得
  inner_h = webdriver.execute_script("return window.innerHeight").to_i
  scroll_h = webdriver.execute_script("return document.documentElement.scrollHeight").to_i

  repeat = (scroll_h.to_f/inner_h.to_f).ceil
  dupl_h = inner_h - (scroll_h % inner_h)

  tmp_fnames = []
  tmp_basename = fname_prefix

  #2. スクロールしながらキャプチャ
  repeat.times{|i|
    tmp_fnames << tmp_fname = tmp_basename + sprintf("%06d",i) + ".png"
    webdriver.save_screenshot(tmp_fname)
    sleep (0.3)
    webdriver.execute_script("window.scrollBy(0,#{inner_h})");
    sleep (0.3)
  }

  if tmp_fnames.length > 1
    #一時ファイルが2つ以上の場合
    #3. 最後の一枚のみ重複ができるのでImageMagickを使ってカット
    if dupl_h > 0
      `convert -chop 0x#{dupl_h} #{tmp_fnames.last} #{tmp_fnames.last}`
    end
    #4. ImageMagickを使って全ての画像を結合
    `convert -append #{tmp_fnames.join(' ')} #{tmp_basename}.png`
    File.unlink *tmp_fnames
  else
    #1つの場合は一時ファイルをリネームするだけ
    File.rename(tmp_fnames[0],"#{tmp_basename}.png")
  end

end

ちなみにMacのSafari、Chromeでも同様の方法でいけるが、Retinaの場合は重複カットする際のピクセル数を2倍(正確には、JavascriptのdevicePixelRatioで取得可能な値倍)にする必要があるため要注意。