ちょっと前から、「Excel×Python最速仕事術」と「退屈なことはPythonにやらせよう」を読んで、Pythonが静かなマイブームになっている、ふーたらです。
で、「Windows10にVisual Studio Code(VS Code)をインストールして日本語化してPythonで開発できるようにするまでの方法ついて。」の記事で書いているように、なんとかVisual Studio CodeでPythonの開発が出来る様になりました。
また、Pythonとは別のお題で、「ExcelのVBAとSeleniumBasicでシネコンのサイトから上映中の映画タイトルをスクレイピングしてExcelシートを作るまでのソースを公開。(コピペOK。たぶん)」って記事を書いていたのを思い出して、Pythonのプログラム記事の1発目に、映画タイトルを取得しようって思い立った次第です。
ってことで、今回のお題は「PythonとSeleniumで簡単スクレイピング?シネコンのサイトから上映中の映画タイトルを取得してCSVで保存する方法について。」です。
事前準備
今回は、Windows10のローカル環境ってのが大前提になっていますので、ご了承下さい。
また、Windows10にPythonがインストールされているってのも大前提です。Pythonのインストールや開発環境のインストールに関しては、こちらをご参照下さい。
一般的にPythonでスクレイピングをしようって時に良く使われるライブラリには、Requests、Beautiful Soup、Selenium等があります。
その中で、今回は以前に作ったExcelとSeleniumBasicのPython版を前提にしようと思っているので、Seleniumを使います。
また、CSV形式で保存する際に、CSVモジュールとopenpyxlライブラリを使用します。この部分のプログラムですが、CSVファイルへの書き込みならopenpyxlライブラリを使わななくて書けると思いますが、「Excel×Python最速仕事術」のサンプルコードから、ちょっくら拝借しておりますので、openpyxlライブラリも使っています。
これらの中で、openpyxlライブラリとSeleniumライブラリは外部ライブラリなので、ターミナルから下のコマンドで事前にインストールしておきます。
pip install openpyxl
pip install selenium
CSVモジュールは標準ライブラリに含まれているので、インストールは不要です。
さらに、今回は、Google Chromeを自動操縦してのスクレイピングを前提としますので、Google Chrome用のWebDriverをダウンロードする必要があります。
Google Chrome用のWebDriverのダウンロードとインストール
Google Chrome用のWebDriverは、こちらのサイトからダウンロードします。
ダウンロードに際しては、ご自身のGoogle Chromeのバージョンにあったものをダウンロードして下さい。
ちなみに、Chromeのバージョンの確認は、Chromeの右上の「Google Chromeの設定」から「ヘルプ」、「Google Chromeについて」を見ましょう。
ダウンロードしたファイルは、解凍すると「chromedriver.exe」が有りますので、今回ブログラムを作成するフォルダに「driver」を言うフォルダを作って、その中に「chromedriver.exe」を移動しておきます。
ここまでで、事前準備やインストールなどは、全て完了です。
サンプルプログラムのソース
四の五の言う前に、まずは、サンプルコードをご覧下さい。
まだ、あまりPython慣れしてないもんで、ご了承下さいね。
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.by import By
import openpyxl
import csv
top_url = "https://www.unitedcinemas.jp/"
theaters = ["kokura", "nakama"]
filename = "move_list1.csv"
list_col = 0
lwb = openpyxl.Workbook()
lsh = lwb.active
driver = webdriver.Chrome("./driver/chromedriver.exe")
for theater in theaters:
full_url = top_url + theater + "/"
driver.get(full_url)
driver.find_element_by_id("gnavi_film").click()
wait = WebDriverWait(driver, 10)
wait.until(expected_conditions.element_to_be_clickable((By.ID, theater + "NowShowing")))
driver.find_element_by_id(theater + "NowShowing").click()
list_row = 1
list_col += 1
lsh.cell(list_row, list_col).value = theater
list_row += 1
for element in driver.find_elements_by_css_selector("#showingList > div > ul:nth-child(2) h3 strong > a"):
lsh.cell(list_row, list_col).value = element.text
list_row += 1
with open(filename,"w") as fp:
writer = csv.writer(fp, lineterminator="n")
for row in lsh.rows:
writer.writerow([col.value for col in row])
ざっと43行のシンプルなコードになっている思います。
この部分をコピペして、実行するだけで、プログラムファイルを置いたフォルダに、「move_list1.csv」なんて、ファイルが出来ていると思います。
それでは、ここから順を追って、サクッと、プログラムの解説です。
プログラム解説
以下、簡単に自分がPythonに慣れるためのメモ的なものをまとめてみました。
「from」と「import」の違いと使い分けについて
まず、最初の7行までで、今回のプログラムに必要なライブラリやモジュールや関数やクラス等を読み込んでいます。
ここで、「from」と「import」が登場してきますが、ここで念のために、「from」と「import」の使い分けについてまとめてみました。
「AAA」というモジュールに「BBB」とうい関数がある場合で、以下の書き方の違いを考えてみましょう。
mport AAA
from AAA import BBB
まず、上の場合にBBBという関数を使うときには、
import AAA
AAA.BBB()
で、BBBという関数を使うことができます。
import の場合は、
from AAA.import BBB
BBB()
で、BBBという関数を使うことができます。
今回のプログラムも
from selenium.webdriver.support.ui import WebDriverWait
と書くところを
import selenium
と書いて
wait = WebDriverWait(driver, 10)
と書くところを
wait = selenium.webdriver.support.ui.WebDriverWait(driver, 10)
と書くことも出来ます。
代入と配列
9行目から12行目で、変数の初期化と配列への代入をしています。
代入は「=」で、配列の初期化は「[]」ですね。ちなみに「[]」は角括弧って名前らしいです。
要素がクリック出来るようになるまで待つ
25、26行目は、「NowShowing」ってIDの要素が表示されるのが遅いので、エラーが出ちゃいました。
なので、「NowShowing」ってIDの要素がクリック出来るようになるまで待つようにしています。
インクリメントの書き方
Pythonのインクリメントは「+=」で書きます。デクリメントは「-=」です。
「list_col = list_col + 1」って書くよりは、「list_col += 1」って書いた方が、ちょっとは楽できるかもです。
「find_elements_by_css_selector」について
CSSセレクタ構文で要素を見つける時に使うのが「find_elements_by_css_selector」です。
ちなみに、似たようなシリーズ仲間に、
- find_elements_by_name
- find_elements_by_xpath
- find_elements_by_link_text
- find_elements_by_partial_link_text
- find_elements_by_tag_name
- find_elements_by_class_name
- find_elements_by_css_selector
があります。
また、ほとんど同じように、
- find_element_by_id
- find_element_by_name
- find_element_by_xpath
- find_element_by_link_text
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
- find_element_by_css_selector
があります。
「element」の所が単数形か複数形かの違いです。
今回は、複数の映画のタイトルを一括して取得する前提なので、「find_elements_by_css_selector」を使います。1つずつ取得するなら、単数形の「find_element_by_css_selector」になります。
分かり難いですけどね。
with構文について
本当は、「with」なんて使わなくても、普通にファイルをオープンして、処理して、ファイルをクローズすれば問題なんでしょうが、「Excel×Python最速仕事術」では、唐突に、こんな風に書かれています。
with open("..datasalessalesList.csv","w",encoding="utf_8_sig") as fp:
writer = csv.writer(fp, lineterminator="n")
for row in lsh.rows:
writer.writerow([col.value for col in row])
ちなみに、「Excel×Python最速仕事術」の解説では、
売上一覧の作成が終わったら、CSVの出力に進みます。まず、出力するファイルをopen(オープン)するのですが、その際にwithを指定すると、使い終わったら勝手にclose(クローズ)してくれます。
と、書かれています。
実は、この部分を自分が、すんなり理解出来なかったんですよね。
要は、withを使ってファイル処理を書いたら、いちいちopenやcloseは書かなくて良いってこと。
ちなみに、通信処理とかデータベース処理とかでも使えるようです。
ただ、withが使えるクラスであることが前提にはなります。
なので、今は、ファイル処理に便利に使えると覚えることにしました。
詳細は、ファイル処理以外でwithを使う機会があったときや、クラスを作ったりするとき等に、改めて勉強しましょうってな感じです。
最後に
今回のプログラムですが、ユナイテッド・シネマ系だったら、多分どこでも使えると思います。
プログラムの10行目の配列のメンバー、” odaiba”を加えれば「ユナイテッド・シネマアクアシティお台場」のデータが取得出来ます。
今回は、もともと自作のExcel版をPython版に変えただけで、Seleniumを使いましたが、このSeleniumは手でGoogle Chromeの動かすのを自動化しているので、ちょっと遅かったりします。
なので、次回は、Beautiful Soupを使った版を作ってみようと思っているところです。
もし、このプログラムで動かなかったり、不明な点がございましたら、ご一報頂けると幸いです。