PythonでWEBページをクローリングする時のTips
PythonでWEBページをクローリングする時のTipsをまとめてみました。
urllib2.urlopenのデフォルトのユーザーエージェントを変更する
PythonでURLを開くには、urllib2.urlopenします。
urllib2.urlopenは、デフォルトで"Python-urllib/(Pythonのバージョン)"というユーザーエージェントを使用しますが、Wikipediaなど一部のページではこのユーザーエージェントに対し403 Forbiddenを返してきます。以下のコードによってデフォルトのユーザーエージェントを変更すると、403エラーを回避することができます。
import urllib2 opener = urllib2.build_opener() opener.addheaders = [('User-agent', 'your user agent string')] urllib2.install_opener(opener)
HTMLからタグを除去する
PythonでHTMLをパースするライブラリではBeautifulSoupが有名ですが、HTMLのタグを除去する程度のタスクの場合、標準ライブラリのsgmllibでも比較的簡単に達成することができます。
import sgmllib import StringIO class TagRemover(sgmllib.SGMLParser): def remove_tag(self, some_html): self.stringio = StringIO.StringIO() self.feed(some_html) self.close() result = self.stringio.getvalue() self.stringio.close() return result def handle_data(self, data): self.stringio.write(data) def clean_html(some_html): return TagRemover().remove_tag(some_html)
ElementTreeモジュールでXMLをパースする
PythonではXMLをパースするための標準ライブラリが複数ありますが、Python2.5以降で使用可能なElementTreeモジュールが一番使いやすいと思います。ただ、このモジュールのXML名前空間の扱いで少しハマったので、ここにメモにしておきます。
ElementTree.ElementTreeのfindやfindallなどのメソッドではタグの名前空間を{名前空間}で指定します。RSSやAtom等からデータを抜き出す際には、タグの名前空間をきちんと指定する必要があります。
ElementTreeのサンプルプログラム
import urllib2 from xml.etree import ElementTree url = 'http://d.hatena.ne.jp/saitodevel01/rss' etree = ElementTree.fromstring(urllib2.urlopen(url).read()) print etree.find("item") print etree.find("{http://purl.org/rss/1.0/}item")
実行結果
None <Element {http://purl.org/rss/1.0/}item at 10101d248>
時刻情報をパースする
はてなのRSSなどでは時刻情報がISO8601というフォーマットで出てきます。このフォーマットは標準ライブラリのtimeモジュールやdatetimeモジュールではパースすることが出来ないので、iso8601というライブラリを使用します。
iso8601のインストール
sudo easy_install.py iso8601 もしくは sudo pip install iso8601
iso8601の使い方
>>> import iso8601 >>> iso8601.parse_date("2007-01-25T12:00:00Z") datetime.datetime(2007, 1, 25, 12, 0, tzinfo=<iso8601.iso8601.Utc ...>) >>>
文字列をUnicodeに変換する際のTips
WEBページでは様々な文字列エンコードが使用されていますが、内部データはUnicodeで統一し、シリアライズはutf-8で行うのが定石かと思います。文字列をUnicodeへ変換する際に文字列のエンコードを指定する必要がありますが、文字列エンコードを推定するためのchardetというライブラリを使えば、unicodeへの変換を簡単に行うことができます。
chardetのインストール
sudo easy_install.py chardet もしくは sudo pip install chardet
chardet.detectに文字列を渡すと、encodingとconfidenceの2つのキーが入ったディクショナリが返され、encodingキーの値はそのままunicode関数の第2引数に渡すことが出来ます。また、unicode関数の第3引数を'ignore'とすると、UnicodeDecodeErrorが発生する文字列を無視してくれます。
# -*- coding: utf-8 -*- import chardet def unicode2(raw_string): encoding = chardet.detect(raw_string)['encoding'] if encoding is not None: return unicode(raw_string, encoding, 'ignore') else: raise ValueError, 'Can not detect encoding' if __name__ == '__main__': text = 'あいうえお' print repr(text) print repr(unicode2(text))