デバックで使えるメソッドMechanizeメソッド集
Mechanizeクラスのメソッド
agentのページ遷移の履歴表示
p @agent.history
# [https://sample.com/page1.html, https://sample.com/page1.htm2]
Mechanize::Pageクラスのメソッド
ページのステータスコード表示
p page.code
# "200"
HTTP通信関連の表示
リクエスト、レスポンスヘッダ情報などをロガーで標準出力できる
特に、Mechanize内部で、FormのPOSTで送信されるqueryが見えるので、デバッグで重宝する
require 'logger'
@agent = Mechanize.new
@agent.log = Logger.new $stderr
レスポンスヘッダー取得
pp page.header
{"cache-control"=>"private",
"content-type"=>"text/html; charset=utf-8",
"x-aspnet-version"=>"Secret",
"x-frame-options"=>"sameorigin",
"date"=>"Tue, 05 Apr 2016 07:43:08 GMT",
"content-length"=>"13577",
"set-cookie"=>
"cookie_oishii=1234.0000.4564; expires=Tue, 05-Apr-2016 08:49:09 GMT; path=/, hontoni_oishi=20220.0000; expires=Tue, 05-Apr-2016 08:49:09 GMT; path=/"}
リクエストヘッダの指定
@agent.request_headers = {
'Origin' => 'https://michadameyo.com',
'accept-language' => 'ja,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4,zh;q=0.2',
'Upgrade-Insecure-Requests' => '1',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
}
特定のcookieのvalueの取得・保存・追加
uri = URI.parse("site.com")
# クッキー取得
cookie_str = @agent.cookie_jar.jar["site.com"]["/"]["hoshii_cookie_name"].value
File.write(CAPTCHA_PATH + '/cookie.txt', cookie_str)
# クッキー追加
cookie_str = File.read(CAPTCHA_PATH + '/cookie.txt')
agent.cookie_jar << Mechanize::Cookie.new('hosii_cookie_name', uri.host, {:value => cookie_str, :domain => uri.host, :path=>"/"})
ページ遷移・リソースの取得方法あれこれ
URL指定でページ取得(GET)
top_uri = 'https://www.webpage.com/index.html'
uri = URI.parse(top_uri)
top_page = @agent.get(uri)
URLとPOSTパラメータ指定でページ取得(POST)
uri = 'https://samplesite.com'
response = @agent.post(uri, {
area: 'kumamoto',
region: 'mashiki',
Date: '20160531'
})
doc = Nokogiri::XML.parse(response.body)
pp doc.css('docroot > array')[0].text.split("\n")
同一のパラメータ名で複数のvalueをPOSTする場合は以下の様に配列でvalueを複数定義する
response = agent.post(uri, {
params1: ['value1-1', 'value1-2'],
params2: 'value2',
})
Mechanizeが送るPOST(content-type => application/x-www-form-urlencoded)のqueryを以下のログから確認すると、"params1=value1-1¶ms1=value1-2¶ms2=value2"
の様にparams1のパラメータ名が送信されていることがわかる。
D, [2020-04-17T15:11:55.066392 #59898] DEBUG -- : query: "params1=value1-1¶ms1=value1-2¶ms2=value2"
I, [2020-04-17T15:11:55.066596 #59898] INFO -- : Net::HTTP::Post: /
D, [2020-04-17T15:11:55.066614 #59898] DEBUG -- : request-header: accept-encoding => gzip,deflate,identity
D, [2020-04-17T15:11:55.066623 #59898] DEBUG -- : request-header: accept => */*
D, [2020-04-17T15:11:55.066630 #59898] DEBUG -- : request-header: user-agent => Mechanize/2.7.6 Ruby/2.5.3p105 (http://github.com/sparklemotion/mechanize/)
D, [2020-04-17T15:11:55.066638 #59898] DEBUG -- : request-header: accept-charset => ISO-8859-1,utf-8;q=0.7,*;q=0.7
D, [2020-04-17T15:11:55.066644 #59898] DEBUG -- : request-header: accept-language => en-us,en;q=0.5
D, [2020-04-17T15:11:55.066654 #59898] DEBUG -- : request-header: host => minaide_kudasai.com
D, [2020-04-17T15:11:55.066673 #59898] DEBUG -- : request-header: content-type => application/x-www-form-urlencoded
D, [2020-04-17T15:11:55.066680 #59898] DEBUG -- : request-header: content-length => 48
クリックでページ遷移する
list_page = top_page.link_with(text: '記事一覧ページ').click
list_page = top_page.link_with(href: '/list?src=ichiran').click
遷移先ページ内のFormを取得して、POSTするパラメータを追加し、送信する
form = page.form_with(name: 'register')
form.action = 'https://minaide_kudasai/login.php'
form.LoginName = 'ID'
form.Passwd = 'PASS'
form.checkbox_with(:name => 'ChkBox').value = '1'
login_page = agent.submit(form)
input fieldの名前によっては、上記の記載ができない場合がある。
その場合はこんな感じで書くと良い。
form = page.forms[0]
form.field_with(name: 'UserId').value = 'ID'
form.field_with(name: 'Password').value = 'PASS'
login_page = agent.submit(form)
puts login_page.body
Formの送信ボタン(submitボタン)にFormパラメータのname,valueが設定されているときは、submitだけでは送信ボタンに付けられたFormパラメータがqueryに追記されないので、submitではなくボタンclickで処理する必要がある。
form = page.forms[0]
button = form.button_with(name: 'login_button')
login_page = @agent.submit(form, button)
mechanizeが保持していないフォームフィールドを自分で追加する
form.add_field!('date', '20160606')
ユーザーエージェントを指定する
@agent = Mechanize.new
@agent.user_agent_alias = 'Windows IE 11'
ページのヒストリーを保持しない
@agent = Mechanize.new
# バックボタンが使える最小個数を保持する
@agent.max_history = 2
画像ファイルなどをダウンロードする
url = base_url + page.search('#LoginWebCaptcha > div.igc_CaptchaImageArea > img').attribute('src').value
@agent.get(url).save_as(CAPTCHA_PATH + "/latest_captcha.gif")
実例集
アパレルECサイトで商品をカートに入れて、買い物を進める感じの一連の操作
require 'mechanize'
require 'pp'
# ログインページ取得
agent = Mechanize.new
agent.max_history = 2
page = agent.get('https://minaide_kudasai/login.php')
page.encoding = 'Shift_JIS'
# ログイン処理
form = page.form_with(name: 'register')
form.action = 'https://minaide_kudasai/dologin.php'
form.LoginName = 'ID'
form.Passwd = 'PASS'
form.checkbox_with(:name => 'ChkBox').value = '1'
login_page = agent.submit(form)
login_page.encoding = 'Shift_JIS'
# トップページへ遷移
top_page = login_page.link_with(text: "トップへ").click
# トップページに表示されたランキング3位の商品ページへ遷移(1-2位は在庫が無かったので3位)
item_page_url = top_page.search('#container > ul:nth-child(2) > li:nth-child(3) > a').attribute('href').value
item_page = top_page.link_with(href: item_page_url).click
# 商品ページ内のカートに入れる
item_id = item_page.search('#container > table tr:nth-child(3) > td:nth-child(3) > div > span').attribute('id').value
cart_in_form = item_page.form_with(name: 'cart_form')
cart_in_form.qId = item_id
cart_in_form.qRetId = item_id
cart_in_form.qMode = 'store'
cart_in_form.qNum = 1
cart_page = agent.submit(cart_in_form)
puts cart_page
気づき
- Formのパラメータやリクエストヘッダ(特にCookie)をあれこれ手動で設定したくなるが、意外なほどMechanizeは普通のブラウザと同じように振る舞って、情報を集めてくれる。
本当に追加が必要な情報かどうか、しっかり調べてから、必要なForm、リクエストヘッダのみ追記するようにすること。
(特に、FormはブラウザとMechanizeのForm 生queryを比較すれば、過不足は明確に分けられるので。)