頻繁な更新のあるテーブルやコピペがしにくいテーブルなどからの
データ収集をちょっとでも効率化できないかと思い今回は、
pythonでスクレイピングしてCSVに書き出すコードを書いてみました。
#設定した環境
MacBook Air (13-inch, Mid 2011)
プロセッサ: 1.8 GHz Intel Core i7
メモリ: 4 GB 1333 MHz DDR3
バージョン: 10.11.5
Python: 3.6.2
#準備
BeautifulSoupをインストールします。
BeautifulSoupはHTMLやXMLからデータを取得することのできるライブラリーです。
今回はpipを使ってインストールしました。
$ pip3 install beautifulsoup4
Collecting beautifulsoup4
Downloading beautifulsoup4-4.6.0-py3-none-any.whl (86kB)
100% |████████████████████████████████| 92kB 1.8MB/s
Installing collected packages: beautifulsoup4
Successfully installed beautifulsoup4-4.6.0
他にはeasy_installやapt-get、直接コードをダウンロードしてインストールする方法などがあります。
詳しく以下の公式Documentの"Installing Beautiful Soup"を読んでいただければと思います。
#テーブル要素をスクレイピングしてみる
beautifulsoup4がインストールできたら、
さっそくO'Reillyの新刊情報を取得してみましょう。
2019/03/20更新:書き込みファイルをwithで開くようにしました。
import csv
from urllib.request import urlopen
from bs4 import BeautifulSoup
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# URLの指定
html = urlopen("https://www.oreilly.co.jp/ebook/")
bsObj = BeautifulSoup(html, "html.parser")
# テーブルを指定
table = bsObj.findAll("table", {"class":"tablesorter"})[0]
rows = table.findAll("tr")
with open("ebooks.csv", "w", encoding='utf-8') as file:
writer = csv.writer(file)
for row in rows:
csvRow = []
for cell in row.findAll(['td', 'th']):
csvRow.append(cell.get_text())
writer.writerow(csvRow)
書き出されたCSVはこんな感じになります。
定期的に実行すれば新刊情報を逃すことはありませんね!
ちなみに上のコードではget_text()で指定したので"カートに追加"の列の画像リンクは空になっています。
ISBN,Title,価格,発行月,カートに追加
978-4-87311-755-3,パフォーマンス向上のためのデザイン設計,"2,073",2016/06,
978-4-87311-700-3,データ分析によるネットワークセキュリティ,"3,110",2016/06,
978-4-87311-754-6,UX戦略,"2,592",2016/05,
978-4-87311-768-3,Pythonからはじめる数学入門,"2,419",2016/05,
978-4-87311-767-6,あなたの知らないところでソフトウェアは何をしているのか?,"2,246",2016/05,
978-4-87311-763-8,発酵の技法,"3,110",2016/04,
978-4-87311-765-2,初めてのAnsible,"2,764",2016/04,
978-4-87311-764-5,カンバン仕事術,"3,110",2016/03,
#他のサイトに応用する方法
基本的にはコードの以下の部分を修正することで他のサイトのテーブルも簡単に取得できます。
- 取得したいテーブルのclass名を変更する
- サイト内に同じclass名のテーブルが複数ある場合は、何番目かを[ ]の中の番号で指定する
#テーブルを指定
table = bsObj.findAll("table",{"class":"tablesorter"})[0]
rows = table.findAll("tr")
#CSVについて
自分はMacを使っているので、書き出されたCSVはutf-8でした。
そのままExcelで読み込むと文字化けするので、文字コードを変換して、整形すると使いやすいです。
変換の方法を知りたい方はこちらからどうぞ(別サイト)