HTML解析に使われるHTMLParserとは?BeautifulSoupについても解説
HTML解析ができるHTMLParserを使ってみたいと思ったことはありませんか?
興味があっても、プログラムの知識を必要としていて、なんとなく難しそうですよね?
今回の記事では、HTMLParserに興味があるけれど、手を出しにくいという方のために
- HTMLParserとは何か?
- HTMLParserはどう使うのか?
- Beautiful Soupとは何か?
などについて詳しく解説していきます。
この記事を読むことで、HTMLParserの基本的な使い方がわかるようになりますよ。ぜひ、最後まで読んでくださいね。
HTMLの解析とは?どんな時に使うもの?
そもそも、HTMLを解析するとはどういうことなのでしょうか?
Webサイト上にある特定のデータを抽出する技術をスクレイピングといいます。
データ収集やデータを分析・加工をすることで、新しいコンテンツを作りたいときなどにこの技術が使われます。
スクレイピングする上で必要となるものが、HTML文書の解析なのです。
こういったHTML文書の解析ができるものを総称してHTMLパーサーといいます。
HTMLパーサーは、HTML文書を解析して、プログラム内で扱いやすいデータに置き換える処理を行います。
今回は、スクレイピングなどで利用されるHTMLパーサーについて、2つ紹介します。
- HTMLParserについて
- Beautiful Soupについて
どちらもPythonの実行環境があれば使えるライブラリです。
Beautiful Soupは外部ライブラリなので、インストールする必要がありますね。
HTMLParserについて
まずはHTMLParserの紹介をしていきます。
HTMLParserはPythonの標準ライブラリに含まれてるHTMLパーサーです。
HTML文書を読み込ませることにより、HTMLのタグを抽出したり、条件に合う属性のテキストを取得したりすることができます。
実はこの後に説明するBeautifulSoupでも、内部でHTMLParserを使うことができます。
BeautifulSoupの方が扱いやすいと言われますが、外部ライブラリを使いたくない場合などにHTMLParserは便利なライブラリです。
ここでは、HTMLParserの基本的な処理を3つお伝えします。
- HTMLタグをすべて解析
- 特定のタグのテキストを取得
- 特定の属性を持つタグのテキストを取得
それぞれ詳しく見ていきましょう。
HTMLタグをすべて解析
まずは、HTMLタグとデータを出力する例を紹介します。
from html.parser import HTMLParser
class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print(f'開始タグ[{tag}]')
def handle_endtag(self, tag):
print(f'終了タグ[{tag}]')
def handle_data(self, data):
print(f'テキスト[{data}]')
parser = MyHTMLParser()
parser.feed('<html><head><title>HTMLParserの処理</title></head><body><h1>HTMLタグを解析</h1></body></html>')
開始タグ[html]
開始タグ[head]
開始タグ[title]
テキスト[HTMLParserの処理]
終了タグ[title]
終了タグ[head]
開始タグ[body]
開始タグ[h1]
テキスト[HTMLタグを解析]
終了タグ[h1]
終了タグ[body]
終了タグ[html]
Pythonコードについて、上から解説していきますね。
1行目の「from html.parser import HTMLParser」にて、HTMLParserをインポートしています。
このHTMLParserを使うために独自クラスを作成します。
「class MyHTMLParser(HTMLParser):」を作成し、handle_starttag、handle_endtag、handle_dataというメソッドを使って、タグに応じた処理をオーバーライド(上書き)しています。
例えば、handle_starttagは、タグ開始にあわせて呼び出されるメソッドです。
こうした各メソッドの処理を実装することで、独自のパーサーを定義することができます。
最後のfeedメソッドが読み込まれたときに、定義したパーサーが実行されます。
解析する文章はfeedメソッドの第1引数に渡したHTML文書となります。
特定のタグのテキストを取得
続いて、HTMLタグの中で特定のタグのみを抽出するパーサーを作ってみます。
from html.parser import HTMLParser
import re
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.parse_head = False
self.headtag_text = []
def handle_starttag(self, tag, attrs):
if re.match('^h[1-9]$', tag):
self.parse_head = True
def handle_data(self, data):
if self.parse_head:
self.headtag_text.append(data)
self.parse_head = False
parser = MyHTMLParser()
parser.feed('''
<h1>見出しの取得</h1>
<h2>1.特定のタグかどうか</h2>
<p>フラグで判断</p>
<h2>2.引数のdataをリストに保存</h2>
<h3>フラグを戻す</h3>
''')
print("\n".join(parser.headtag_text))
見出しの取得
1.特定のタグかどうか
2.引数のdataをリストに保存
フラグを戻す
このコードでは、特定のタグ<h1>, … ,<h9>のテキストを抽出する処理を行っています。
MyHTMLParserクラスを定義して、handle_starttagの部分で、タグが<h1>, … ,<h9>のどれかであるか判定しています。
特定のタグであった場合、self.parse_headのフラグをTrueにしましょう。
handle_dataが呼び出されたときに、self.parse_headがTrueであれば、リストに加えていきます。
ここで、フラグをFalseに戻しておく必要がありますね。
最後にリストを1行ずつ出力することで、特定のタグのテキストを抽出することができます。
特定の属性を持つタグのテキストを取得
今度は、タグだけでなく、属性に対しても特定のものを抽出するパーサーを考えます。
from html.parser import HTMLParser
import re
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.parse_head = False
self.headtag_text = []
self.parse_class = ''
def handle_starttag(self, tag, attrs):
d = dict(attrs)
if re.match('^h[1-9]$', tag) and self.parse_class in d.get('class', ''):
self.parse_head = True
def handle_data(self, data):
if self.parse_head:
self.headtag_text.append(data)
self.parse_head = False
def feed(self, content, class_=''):
self.parse_class = class_
super().feed(content)
parser = MyHTMLParser()
parser.feed('''
<h1>見出しの取得</h1>
<h2 class="grep">1.特定のタグかどうか</h2>
<p>フラグで判断</p>
<h2 class="grep">2.引数のdataをリストに保存</h2>
<h3>フラグを戻す</h3>
''', class_='grep')
print("\n".join(parser.headtag_text))
1.特定のタグかどうか
2.引数のdataをリストに保存
HTML文書のタグが<h1>, … ,<h9>のものの中で、さらにclass属性がgrepのものを抽出する処理を書いています。
MyHTMLParserクラスの中で、今回はfeedメソッドの処理をオーバーライドしていますね。
class_に指定されている値をself.parse_classに代入して、feedを実行します。
def handle_starttag(self, tag, attrs):
d = dict(attrs)
if re.match('^h[1-9]$', tag) and self.parse_class in d.get('class', ''):
self.parse_head = True
attrsには、属性のデータが(属性名, 値) のペアでリストとして保存されています。
このattrsを辞書型に変換し、getメソッドで、属性名がclassのものを取得しています。
その中に先ほどのself.parse_classに代入した値があれば、Trueを返しましょう。
タグが<h1>, … ,<h9>かつ、class=”grep”であれば、self.parse_headがTrueになります。
このフラグを利用して、handle_dataメソッドの部分で、テキストを保存するかどうかを判断します。
Beautiful Soupについて
HTMLParserに続いて、HTML文書のパーサーとして使えるPythonライブラリをもう1つ紹介します。
Beautiful Soupは、HTMLParserより短いコードで記述でき、簡単に目的のデータ取得ができます。
外部ライブラリなのでインストールする必要がありますね。
こちらのライブラリでも同じようにデータを取得してみましょう。
具体的に以下の2つの方法を試してみます。
- 特定のタグのテキストを取得
- 特定の属性を持つタグのテキストを取得
それぞれ説明していきましょう。
特定のタグのテキストを取得
まずは、特定のタグのテキストを取得する方法を紹介します。
from bs4 import BeautifulSoup
html_doc = '''
<html>
<head>
<title>タイトル</title>
</head>
<body>
<h1>BeautifulSoupについて</h1>
<ul>
<li>インストールしてみよう</li>
<li>HTML文書を解析してみよう</li>
<li>色々な処理を試してみよう</li>
</ul>
</body>
</html>
'''
soup = BeautifulSoup(html_doc, 'html.parser')
print('title: ', soup.find('title').text)
print('h1: ', soup.find('h1').text)
print('li: ', soup.find('li').text)
title: タイトル
h1: BeautifulSoupについて
li: インストールしてみよう
「from bs4 import BeautifulSoup」でBeautifulSoupをインポートします。
bs4は、BeautifulSoupが入っているパッケージの名前です。
HTML文書をBeautifulSoupの第1引数に渡して、第2引数に使用するパーサーを指定するだけで解析をしてくれます。
soup.find(‘タグ名’)で、どのタグの要素を取得するか指定します。これに.textとつけることで、要素内のテキスト部分を取得できますよ。
実行結果のliタグを見るとわかると思いますが、soup.find(‘タグ名’)で取得できるものは最初の要素のみです。
すべての要素を取得したい場合は、以下のように記述してみてください。
for element in soup.find_all("li"):
print('li: ',element.text)
特定の属性を持つタグのテキストを取得
BeautifulSoupの場合でも、特定の属性を持つタグを取得できます。
from bs4 import BeautifulSoup
html_doc = '''
<html>
<head>
<title>タイトル</title>
</head>
<body>
<h1>BeautifulSoupについて</h1>
<ul>
<li>インストールしてみよう</li>
<li class="grep">HTML文書を解析してみよう</li>
<li class="grep">色々な処理を試してみよう</li>
</ul>
</body>
</html>
'''
soup = BeautifulSoup(html_doc, 'html.parser')
for element in soup.find_all("li", {'class': 'grep'}):
print(element.text)
HTML文書を解析してみよう
色々な処理を試してみよう
soup.find_allの第2引数に{属性名, 値}を足すことで、特定の属性を持つ要素を取得できます。
上記では、class名がgrepのli要素をすべて取得しています。
未経験でも確実にプログラミングスキルを身につけられる!
【DMM WEBCAMP】では、専属コーチが卒業まで伴走します!
✔短期間で効率的にプログラミングスキルを身につけたい
✔プログラミングを独学で進めていくのが不安
✔家での時間を有効に使ってスキルアップがしたい
といった方におすすめです!
\実践的なスキルが身に付くカリキュラム/
まとめ:HTMLParserを使って様々な実装を試してみよう
今回は、HTMLParserの基本的な使い方について説明してきました。
Pythonの環境が必要となりますが、HTMLParserを使うとHTML文書の中の特定のデータ抽出ができるということがわかっていただけたでしょうか。
同じようなパーサーとして、Beautiful Soupについても解説させていただきました。
基本を覚えれば、コードを書き換えるだけで、様々なデータを抽出することができるようになりますよ。
今回の記事が少しでも参考になれば幸いです。
【DMM WEBCAMP】は受講生の97%が未経験からのスタート!
充実のサポート体制で、プログラミングスキルを確実に身につけられます!
✔一人ひとりに合わせた学習計画で進められるため、仕事や学校と両立できる
✔未経験者のために開発された実践的なカリキュラムを用意
✔︎専属コーチが卒業まで学習をサポート
\目的別で選べる3つのコース/