見出し画像

PythonでWebスクレイピングをやってみた ~3~

では今回作成したコードを見ていきます。

以下はWebスクレイピングに必要なrequestsとBeautifulSoupのライブラリをインポートしています。

import requests
from bs4 import BeautifulSoup

requestsとBeautifulSoupのライブラリをPythonにインストールしないとライブラリとして使えませんが、インストールするには「pip install requests」や「pip install beautifulsoup4」などのコマンドでインストールできます。

以下は、requestsモジュールを使って、Webページを取得するための部分になります。変数urlに今回だと「ぐるっとパス 活用ブログ」のURLを入力して、requests.get(url)でWebページが取得できます。

url = 'https://www.rekibun.or.jp/grutto/blog/20230925-4896/'
res = requests.get(url)

以下は、コードのコメントにもあるように文字化け対策になります。

# 文字化け対策
text = res.content.decode(encoding=res.apparent_encoding)

ここでいきなりres.textとしたら文字化けしてしまったので、今回は上の文字化け対策を入れました。

以下は、取得したWebページを行毎に分けてリストに格納している部分になります。

# 文字列を行で分割
lines = text.splitlines()

HTMLの構造を解析してBeautifulSoupを使って文字列を抽出するのであれば上の作業は不要かもしれませんが、今回はブログ中のミュージアム名を抽出するのにBeautifulSoupを使わないのでわざわざこんなことをしています。

以下は、取得したWebページから「会場:」という文字が含まれている行だけを抜き出して、その行から「会場:」と「<」以降を削除する部分になります。

# 「会場:」が含まれている行だけを処理
processed_lines = []
for line in lines:
    if target_string in line:
        # 「会場:」と「<」以降を削除
        modified_line = line.replace(target_string, '').split('<')[0]
        processed_lines.append(modified_line + '\n')

最初にprocessed_lines = []としてブログ中のミュージアム名の行を格納するリストを初期化しています。次にforループで各行を読み出して「会場:」という文字(変数target_string)が含まれていたらその行の「会場:」という文字を削除してその後に「<」で分割した最初の文字列に改行コードを付加してprocessed_linesリストに追加しています。

なんでこんなことをしているかと言うと、なぜかミュージアム名のあとに<br />というHTMLタグがあったからです。こんな風にWebスクレイピングでは実際に取得したWebページの内容を見ながら順次個別対応していくしかないみたいです。

以下は、ここまで抽出した行から重複している行を削除している部分になります。

# 重複している行を削除
unique_lines = list(set(processed_lines))

一つの会場で2つの展覧会が開催される場合もあるので、重複するミュージアム名を削除する必要がありました。

以下は、csvファイルに出力する際の見出し行を追加している部分になります。

# csvファイルの1行目に見出しを追加
unique_lines.insert(0, '名称\n')

Googleマップにcsvファイルを読み込ませる時、先頭は見出し行にしたいので、この処理を行っています。

以下は、csvファイル形式で保存するファイル名をページタイトルにしたかったので追加しました。

# 保存するファイル名をページタイトル.csvにする
soup = BeautifulSoup(text, "html.parser")
output_file_name = soup.title.string.split(' ')[0] + '.csv'

ここで初めてBeautifulSoupを使っていますが、csvファイルのファイル名を何か固定の名前にしてしまえば、今回はBeautifulSoupを使うことなく済んだと思います。

なぜわざわざこんなことをしてファイル名を決めているかと言うと、Googleマップにcsvファイルを読み込ませる時に、デフォルトでファイル名がレイヤー名になってしまうので、レイヤー名を変更する手間を省くためにこんなことをしています。

soup.title.stringで「ぐるっとパス 活用ブログ」のタイトルを取得できますが、実際のタイトルは例えば「1~2月のおすすめ展覧会(入場) | 東京・ミュージアム ぐるっとパス2023」と長いので、ここでは空白文字で分割した最初の文字列だけを取り出してcsvのファイル名にしています。

以下は、実際にcsvファイルに書き出す部分ですが、ここで結構ハマりました。

# ファイルに結果を書き込む(utf_8_sigでエンコード)
with open(output_file_name, 'w', encoding='utf_8_sig') as output_file:
    output_file.writelines(unique_lines)

最初はエンコードを「shift_jis」にしていたのですが、これだとエラーで保存できませんでした。調べたところどうも森鷗外の「鷗」の字がshift_jisに変換できないらしく、そのエラーを回避するためには結構面倒な処理が必要らしいので諦めました。

次に今度はエンコードを「utf_8」にしたのですが、これだと書き出したcsvファイルがExcelでそのまま開けないということになりました。

そんなわけで色々調べたところエンコードを「utf_8_sig」にすればExcelでもそのまま開けるということだったので、今回はそうしています。

今回初めてWebスクレイピングをやってみて分かりましたが、Webスクレイピング自体はそんなに難しくなくても文字コードが絡んで来るので、文字コードをうまく扱う処理をしないとやりたいことができないみたいです。

そんなわけで今回実際に取得したデータで作成したcsvファイルの中身は下記のようになりました。

名称
郷さくら美術館
相田みつを美術館
パナソニック汐留美術館
紙の博物館
世田谷美術館
NTTインターコミュニケーション・センター [ICC]
地下鉄博物館
井の頭自然文化園 水生物館(分園)特設展示場
多摩動物公園 ウォッチングセンター展示スペース
横浜みなと博物館内(柳原良平アートミュージアム)
石洞美術館
文京区立森鷗外記念館
五島美術館
旧東京音楽学校奏楽堂
東洋文庫ミュージアム
書道博物館
東京都写真美術館 2階展示室
長谷川町子美術館/長谷川町子記念館
東京富士美術館
江東区芭蕉記念館
国立映画アーカイブ展示室(7階)
大倉集古館
東京都庭園美術館
武蔵野市立吉祥寺美術館
埼玉県立歴史と民俗の博物館
松岡美術館
新宿区立漱石山房記念館
東京都現代美術館 コレクション展示室 1F / 3F
古代オリエント博物館
文化学園服飾博物館
多摩六都科学館
三鷹市山本有三記念館
東京都美術館 ギャラリーA・C
朝倉彫塑館
神奈川県立歴史博物館
葛西臨海水族園 本館1階「渚の生物」エリア手前
永青文庫
たましん美術館
千葉市美術館
新宿区立新宿歴史博物館
小平市平櫛田中彫刻美術館
三鷹市美術ギャラリー
八王子市夢美術館
調布市武者小路実篤記念館
たばこと塩の博物館
渋谷区立松濤美術館
泉屋博古館東京
印刷博物館 展示室
埼玉県立近代美術館
井の頭自然文化園 動物園(本園)資料館1階
そごう美術館
ちひろ美術館・東京
ミュゼ浜口陽三・ヤマサコレクション
東京オペラシティ アートギャラリー

次回はこのcsvファイルを使って、Googleマップのマイマップを作成する方法について書くことにします。

この記事が気に入ったらサポートをしてみませんか?