ども。
一度もブログを書くことなく8月が過ぎてた。
もう9月ってやばくないですか。やばいです。
今回は9/11(水)のみんなのPython勉強会 #49でLTする予定の「アイドルで理解するTF-IDF」のデータ準備編。
TL;DR
アメブロの記事本文以外(投稿日時とか)の多くはJavaScriptで描画されている
Requests + BeatifulSoupでは満足にスクレイピングできない
今回やりたいこと
sora tob sakana official blogから記事のタイトル, 投稿日時, 記事本文をスクレイピングする。
ブログ記事の見た目はこんな感じ。
※ 風花ちゃんのブログを例に出したけど今回は山崎愛ちゃんのブログ記事を対象にする。
ぱっと見、Requestsでレスポンスボディを取ってきてBeautifulSoupに喰わせてやればよさそうに見えるけど、実際にそれで取得できるのはタイトルと記事本文のみ。なぜ投稿日時がJavaScriptで描画されているのか。わからない。
山崎愛ちゃんのブログを選んだ理由
「基本的に1記事につき1つの話題」だから。TF-IDFで記事の特徴語を取ったときに、特徴語が記事のテーマと一致しているかの判断が簡単なように思えた。
あとオサカナのオタクとして、毎日更新されるのを楽しみにしてるから。愛ちゃんはここ数ヶ月毎日更新している。その原動力は知らんけど。
風花ちゃん最近割と更新が多いのでとても嬉しい。
ヘッドレスブラウザを導入する
ヘッドレスブラウザを使ってJavaScriptが実行された後のソースコードを使えばよさそう、ということでその方法を探す。今回はHeadless Chromeを使う。
ブラウザを実際に動かすということでまず必要になるのはSelenium。さくっと入れる。
$ pip install selenium
Chromeのドライバーのパスを指定してやる必要があるけど、chromedriver_binaryを使うとパスを通してくれる。便利かよ。
To use chromedriver just import chromedriver_binary. This will add the executable to your PATH so it will be found.
注意したいのは手元のChromeのバージョンに合ったchromedriver_binaryのバージョンをインストールする必要があるということ。
自分の手元では76.0.3809.132
だったのでこれに合ったバージョンをインストールする。
$ pip install chromedriver_binary==76.0.3809.126.0
Chromeをヘッドレスモードで使うときはChromeのオプションに--headless
を指定する。
コードを書く
import chromedriver_binary # 手元の環境に合わせて76.0.3809.126.0を使う from bs4 import BeautifulSoup as bs from selenium import webdriver from selenium.webdriver.chrome.options import Options def init_driver() -> webdriver.Chrome: options = Options() options.add_argument('--headless') driver = webdriver.Chrome(options=options) return driver def get_soup(driver: webdriver.Chrome, url: str) -> bs: driver.get(url) html = driver.page_source return bs(html, 'html.parser') def main(): # 2019/09/06の山崎愛ちゃんの記事 url = 'https://ameblo.jp/soratobsakana/entry-12521726090.html' driver = init_driver() soup = get_soup(driver, url)
基本形としてはこれで以上。どうでもいいけど今回からType Hintingを導入してみた。
後はいい感じに前処理してCSVで保存する。
詳細は https://github.com/NaoY-2501/tf_idf_with_idol/blob/master/blog_scraper.py を参照のこと。
アイドルで理解するTF-IDFのリポジトリは以下。
↑を見られるとまだTF-IDFが実装できてないことがバレる。
次回は環境構築編を書く予定。