BeautifulSoup4でタグをCSVに変換する
- 作成日: 2021-04-15
- 更新日: 2023-12-24
- カテゴリ: BeautifulSoup4
BeautifulSoup4で得たタグをCSVに変換する
PythonにはHTML/XMLパーサーとしてBeautifulSoup4という外部ライブラリがあります。
これを使うと簡単にHTML/XMLなどのドキュメントをパースすることが可能です。
今回は、このBeautifulSoup4を使って得たタグのリストをCSVファイルに書き込んでみたいと思います。
具体的には↓を見ていきます。
- CSVとは?
- 単一のulをCSVに変換する
- 複数のulをCSVに変換する
- テーブルをCSVに変換する
CSVとは?
CSV(シーエスブイ)とは「Comma Separated Values」の略です。
これは直訳すると、「カンマで区切られた複数の値」という意味になります。
たとえば↓のようなものがCSVフォーマットの文字列です。
one,two,three
cat,dog,bird
値がカンマ(,
)で区切られて並べられています。
この時一行を「行」または「レコード」といい、これが1つの塊のデータとして扱われます。
行(レコード)が複数並んでいる状態はつまり複数のデータがある状態です。
たとえば学校の名簿を考えてみたいと思います。
名簿には学年や名前、出席番号などが書かれています。
この時生徒1人分のデータがレコードになります。
つまり↓ということです。
1,田中太郎,101
1,山田花子,102
1,原人北京,103
...
HTMLなどののデータをこのようなCSVに変換したいというのは割とよくあることです。
スクレイピングなどでデータを取得して、そのHTMLのデータから目的のデータを抽出して、それをファイルにCSVで保存するという具合にです。
リスト内包表記について
この記事でよく使われるリスト内包表記の解説です。
知ってる方は飛ばしてください。
リスト内包表記とは↓のようなフォーマットの表記です。
結果 = [ 要素 for 要素 in リスト ]
↑のようにするとリスト内の要素が新しく出来たリストに保存され、結果として返ってきます。
具体的にコードにすると↓のようなコードになります。
lis = [1, 2, 3]
res = [el for el in lis]
print(res)
↑のコードを実行すると↓のような結果になります。
[1, 2, 3]
リスト内包表記ではfor
の左側にある要素に対して加工などを行うことができます。
たとえば要素を10
で割るという加工を行うと↓のようなコードになります。
lis = [1, 2, 3]
res = [el / 10 for el in lis]
print(res)
↑のコードを実行すると↓のような結果になります。
[0.1, 0.2, 0.3]
リスト内包表記は普通のfor
文と比べてコードが短くなるという特徴があります。
単一のulをCSVに変換する
それでは単一のul
タグをレコードに変換してCSVファイルに保存してみます。
例としては↓のようになります。
from bs4 import BeautifulSoup
import csv
# 元になるHTML
code = '''<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
'''
soup = BeautifulSoup(code, 'html.parser') # パースする
row = [li.text for li in soup.find_all('li')] # liタグのテキストをリストにする
with open('out.csv', 'w') as fout: # 書き込み用ファイルを開き
writer = csv.writer(fout) # ライターを作成し
writer.writerow(row) # レコードを一行書き込む
code
をBeautifulSoupでパースしてsoup
という結果を得ます。
このsoup
のメソッドfind_all()
を呼び出してli
タグのリストを得ます。
それをリスト内包表記で回してli.text
をリストの要素に格納していきます。
これでrow
というli
タグのテキストが格納されたレコードができました。
あとはout.csv
というファイルを開いて、そのファイルオブジェクトをcsv.writer()
に渡します。
(今回はCSVファイルの保存にcsv
モジュールを使います)
writer
を作ったらwriterow()
メソッドに先ほどのrow
を渡して書き込みます。
これであとはwriter
が良い感じのフォーマットにしてくれます。
書き込んだout.csv
ファイルの中身は↓のようになっています。
one,two,three
ul
内のデータがCSVとして保存できてますね。
複数のulをCSVに変換する
複数のul
タグをCSVに変換するには↓のようにします。
from bs4 import BeautifulSoup
import csv
# 元になるHTML
code = '''<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
<ul>
<li>cat</li>
<li>dog</li>
<li>bird</li>
</ul>
'''
soup = BeautifulSoup(code, 'html.parser') # パースする
mat = [] # 行列
for ul in soup.find_all('ul'): # ulタグを取り出す
row = [li.text for li in ul.find_all('li')] # liを取り出してtextを保存する
mat.append(row) # 行を追加
with open('out.csv', 'w') as fout: # 書き込み用ファイルを開き
writer = csv.writer(fout) # ライターを作成し
for row in mat:
writer.writerow(row) # レコードを一行書き込む
soup
を作ってfind_all()
でul
タグを取り出してfor
文で回します。
そしてそのul
タグからfind_all()
を呼び出してli
タグを取り出します。
そのli
タグはリスト内包表記で回してtext
をリストの要素に保存します。
その結果をrow
として、出来あがったらmat
に追加します。
ちなみにmat
はmatrix
(行列)の略です。
mat
が出来上がったらout.csv
ファイルを書き込みモードで開きます。
そのファイルオブジェクトをcsv.writer()
に渡してwriter
を作ります。
mat
をfor
文で回して行(row
)を取り出し、writer
のwriterow()
メソッドに渡して行(レコード)をファイルに書き込みます。
書き込まれたout.csv
を見ると↓のようになっています。
one,two,three
cat,dog,bird
テーブルをCSVに変換する
テーブルをCSVに変換したい場合は↓のようにします。
from bs4 import BeautifulSoup
import csv
# 元になるHTML
code = '''<table>
<tr>
<td>one</td>
<td>two</td>
<td>three</td>
</tr>
<tr>
<td>cat</td>
<td>dog</td>
<td>bird</td>
</tr>
</table>
'''
soup = BeautifulSoup(code, 'html.parser') # パースする
mat = [] # 行列
# テーブルをパースする
table = soup.find('table')
for tr in table.find_all('tr'): # trタグを取る
row = [td.text for td in tr.find_all('td')] # tdのtextを保存する
mat.append(row) # 行を追加
with open('out.csv', 'w') as fout: # 書き込み用ファイルを開き
writer = csv.writer(fout) # ライターを作成し
for row in mat:
writer.writerow(row) # レコードを一行書き込む
基本的には複数のul
タグのパースと同じです。
まずsoup.find()
でtable
タグを取ります。
そしてtable
タグのfind_all()
でtr
タグを取ってきてfor
文で回します。
tr
タグのfind_all()
でtd
タグを取ってきて、リスト内包表記でtd
のtext
をリストの要素に保存します。
その結果をrow
として、mat
に保存します。
mat
が出来上がったらout.csv
を書き込みモードで開き、writer.writerow()
で行を書き込みます。
おわりに
今回はBeautifulSoup4で取得したデータをCSVに変換してみました。
CSVはスクレイピングなどでもよく使われるデータフォーマットです。
Pythonではモジュールを使えば簡単に変換することができます。
🦝 < カンマで区切ってあげる
🐭 < けっこうです