Mechanizeを使ってgoogleにログインする

  • 4
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

2016/10/10現在動作確認済み
Mechanizeというスクレイピングができるgemを使って、googleにログインします。
Googleのセキュリティの関係で確認コードを求められるところまでアクセスするのが限界でした。

必要なGem

  • Mechanize(スクレイピングに必要)
  • Nokogiri(Mechanizeが動くために必要)

Gemfileで入れるなり、gem installをするなりしてください。

Let's Try!

STEP1 素直にコードを書く

とりあえずドキュメントを参考にしながら、Googleのログインフォームを観察しつつコードを書きます。

require 'nokogiri'
require 'mechanize'

agent = Mechanize.new
agent.user_agent_alias = 'Mac Safari 4'
agent.get('https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fwww.google.co.jp%2Fwebhp%3Fie%3Dutf-8%26oe%3Dutf-8%26client%3Dfirefox-b%26gfe_rd%3Dcr%26ei%3D-E37V9nIHLHK8gfpgaWgDQ') do |page|

  second_stage = page.form_with(id: "gaia_loginform") do |form|
    form.Email = ENV["mail"]
    form.Passwd = ENV["pass"]
  end.submit

  doc = Nokogiri::HTML(second_stage.content.toutf8)
  puts doc.to_html
end

メールアドレスとパスワードをコードに書くのは微妙な気がしたので環境変数から読み出しています。
ここでこのコードを走らせると、パスワードの入力フォームに飛ばされてしまいます。

STEP2 一工夫!

なぜ、このようなことになってしまったのでしょう?
その答えは、Googleのフォームのaction属性とputs form.actionを見比べてみればわかります!
なんと、この2つ一致しません・・・(ちなみにputs form.actionを実行した時に出てくるhttps://accounts.google.com/accountLoginInfoXhrはメールアドレスの有効性について問い合わせるためのURLのようです。)
そんなわけでform.actionを上書きしてしまいましょう!

require 'nokogiri'
require 'mechanize'

agent = Mechanize.new
agent.user_agent_alias = 'Mac Safari 4'
agent.get('https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fwww.google.co.jp%2Fwebhp%3Fie%3Dutf-8%26oe%3Dutf-8%26client%3Dfirefox-b%26gfe_rd%3Dcr%26ei%3D-E37V9nIHLHK8gfpgaWgDQ') do |page|

  second_stage = page.form_with(id: "gaia_loginform") do |form|
    form.action = "https://accounts.google.com/signin/challenge/sl/password"
    form.Email = ENV["mail"]
    form.Passwd = ENV["pass"]
  end.submit

  doc = Nokogiri::HTML(second_stage.content.toutf8)
  puts doc.to_html
end

このコードを使うとなんとかログインはできますが、確認コードを選択する画面に飛ばされてしまいます。

STEP3 確認コードを入力するページに飛ぶ

require 'nokogiri'
require 'mechanize'

agent = Mechanize.new
agent.user_agent_alias = 'Mac Safari 4'
agent.get('https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fwww.google.co.jp%2Fwebhp%3Fie%3Dutf-8%26oe%3Dutf-8%26client%3Dfirefox-b%26gfe_rd%3Dcr%26ei%3D-E37V9nIHLHK8gfpgaWgDQ') do |page|

  second_stage = page.form_with(id: "gaia_loginform") do |form|
    form.action = "https://accounts.google.com/signin/challenge/sl/password"
    form.Email = ENV["mail"]
    form.Passwd = ENV["pass"]
  end.submit

  confirm_code_page = second_stage.form_with(method: "POST").nil? ? nil : second_stage.form_with(method: "POST").submit

  doc = Nokogiri::HTML((confirm_code_page || second_stage).content.toutf8)
  puts doc.to_html
end

STEP4 PINを入力する

標準入力で頑張ります。

require 'nokogiri'
require 'mechanize'

agent = Mechanize.new
agent.user_agent_alias = 'Mac Safari 4'
agent.get('https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fwww.google.co.jp%2Fwebhp%3Fie%3Dutf-8%26oe%3Dutf-8%26client%3Dfirefox-b%26gfe_rd%3Dcr%26ei%3D-E37V9nIHLHK8gfpgaWgDQ') do |page|

  second_stage = page.form_with(id: "gaia_loginform") do |form|
    form.action = "https://accounts.google.com/signin/challenge/sl/password"
    form.Email = ENV["mail"]
    form.Passwd = ENV["pass"]
  end.submit

  confirm_code_page = second_stage.form_with(method: "POST").nil? ? nil : second_stage.form_with(method: "POST").submit

  pin = STDIN.gets
  final_page = nil
  unless confirm_code_page.nil?
    final_page = confirm_code_page.form_with(id: "challenge") do |form|
      form.Pin = pin.gsub("\n", "")
    end.submit
  end

  doc = Nokogiri::HTML((final_page || confirm_code_page || second_stage).content.toutf8)
  puts doc.to_html
end

終わりに

あんまり(短時間に)クエリどしどし投げてると不正アクセスとみなされて色々大変なので、間隔おくなり少ない試行回数で答えを導くなり工夫しましょう!