cron jobで動作させるクローラの実装に有用なHTMLParserのサンプルコードを記載します。
Table of Contents
1 urllib.requestでヘッダとボディを取得する
- urllib.requestでレスポンスを取得し、ヘッダに記載された文字コードでデコードします。
- ヘッダに文字コードがない場合は、DECODE_CHARSETに含まれる文字コードでデコードを試みます。
import urllib.request
DECODE_CHARSET = ['iso-8859-1', 'utf-8', 'shift-jis', 'euc-jp']
def example_decode(html):
for charset in DECODE_CHARSET:
try:
decode_html = html.decode(charset)
return decode_html
except:
pass
return html
def example_http_get(url):
with urllib.request.urlopen(url) as response:
charset = response.headers.get_content_charset()
if charset:
return response.read().decode(charset)
return example_decode(response.read())
return ""
2 HTMLParserでボディを解析する
- HTMLParserを継承したExampleParserを定義します。
- ExampleParserのfeedを呼ぶと、handle_starttagが呼ばれます。
- handle_starttagには以下の引数が格納され、コンストラクタで与えられたtagとattrに等しい場合に値を出力します。
<a href=http://example.com> tag = a attrs = [ [ 'href', 'http://example.com' ] ]
from html.parser import HTMLParser
class ExampleParser(HTMLParser):
def __init__(self, tag, attr):
super(ExampleParser, self).__init__()
self.tag = tag
self.attr = attr
def handle_starttag(self, tag, attrs):
if tag == self.tag:
for attr in attrs:
if attr[0] == self.attr:
print(attr[1])
def example_print(tag, attr, html):
parser = ExampleParser(tag, attr)
parser.feed(html)
3 サンプルコード
サンプルコードは以下の通りです。
#!/usr/bin/env python3
import sys
import urllib.request
from html.parser import HTMLParser
DECODE_CHARSET = ['iso-8859-1', 'utf-8', 'shift-jis', 'euc-jp']
def example_decode(html):
for charset in DECODE_CHARSET:
try:
decode_html = html.decode(charset)
return decode_html
except:
pass
return html
def example_http_get(url):
with urllib.request.urlopen(url) as response:
charset = response.headers.get_content_charset()
if charset:
return response.read().decode(charset)
return example_decode(response.read())
return ""
class ExampleParser(HTMLParser):
def __init__(self, tag, attr):
super(ExampleParser, self).__init__()
self.tag = tag
self.attr = attr
self.attrs = []
def handle_starttag(self, tag, attrs):
if tag == self.tag:
for attr in attrs:
if attr[0] == self.attr:
print(attr[1])
def example_print(tag, attr, html):
parser = ExampleParser(tag, attr)
parser.feed(html)
if __name__ == "__main__":
argv = sys.argv
argc = len(argv)
if argc != 4:
print('usage: %s <tag> <attr> <url>' % argv[0])
exit(1)
example_print(argv[1], argv[2], example_http_get(argv[3]))
exit(0)
このコードをexample-html-parser.pyという名前で実行すると以下の出力を得られます。
$ ./example-html-parser.py a href http://yahoo.co.jp http//... http//... http//... <snip>
4 HTMLParserの弱点
特定のタグが不完全なウェブサイトの場合はfeedメソッド実行時にエラーが発生します(例えばimgタグがきちんと閉じていない場合)。