「Ruby の Hpricot でスクレイピング」の続き。
1. Basic 認証を用いたサイトをスクレイピングしたい
ルータに割り当てられた IP アドレスを取得したい。
ブラウザでルータの設定画面をアクセスすると、IP アドレスを知ることができる。
ルータの設定画面にアクセスするには、パスワードを入力する必要がある。このときの認証方式は、Basic 認証。
上記を Ruby を用いて、スクレイピングする。
2. 方法の概略
3. Net:HTTP を用いて Basic 認証を行う
IP アドレスが表示されるページ
ルータは、AirStation を使っている。最初に、Basic 認証でルータの設定ページにアクセスできるか確かめる。
現在の IP アドレスは、AirStation の
- 「システム情報」
において表示される。このページはフレームで作成されている。IP アドレスが表示されるのは、右側のフレーム。このフレームだけ表示し、 URL を確認する。
Basic 認証
を参考にして Basic 認証を行う。認証を行うには、Net::HTTP::Get クラスを利用する。
Net::HTTPRequest によると、
HTTP リクエストを抽象化するクラスです。Net::HTTPRequest は抽象クラスなので実際にはサブクラスの
- Net::HTTP::Get
- Net::HTTP::Post
- Net::HTTP::Head
- Net::HTTP::Put
を使用してください。
Net::HTTP を使い、IP アドレスが表示されるページを取得するために、GET リクエストを投げる。
require 'net/https' require 'kconv' IP_ADDRESS = '192.168.11.1' ID = 'root' PASSWD = 'パスワード' SETTING_PAGE = '/cgi-bin/cgi?req=frm&frm=info.html' def getHtml(ip, id, passwd, page) req = Net::HTTP::Get.new(page) req.basic_auth(id, passwd) Net::HTTP.start(ip) do|http| response = http.request(req) return Kconv.tosjis(response.body) end end puts getHtml(IP_ADDRESS, ID, PASSWD, SETTING_PAGE)
これにより、「システム情報」のページが出力されることを確認した。
4. XPath を利用して、HTML から IP アドレスを抽出する
HMTL から XPath を利用して、要素を取得する関数
次に、上記で取得した HTML を Hpricot で解析。XPath を使って、IP アドレスが書かれた文字列を取得する。
関数 getIpAddress は、HTML から XPath を用いて要素を取得する。
上記の getHtml 関数で得た「システム情報」ページの HTML を、関数 getIpAddress の引数 html 与える。
def getIpAddress(html, xpath) doc = Hpricot.parse(html) (doc/xpath).each do |td| return $1 if /(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ =~ td.inner_html end end XPATH = '/html/body/form/table/tr[3]/td[2]/table/tr[5]/td[2]' puts getIpAddress(html, XPATH)
これにより、IP アドレスが表示された。
Firebug で XPath を取得
XPath を記述するために、Firefox のアドオン Firebug を利用した。 Firebug で XPath を得るには、
- HTML の要素を選択し、
- 「右クリック > XPath をコピー」。
取得した XPath は、以下の通り。
/html/body/form/table/tbody/tr[3]/td[2]/table/tbody/tr[5]/td[2]
しかし、Hpricot で、この XPath を用いて IP アドレスを取得できなかった。
Firefox, Google Chrome で自動的に挿入される HTML 要素
なぜか上記の XPath から `tbody’ を削除することによって、要素を取得できた。
これは、http://ircarchive.info/ruby-lang/2007/4/12/10.html によると、
firefox inserts tbodies after tables if they're not there
Firefox は、table 要素の後に tbody 要素がないと、tbody 要素を挿入する。
試しに、HTML で tbody 要素を書かずに table を書き、Firebug で確かめたら、確かに tbody が挿入されているのを確認した。 Google Chrome も同じ現象が生じた。
5. 全体のソースコード
require 'net/https' require 'kconv' require 'hpricot' # ルータの IP アドレス IP_ADDRESS = '192.168.11.1' # Basic 認証のための ID とパスワード ID = 'root' PASSWD = '' # 「システム情報」のページ SETTING_PAGE = '/cgi-bin/cgi?req=frm&frm=info.html' # IP アドレスを取得するための XPath XPATH = '/html/body/form/table/tr[3]/td[2]/table/tr[5]/td[2]' def getHtml(ip, id, passwd, page) req = Net::HTTP::Get.new(page) req.basic_auth(id, passwd) Net::HTTP.start(ip) do|http| response = http.request(req) return Kconv.tosjis(response.body) end end def getIpAddress(html, xpath) doc = Hpricot.parse(html) (doc/xpath).each do |td| return $1 if /(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ =~ td.inner_html end end html = getHtml(IP_ADDRESS, ID, PASSWD, SETTING_PAGE) puts getIpAddress(html, XPATH)
0コメント:
コメントを投稿