5log

日々の仕事の備忘録

BeautifulSoupでスクレイピングしたHTMLをCSVに出力する

PythonによるWebスクレイピングネタ第三弾。今回は取得したデータをCSVに出力する方法を紹介していこうと思います。

前回の記事はこちら

5log.hateblo.jp

はじめに:本記事で取得するデータ

今回は第三弾ということで、取得するデータも少し複雑なものを選んでいこうと思います。

そこで今回は毎日新聞社の新着ニュースのタイトル文言を取得していきます。下記画像の赤枠で囲んだところですね。

f:id:K3105:20190102132829j:plain

スクレイピングするために、このページのソースコードを見てみましょう。

f:id:K3105:20190102133200p:plain

TOPの記事は<p>タグ内に、2番目以降の記事は<li>タグの中に入っています。両方取得するためには、プログラムの記述を変える必要があるので、今回は簡単に取得できそうな<ul>タグ内のニュースタイトルを取得していくことにします。

今回取得したい要素は<span>タグに囲まれていますが、とはいえ<span>という条件でサイト全体から情報を取得すると、余分なタグも多く含まれてしまいます。余分なタグは取得せず、目的の情報にアクセスするために、サイト内のclass要素から範囲を絞っていき、該当の情報を取得していく形を取ろうと思います。

今回は<div class="mainbox">というタグ内の情報を取得後、<ul class="list-typeA">でさらに情報を取得、その中のaタグ全てからテキスト情報を取得し、CSVに出力していきます。

<a>タグに指定されているid情報を使って取得する事もできそうですが、サンプルコードの記述をシンプルにしたいので、今回は上記の方法で進めます。

1. テキストを1行でCSVに出力する。

pythonで取得したデータをCSVに出力するにはPythoncsvというモジュールを使用します。こちらもインストール作業なしで使うことができます。

早速、下記にサンプルコードを書いてみました。

import urllib.request, urllib.error
from bs4 import BeautifulSoup
import csv

# アクセスするURL
url = "https://mainichi.jp/"
# URLを開く
html = urllib.request.urlopen(url)
# BeautifulSoupで開く
soup = BeautifulSoup(html, "html.parser")

# HTMLからニュース一覧に使用しているaタグを絞りこんでいく
tag_mainbox = soup.select_one(".main-box")
tag_listA = tag_mainbox.select_one(".list-typeA")
news_tag = tag_listA.findAll("a")
# 配列の作成。
csvlist = []
for news_txt in news_tag:
    news_txt = news_txt.text
    csvlist.append(news_txt)

# CSVファイルを開く。ファイルがなければ新規作成する。
f = open("output.csv", "w")
writecsv = csv.writer(f, lineterminator='\n')

# 出力
writecsv.writerow(csvlist)

# CSVファイルを閉じる。
f.close()

このプログラムでは、毎日新聞のURLにアクセスして目的のタグにアクセスした後、その中のテキストデータをPythonの配列に保存、そして配列データをCSVファイルに出力する処理を実行しています。CSVへの書き込みには.writerowを使用します。

このPythonファイルを実行すると、実行したファイルと同じ階層に「output.csv」というファイルが作成されるはずです。それを開くと、下記のような結果となります。

f:id:K3105:20190102135105p:plain

これで、CSVデータへのテキスト情報出力が完了しました。

2. テキストを複数行で出力する。

さて、1ではデータを1行で出力しましたが、もう少し綺麗な形になるよう出力したいと思うので、少しプログラムを書き換えてみましょう。

今回は.writerowsを使用して、テキストを複数行で出力します。また、取得したテキスト要素に見出しや項番などもつけていきたいと思います。

import urllib.request, urllib.error
from bs4 import BeautifulSoup
import csv

# アクセスするURL
url = "https://mainichi.jp/"
# URLを開く
html = urllib.request.urlopen(url)
# BeautifulSoupで開く
soup = BeautifulSoup(html, "html.parser")

# HTMLからニュース一覧に使用しているaタグを絞りこんでいく
tag_mainbox = soup.select_one(".main-box")
tag_listA = tag_mainbox.select_one(".list-typeA")
news_tag = tag_listA.findAll("a")
# 配列の作成。表の見出し部分の情報を入力しておく。
csvlist = [["","ニュースリスト"]]
num = 0
for news_txt in news_tag:
    news_txt = news_txt.text
    csvlist.append([num, news_txt])
    num += 1

# CSVファイルを開く。ファイルがなければ新規作成する。
f = open("output.csv", "w")
writecsv = csv.writer(f, lineterminator='\n')

# 出力
writecsv.writerows(csvlist)

# CSVファイルを閉じる。
f.close()

プログラムを修正したら、再びPythonファイルを実行後に「output.csv」ファイルを開きます。

f:id:K3105:20190102140107p:plain

このように、1よりも見やすい形式で出力することができました。

まとめ

CSVで出力できるようになることで、サイト内の情報を目視で調べなくても、Pythonで自動的に情報取得が可能になります。ぜひ皆さんも試してみてください。