きっかけ
自分が持っている書籍の管理として、読書メーターを使いはじめました。
(といっても、ただバーコードで読み込むのが使いたかっただけ)
個人的には、いろいろ項目をカスタマイズしたいため、最終的にGoogleスプレッドシートなりで管理しようとしています。
しかし、公式の機能で書籍情報のエクスポートはできない。
(フォームをのぞいていると、だいぶ昔からエクスポートの要望はあるそうだけど、一向に実装されないそうな)
そんな困ったときには、Pythonが使えるのでスクレイピングを用いて、最終的にCSVとして出力するコードです。
全体のコード
イメージ
手書きですが、操作のイメージを描いてみました。
import requests
import bs4
import time
import pandas as pd
# JSver
from selenium import webdriver
import chromedriver_binary
from selenium.webdriver.chrome.options import Options
# urlからHTMLの中身を取得
def get_soup_url(url):
res = requests.get(url)
html = res.text
soup = bs4.BeautifulSoup(html, 'lxml')
return soup
# urlからHTMLの中身を取得 JSver
def get_soup_url_js(url):
options = Options()
options.set_headless(True) # Headlessモード
driver = webdriver.Chrome(chrome_options=options)
driver.get(one_url)
html = driver.page_source.encode('utf-8')
soup = bs4.BeautifulSoup(html, "html.parser")
return soup
# soupから各種要素をリストに追加
def append_list_element(soup, list_add):
for book in soup.select('div.detail__title'):
one_url = "https://bookmeter.com" + book.a.get("href")
# soup_one = get_soup_url(one_url)
soup_js = get_soup_url_js(one_url)
# 要素を抜き出す
title = soup_js.select('div.header__inner')[0].h1.text
author = soup_js.select('div.header__inner')[0].ul.text
page = soup_js.find_all(class_="bm-details-side__item")[-1].text
amazon_url = soup_js.select_one("li._3jlUehstt7-3W8HFJMgE94._1HTll1phkIA_FlA27ZN9ZM").a["href"]
img_link = soup_js.select_one('div.group__image').img["src"]
# リストに追加
list_add.append([title, author, page, amazon_url, img_link])
time.sleep(3)
# 次のリンクを見つける
# soupは現在のページのHTML
def get_next_link(soup):
for i in soup.select("a.bm-pagination__link"):
if "次" in i:
next_ = i["href"]
else:
pass
return "https://bookmeter.com" + next_
# 最初のURL
soup = get_soup_url("")
list_element = []
# 1回目
append_list_element(soup, list_element)
# 2回目以降
while True:
try:
next_link = get_next_link(soup)
except UnboundLocalError:
print("Done!")
break
soup = get_soup_url(next_link)
append_list_element(soup, list_element)
# 保存
df = pd.DataFrame(list_element, columns=["title", "author", "page", "amazon_url", "img_link"])
df.to_csv("path")
早速全体のコードです。
注意点としては、
他のフォルダもタグが同じだったら、上手く動くと思います。
(確認できていません🙏)
以下、詳しく中身を見ていきます。
コードの説明
流れ
関数の説明
get_soup_url(url)
urlからHTMLの中身を取得
def get_soup_url(url):
res = requests.get(url)
html = res.text
soup = bs4.BeautifulSoup(html, 'lxml')
return soup
get_soup_url_js(url)
urlからHTMLの中身を取得 JSver
def get_soup_url_js(url):
options = Options()
options.set_headless(True) # Headlessモード
driver = webdriver.Chrome(chrome_options=options)
driver.get(one_url)
html = driver.page_source.encode('utf-8')
soup = BeautifulSoup(html, "html.parser")
return soup
append_list_element(soup, list_add)
soupから各種要素をリストに追加
def append_list_element(soup, list_add):
for book in soup.select('div.detail__title'):
one_url = "https://bookmeter.com" + book.a.get("href")
# soup_one = get_soup_url(one_url)
soup_js = get_soup_url_js(one_url)
# 要素を抜き出す
title = soup_js.select('div.header__inner')[0].h1.text
author = soup_js.select('div.header__inner')[0].ul.text
page = soup_js.find_all(class_="bm-details-side__item")[-1].text
amazon_url = soup_js.select_one("li._3jlUehstt7-3W8HFJMgE94._1HTll1phkIA_FlA27ZN9ZM").a["href"]
img_link = soup_js.select_one('div.group__image').img["src"]
# リストに追加
list_add.append([title, author, page, amazon_url, img_link])
time.sleep(3)
get_next_link
次のリンクを見つける
def get_next_link(soup):
for i in soup.select("a.bm-pagination__link"):
if "次" in i:
next_ = i["href"]
else:
pass
return "https://bookmeter.com" + next_
その他のポイント
ChromeのWebdriverのinstall
参考:[selenium向け]
ChromeDriverをpipでインストールする方法(パス通し不要、バージョン指定可能) - Qiita
JavaScript込みのページのスクレイピングに対応するためには、Seleniumを使用します。
Webdriverのinstallの手順は、
- chromeのversionの確認 81.0.4044.138
- install
pip install chromedriver-binary==81.0.4044.138
Topページから、各本のページに移る
各本の個別のページはこのようになっており、
ここから、
append_list_element(soup, list_add)が対応しています。
pandasでCSVを書き出す
df = pd.DataFrame(list_element, columns=["title", "author", "page", "amazon_url", "img_link"])
df.to_csv("path")
抜き出した情報から、CSVを作成します。
参考
- Beautiful Soup のfind_all( ) と select( ) の使い方の違い | ガンマソフト株式会社
- Python Webスクレイピング テクニック集「取得できない値は無い」JavaScript対応@追記あり6/12 - Qiita
- Pythonでページ遷移を繰り返しながらスクレイピング - Qiita
記事の感想をリアクションでお願いします!