スクレイピングでBasic認証を扱う。＋αフォームからログインする。

#はじめに
本記事では、basic認証を使用しているページをスクレイピングするときにbasic認証を扱う方法を示しています。
さらに、ログインフォームからログインしなければページにアクセスできない場合を想定して、テキストフィールドを扱う方法も示しています。

#流れ
・add_authでBasic認証を扱う
・ログインフォーム内のテキストに文字を入力し、ログインボタンを押す
・トップページのHTMLを取得する

#Basic認証を扱う
##add_auth
mechanizeでbasic認証を扱うには、add_auth()を使用します。
第一引数→basic認証の対象のURL
第二引数→basic認証に使用するid
第三引数→basic認証に使用するpassword
以下のようにしてbasic認証を使ったページにアクセスします。
なお、ここではbasic認証に使用するidとpasswordを以下のように定義します。
id → basic_id
password → basic_password

```rb:scraping.rb
require 'mechanize'

url = 'http://hogehoge.com'
basic_id = 'hoge'
basic_password = 'basichogehoge'

agent = Mechanize.new
agent.add_auth(url, basic_id, basic_password)

#basic認証後にログインする必要なければ、このままページの情報を取得します。
page = agent.get(url)
```

##auth()とbasic_auth()
これは使用すると以下のようなエラーがでます。ここでは`#authと#basic_authの使用は、セキュリティ上の脆弱性に起因して推奨されません。`と言われています。これは、authとbasic_authがbasic認証を使用しているurlを指定しないために、ユーザー名とパスワードを必要としない場合でも送ってしまい、不具合を起こすためらしいです。

```lang:ターミナル
At test6_scraping.rb line 11

Use of #auth and #basic_auth are deprecated due to a security vulnerability.

You have supplied default authentication credentials that apply to ANY SERVER.
Your username and password can be retrieved by ANY SERVER using Basic
authentication.

THIS EXPOSES YOUR USERNAME AND PASSWORD TO DISCLOSURE WITHOUT YOUR KNOWLEDGE.

Use add_auth to set authentication credentials that will only be delivered
only to a particular server you specify.
```

#ログインする
ここでは、以下のフォームからログインすることを想定しています。

```html:/users/sign_in.html
<form action="/users/sign_in" method="post">
  <h1>ログイン</h1>
  <input type="email" name="email" placeholder="メールアドレスを入力">
  <input type="password" name="password" placeholder="パスワードを入力">
  <input type="submit" value="ログイン" name="login">
</form>
```
まずログイン画面のhtml情報を取得するために、ログイン画面のurlを引数にgetメソッドを使います。

```rb:scraping.rb
require 'mechanize'

url = 'http://hogehoge.com'
basic_id = 'hoge'
basic_password = 'basichogehoge'

agent = Mechanize.new

agent.add_auth(url, basic_id, basic_password)

#以下追加文
agent.get(url + '/users/sign_in') do |page|
  #このブロック内でpage変数を使用する
end
```

次に、今取得したログイン画面のhtml情報が格納された変数pageに対して、フォームの値にログインするために必要な情報を入力するための作業をします。

作業内容としては、
1.form要素を取得する
2.form内のテキストフィールドにログイン情報（今回はlogin_emailとlogin_password）を入力する
3.form内の送信ボタン（ログインボタン）をクリックする。
**field_withメソッドの引数のactionとnameの値は実際にログインするフォームで要素の検証をして確認してください。**

```rb:scraping.rb
require 'mechanize'
url = 'http://hogehoge.com'
basic_id = 'hoge'
basic_password = 'basichogehoge'

#新しく定義
login_email = 'hoge@gmail.com'
login_password = 'loginhogehoge'

agent = Mechanize.new

agent.add_auth(url, basic_id, basic_password)

agent.get(url + '/users/sign_in') do |page|
  # 作業1
  page.form_with(action: '/users/sign_in') do |form|
    # 作業2
    form.field_with(name: 'email').value = login_email
    form.field_with(name: 'password').value = login_password
    # 作業3
    form.click_button
  end
end
```

作業１について
ログインページのhtml情報が格納されている`page`に対して、`form_with`メソッドを使用することでフォームを取得します。今回引数で`action: '/users/sign_in'`を指定することで、action属性に'/users/sign_in'を持つフォームを特定しています。**これは実際に取得したいフォームを要素の検証で確認してください。**

作業２について
作業１で取得したformに対して、field_withメソッドを使用することで任意のテキストフィールドを取得しています。今回引数に`name: 'email'`と`name: 'password'`とすることで、それぞれname属性が'email'、'password'のテキストフィールド二つを取得しています。
*valueメソッド*と*`=`（代入）*を使用することでテキストフィールドの値にこちらから任意の値を入力しています。

作業３について
作業１で取得したform内にあるボタンをクリックしてテキストフィールド内に入力したものを送信します。


以上が、「basic認証」「ログイン」が必要なページをスクレイピングをするために最初にやることです。

これであとは自由にスクレイピングしてください。

#完成ソースコード

```rb:scraping.rb
require 'mechanize'
url = 'http://hogehoge.com'
basic_id = 'hoge'
basic_password = 'basichogehoge'
login_email = 'hoge@gmail.com'
login_password = 'loginhogehoge'

agent = Mechanize.new

agent.add_auth(url, basic_id, basic_password)

agent.get(url + '/users/sign_in') do |page|
  page.form_with(action: '/users/sign_in') do |form|
    form.field_with(name: 'email').value = login_email
    form.field_with(name: 'password').value = login_password
    form.click_button
  end
end
```