今回は Python の標準モジュールである urllib2 と HTMLParser クラスを使って Web 上のリソースにアクセスし、取得した HTML を解析する方法について説明します。
Web上からHTMLを取得
Python で Web 上にあるリソースにアクセスするためには urllib2 の urlopen() を使用します。以下のサンプルプログラムでは、指定した URLから HTML を取得し、その取得した HTML をそのまま表示しています。
1 2 3 4 5 6 7 8 9 10 11 12 |
# -*- coding: utf-8 -*- import urllib2 if __name__ == "__main__": url = "http://www.python.org" # Pythonの公式ページのURL response = urllib2.urlopen(url) # URLを指定してHTMLファイルを開く print unicode(response.read(),"utf-8") # 取得したHTMLファイルの内容を表示する response.close() |
HTML タグの情報を取得・解析する
取得した HTML を解析するためには HTMLParser を継承して使用します。今回は主に以下の3つのメソッドを利用します。
1. 開始タグを扱うためのメソッド
1 |
handle_starttag(self, 開始タグ名, 属性名と属性値のタプルのリスト) |
2. 要素内容を扱うためのメソッド
1 |
handle_data(self, 要素内容) |
3. 終了タグを扱うためのメソッド
1 |
handle_endtag(self, 終了タグ) |
取得したHTML を HTMLParser の feed() で読み込ませると、各要素に対して上の3つのメソッドが順番に実行されていきます。
ページのタイトルを取得
次のサンプルプログラムは、リンク先のタイトルを取得し表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# -*- coding: utf-8 -*- import urllib2 from HTMLParser import HTMLParser class TestParser(HTMLParser): # HTMLParserを継承したクラスを定義する def __init__(self): HTMLParser.__init__(self) self.flag = False # タイトルタグの場合のフラグ def handle_starttag(self, tag, attrs): # 開始タグを扱うためのメソッド if tag == "title": self.flag = True def handle_data(self, data): # 要素内用を扱うためのメソッド if self.flag: print data self.flag = False if __name__ == "__main__": url = "http://www.python.org/" response = urllib2.urlopen(url) parser = TestParser() # パーサオブジェクトの生成 parser.feed(response.read()) # パーサにHTMLを入力する parser.close() response.close() |
実行結果
1 |
Welcome to Python.org |
上の例ではまず、urlopen() でWeb上のリソースを取得し feed() で取得した HTML をパーサで読み込みます。
次に、handle_startag() が実行されタグ名が title だった場合、フラグを立てます。
そして、フラグが True の場合 handle_data() で要素内容を、すなわち <title> </title> のタグで囲まれている部分を表示しています。
ページ中のリンクを抽出する
以下は、ページ中の外部リンクをすべて抽出するプログラムです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# -*- coding: utf-8 -*- import urllib2 import re from HTMLParser import HTMLParser class TestParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.url = "" def handle_starttag(self, tag, attrs): if tag == "a": # 開始タグがaであるかどうか判定 attrs = dict(attrs) # タプルを辞書に変換する if 'href' in attrs: # キー値(属性名)がhrefであるか判定 self.url = attrs['href'] def handle_endtag(self, tag): # 開始・終了タグに囲まれた中身の処理 if self.url and re.match('^http', self.url): # 先頭がhttpであるか判定 print self.url self.url = "" if __name__ == "__main__": url = "http://www.python.org/" response = urllib2.urlopen(url) parser = TestParser() parser.feed(response.read()) parser.close() |
先ほどの例と同様にまず、まず feed() で HTML を読み込みます。
次に、handle_startag() を用いて a タグの href 属性の値を取得して表示します。 属性のリスト attrs は (name, value) のタプルのリストで構成されており、タプルのままだと扱いづらいので、辞書に変換して使用しています。そして、その辞書のキー値が href のものだけ抽出し self.url に保存しています。
最後に、handle_endtag() が実行されます。今回は外部リンクを抽出するので、正規表現を利用して先頭の文字列が http であるか確認し保存しています。