【データ収集】Webスクレイピングことはじめ
webサイトからデータとってくる単純作業を自動化(スクレイピング)していこうの巻
注意事項~具体的方法をざっくり説明するよ(5,900文字…?!?!
※
例のごとく、こうやって誰かに教える感じで書くと学習効果が高いので教える感じで書きます
調べてますが、理解に間違いあればすみません。教えて貰えるとありがたいです
スクレイピングは、鑑定業界ならどうするのが良いとかいうのはなく、方法は各自やりやすい方法でやれば、という感じであります
古い情報とかもいっしょくたにいっぱい転がってる中で、この記事書いてる2023/1/14時点でちょろっと触ってみてわかったことや躓いたことを書いていきます
※当然ながら、スクレイピング禁止されてるサイトではだめです
収集データを個人使用する場合も、著作権やマナー等注意事項を調べて軽く頭に入れるべき
あと、下記事件の概要は知っといた方がいいと思います
これがあるため、スクレイピングやる全員が、逮捕・勾留されるリスクを負っているとも言える
岡崎市立中央図書館事件 - Wikipedia
スクレイピング概要
目的
・特定のWebサイト上の欲しい情報(テキストデータ、画像データ等)を自動的に取得すること
手段
プログラムを用いて、
・ブラウザ(Chromeとか)を操作する
ex. リンクをクリックしたり、テキストボックスに文字入力したり
・HTMLソースを取得する
・取得したHTMLソースから欲しい文字列をとってくる
ex. リンク先になってるURLの取得、表示されている文字列の取得
・あと、画像等のファイルをダウンロードしたり
VBAかPythonかはたまたその他言語か
結論: どれでもよ◎(迷ったらPythonか)
自分はPythonで始めたので、ここではPythonでやる場合について書きます
Excel士の人の場合、なんでもExcelに取り込んでVBAで操作するのが馴染みあるかと思うのですが、自分の場合は、VBA少しだけ書いてみたらJava経験あるプログラミング初心者には書きづらく…
取り込んだデータをあっちゃこっちゃ加工・分析するのにはPythonが良く、記述がとても簡潔で、Webや書籍に情報がたくさんあるので、Pythonでやることにしました
VBAでもPythonでも「Celenium」というライブラリを使ってGoogle Chromeを操作するのが一般的だと思います
※ VBA単体ではIEの操作はできてたけど、2022年でサポート終了した
必要なライブラリ
以下のライブラリをPythonの仮想環境にインストールして始めます
その他のライブラリは必要に応じて適宜
・Helium - Celeniumのラッパーライブラリ
Celeniumとは、ブラウザ操作するためのものだよ(HTMLソースの一部取得とかもできるけど、それは後述のBeautiful soupでやったほうがいいっぽい)
HeliumインストールするとCeleniumも入ってるし、Celeniumのメソッドとかもだいたい使えるからHelium入れといて損は無い
Celeniumより簡潔に書けるところがあるので、結局Celeniumのメソッド使うところも多々あるものの、積極的に使っていきたい
可読性も良い
Heliumについては、日本語の情報が少ないが、以下のサイトを読む。
まずここ
zenn.dev
公式
selenium-python-helium.readthedocs.io
CeleniumやBeautiful soupそれぞれの使い所。どうやって記述するかの参考になる
su-gi-rx.com
・Beautiful soup4
取得したHTMLソースから特定の文字列を抽出(抜き出したり)するやつ
「pip install bs4」でインストールできちゃったけど、正式なのは「beautifulsoup4」でした。危なかった…ちゃんと調べないと
pip install beautifulsoup4
※IDEについて
「PyCharm」使ってます
Python専用で使いやすいです
大学生だと無料で使える
※仮想環境について
Pythonでは、まず仮想環境を作成し、それに上記ライブラリ(Celeniumとか)を適宜インストールし、そこでプログラムを実行します
方法
1.Chromeを立ち上げてドライバオブジェクト取得
Heliumのstart_chromeメソッド一発。戻り値にドライバ。
※
Chromeの操作をする場合、Chrome DriverとChrome本体それぞれのバージョンを合わせる必要がある。
基本的にはHeliumのインストール時にChrome Driverもついてくるので、なんもしなくてもいけることもあるらしいが、私はエラー出てだめだった。
実行してエラー出る場合、以下から、自分の使ってるChrome本体と同じくらいのバージョンのChrome Driverをゲットして、どこかにおいて、Pathを通す。または、Heriumインストール時に元々入ってたChrome Driverと置き換える。
chromedriver.chromium.org
2.お好みの操作
・ブラウザ操作
クリックしたい箇所がテキスト(文字列)でできているなら、Heriumのclickメソッドが使える。
でも、テキストだけどうまくいかない、又は画像になってたりする場合は、Celeniumのメソッドを使って要素を指定した上でJavascriptでクリック等の操作をする。
下記は、要素の取得を行うメソッド。ID、Name、XPath、CSSセレクタ等いろいろ条件にできる。
・find_elementメソッド 条件に当てはまる最初の要素を返す
・find_elementsメソッド 条件に当てはまる全ての要素をリストで返す
要素の探し方は、Chromeで対象のWebサイトを開いて、適当なとこで右クリック「検証」から、クリック等したい要素がHTMLのどこにあたるのかを探す。Chrome便利。
基本的には、Helium試す→ダメならCelenium。Helium使えるとこでは使うのが一番作業時間短い。
注意
(1)クリックはJavaScript使う
Celeniumでもクリック操作できるが、画面外の要素はエラー出て落ちる。
なので、Celeniumのクリックメソッドは使わずに、execute_scriptメソッドを利用しJavaScriptのクリック操作を行うこと。
(2)ウェイトかける
適宜ウェイトをかけてご迷惑にならないようにしよ、ってのと。(time.sleepメソッド)
画面遷移後に要素が表示されてないのに操作しようとしてエラーになることも?その場合もウェイト必要かも。
Heliumは、その要素が表示されるまで、10秒まで勝手に待つようになってた気がする。
(3)Celeniumはバージョンアップしてメソッドの記述変わってる
find_element_by_idメソッド等は、ネットや本でいっぱい使われてますが、今使用できないです。
今は、find_elementメソッドになっており、第一引数で何を使って要素を指定するのか(ID、Xpath、CSSセレクタ等)を書く。下記ソースコード一行目の「By.ID」は、HTMLのID。第二引数は、その値。
element_check_logout = driver.find_element(By.ID, 'auto-logout') # チェックボックスにチェックが入っていなかったらチェックする if not element_check_logout.is_selected(): driver.execute_script('arguments[0].click();', element_check_logout) time.sleep(NUM_SHOW_PAGE_NEED_SLEEP)
・HTMLソースの解析
ブラウザ操作で対象のページを表示させたあとは、Beautiful soupの出番
(1)HTMLソースをBeautiful soupオブジェクトにする
個人的に、全部の具材が入った寄せ鍋みたいなイメージ。ここからお好みの具をすくってくるぞ。
html = driver.page_source
soup = BeautifulSoup(html, "html.parser")
(2)Beautiful soupオブジェクトから必要な文字列等を抽出する
Beautiful soupオブジェクトからfind系メソッドかselect系メソッドで文字列抽出。基本的にはどっち使っても良いのだが…
find系: 要素名、属性名指定できる←可読性が良い
find_all() 全ての要素をリストで返す
find() 最初に見つかった要素1つだけ返す
select系: CSSセレクタ使える。←CSSセレクタは他に被ってるかとか気にせず一発で取れる(ただし、動的な何かが含まれる場合は工夫必要)
select() 全ての要素をリストで返す
select_one() 最初に見つかった要素1つだけ返す
trs = soup.findAll("tr", bgcolor="#FFFFE0")
記述例
# -------------------------------------------------- # 株価を取得するメソッド # -------------------------------------------------- def get_kabuka(): list_kabuka = [] driver = start_chrome('https://quote.jpx.co.jp/jpx/template/quote.cgi?F=tmp/stock_search') # ※要修正※ # チェックボックスクリックが動作していないかも click('プライム') click('スタンダード') click('グロース') select(ComboBox('25件ずつ'), '100件ずつ') click(Button('検索開始')) time.sleep(NUM_SHOW_PAGE_NEED_SLEEP) while True: html = driver.page_source soup = BeautifulSoup(html, "html.parser") trs = soup.findAll("tr", bgcolor="#FFFFE0") for tr in trs: rows = [] for cell in tr.findAll('td'): rows.append(cell.get_text().replace("\r\n", "") .replace("\n", "") .replace("\t", "") .replace("\xa0", "")) # .replace(",", "") if rows: list_kabuka.append(rows) if Link('次のページ').exists(): click(Link('次のページ')) time.sleep(NUM_SHOW_PAGE_NEED_SLEEP) else: break kill_browser() # csvファイルに書き込み with open(PATH_KABUKA, 'w', newline="", encoding="utf_8_sig") as f: writer = csv.writer(f) writer.writerows(list_kabuka) return list_kabuka
まとめ
Helium、できなければCeleniumでブラウザ操作
↓
Beautiful soupでHTMLの鍋から好きな具材を拾おう
サイトによってどうやって書いたら拾えるかは、いろいろ手段があるので考えようね