はじめに
前回の記事に続き、今回もスクレイピングのデモ記事です。
「スクレイピング・作業自動化周りでできることを増やしていきたい」
ということで、今回はSelenium
を用いた自動ログインのデモです。
Qiitaにログインし、自分の全投稿のバックアップをとるプログラムです。
バックアップって手動で取ろうとすると手間ですし、定期的に行うのは面倒。
一定間隔で自動実行してくれると便利ですよね。
※前回の記事では途中でBeautifulSoup4
をかませましたが、今回はSelenium
でやり遂げます。
※同じくPhantomJSを使用しましたが、今回はChromeDriver
を使います。ページの移行が可視化されて分かりやすいです。
画面が自動で切り替わっていくの、見ていて楽しいです。
何ができるのか
以下のようなcsvファイルが得られます。
※csvファイルをExcelで読み込んだ画面のキャプチャ
時間指定しておけば、1ヶ月に1回自動でバックアップ、などの運用も可能です。
やること
Qiitaに投稿した全記事を対象に
- 通し番号
- タイトル
- URL
- タグ
- Qiita記法テキスト
をcsvファイルに保存します。
流れ
-
以下の機能を持つプログラムを作成
- SeleniumでQiitaにログイン
- マイページから投稿一覧とURLを取得
- 各投稿の編集ページへ移行
- 編集ページからQiita記法のテキストを抽出
- csvファイルに保存
毎月自動実行されるように設定
環境
- Windows10 64bit
- Python3.7
- Selenium 3.14.0
- chromedriver 2.42
前準備
- chromedriverをダウンロードしておく。
コード
0. logのためのおまじない
参考:ログ出力のための print と import logging はやめてほしい - Qiita
from logging import getLogger, StreamHandler, DEBUG
logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(DEBUG)
logger.setLevel(DEBUG)
logger.addHandler(handler)
logger.propagate = False
1. 以下の機能を持つプログラムを作成
- SeleniumでQiitaにログイン
- マイページから投稿一覧とURLを取得
- 各投稿の編集ページへ移行
- 編集ページからQiita記法のテキストを抽出
- csvファイルに保存
import os
import sys
import time
import datetime
import csv
from selenium import webdriver # pip install selenium
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
Qiitaへのログイン情報やマイページURL用のアカウント名、ページ読み込みの待ち時間を設定します。
Qiitaのログインにはメールアドレスやパスワード等の情報が必要ですが、ソースコードにベタ打ちするのは危険です。
今回はsys.argv[1]
という形でコマンドライン引数から持ってくることにします。
QIITA_EMAIL=sys.argv[1]
QIITA_PASSWORD=sys.argv[2]
QIITA_ACCOUNT=sys.argv[3]
deray_time = 2 # 2秒
メインの処理です。
Qiitaにログインし、マイページから全投稿のURLを取ってきます。
その後、各ページの編集画面に入ってデータをバックアップします。
※編集画面に入るため、万が一もありえます。
責任は取れませんので、テスト投稿などで試してから使用してください。
def main():
"""
メイン処理
"""
# chromedriver本体のパスを指定
chr_path = r"C:\chromedriver-2.42\chromedriver.exe"
driver = webdriver.Chrome(executable_path=chr_path)
# Qiitaにログインする
login_qiita(driver)
time.sleep(deray_time)
print('login')
# マイページに移行
mypage_url = 'https://qiita.com/' + QIITA_ACCOUNT
driver.get(mypage_url)
time.sleep(deray_time)
print('move to ', mypage_url, ' ...')
# 投稿済みの記事のリストを取得
posts = driver.find_elements_by_css_selector('article.ItemLink')
num_posts = len(posts)
# 投稿済みの記事のURLリストを取得
post_urls = []
for post in posts:
post_urls.append(post.find_element_by_css_selector('.ItemLink__title a').get_attribute('href'))
post_data_list = []
for i in range(num_posts):
no = num_posts - i
# 各投稿のURLを取得
post_url = post_urls[i]
post_data = get_post_content(driver, post_url)
# 話数的な数字をゼロパディングで作成
post_no = str(no).zfill(4)
post_data['no'] = post_no
post_data_list.append(post_data)
print('[{}]{} data is appended ...'.format(post_no, post_url))
save_as_csv(post_data_list)
print('backup finish!')
1.1. Qiitaにログイン
Qiitaのログインフォームにメールアドレスとパスワードを入力し、ログインボタンをクリックします。
Seleniumが全部自動でやってくれます。見ていて楽しいです。
def login_qiita(driver):
"""
Qiitaにログイン
"""
# Qiitaログイン画面を開く
driver.get('https://qiita.com/login')
time.sleep(deray_time)
# Qiitaにログイン
login_email = driver.find_element_by_id('identity')
login_email.send_keys(QIITA_EMAIL)
login_password = driver.find_element_by_id('password')
login_password.send_keys(QIITA_PASSWORD)
login_button = driver.find_element_by_name('commit')
login_button.click()
1.2. 編集ページからQiita記法のテキストを抽出
記事の編集ページに入り、タイトル、タグ、Qiita記法でマークダウンされたテキストを取得します。
def get_post_content(driver, post_url):
"""
投稿記事コンテンツを取得
"""
# 各投稿の編集ページへ移行
driver.get(post_url)
time.sleep(deray_time)
# 編集ページからQiita記法のテキストを抽出
# 投稿ページ内の編集へのリンクを取得
edit_url = driver.find_element_by_css_selector('.it-Header_edit a').get_attribute('href')
# 編集ページへ移行
driver.get(edit_url)
time.sleep(deray_time)
# 投稿記事コンテンツを取得
post_data = {
# Qiita記法のテキストを取得
'text': driver.find_element_by_css_selector('textarea.editorMarkdown_textarea').text,
# タイトル
'title': driver.find_element_by_css_selector('div.editorTitle input').get_attribute('value'),
# tag
'tags': driver.find_element_by_css_selector('div.editorTag input').get_attribute('value'),
'url': post_url,
}
return post_data
1.3. csvファイルに保存
編集ページから抜き出したデータをcsvファイルに保存します。
ファイル名には日時を入れておきます。
def save_as_csv(post_data_list):
"""
csvファイルにデータを保存
"""
# バックアップファイルの保存先の指定
directory_name = 'backup'
# ディレクトリが存在しなければ作成する
if not os.path.exists(directory_name):
os.makedirs(directory_name)
# バックアップファイル名の作成
today = datetime.datetime.now().strftime('%Y-%m-%d_%Hh%Mm')
csv_name = os.path.join(directory_name, 'Qiita-backup[{}].csv'.format(today))
# 列名(1行目)を作成
col_name = ['no', 'title', 'url', 'tags', 'text']
with open(csv_name, 'w', newline='', encoding='utf-8') as output_csv:
csv_writer = csv.writer(output_csv)
csv_writer.writerow(col_name) # 列名を記入
# csvに1行ずつ書き込み
for post in post_data_list:
row_items = [post['no'], post['title'], post['url'], post['tags'], post['text']]
csv_writer.writerow(row_items)
print(csv_name, ' saved...')
実行用
if __name__ == '__main__':
main()
毎月自動実行されるように設定
毎月自動で実行するための設定が必要です。
ここでは、ローカル環境で実行することとし、batファイルとタスクスケジューラを使用します。
1. batファイルを作成
batファイルとは、簡単にいうと
「コマンドプロンプトで実行するコマンドを羅列したファイル」
です。
ダブルクリックでそれぞれのコマンドを順番に実行できます。
メモ帳などのテキストエディタでコマンドを書き、拡張子を「.bat」で保存すれば完成です。
pipenvで構築した仮想環境内で実行するため、今回はbatファイルを以下のように作成します。
cd C:\Users\workspace\venv
pipenv run python C:\Users\workspace\venv\QiitaBackup\QiitaBackup.py qiitaaccount@xxxxx.com qiita-password qiitaaccount
pause >nul
コマンドライン引数に
- ログインに使用するメールアドレス
- パスワード
- Qiitaのアカウント名
を含めて実行することで、Pythonプログラムにこれらの変数を渡します。
※pause >nul
を入れておくことで、実行後すぐにコマンドプロンプトが終了してしまうことを防ぎます。
2. タスクスケジューラを設定
タスクスケジューラは任意のプログラムをスケジュールを組んで実行するためのツールです。1
設定方法は以下の記事をご覧ください。
「Python3のWindows環境における手動/自動実行方法+実行形式化まとめ。 | KodoCode」
以上で完了です。
まとめ
以上により、設定したタイミングにQiitaの全投稿がバックアップされます。
バックアップって面倒ですし、忘れがちですよね。そしていつしかやらなくなる…。
しかし、このように一度自動化してしまえばあとは放置で大丈夫です。
※ローカル環境での設定のため、PCの電源が切れていた場合は実行されませんが…。
ついにログインまで自動化できるようになりました。
スクレイピングでできることが広がっていきますね。
注意点としては、ログインしてスクレイピングをしてはいけないサービスもあるということです。
利用規約やrobots.txtを確認しましょう。
Twitterとかですと公式のAPI以外から自動操作するのは規約違反なようですし。
気をつけましょう。
(Qiitaさんは特に明記されていなかったはず…。問題がありましたらご指摘ください。)
参考
コードは主に以下を参考にさせていただきました。
- 『Pythonクローリング&スクレイピング―データ収集・解析のための実践開発ガイド―』技術評論社
- 『退屈なことはPythonにやらせよう――ノンプログラマーにもできる自動化処理プログラミング』O'Reilly Japan
- たった3行のpythonで始めるSelenium入門 - Qiita
- 【Python】 実践 Selenium 【前編】 - Qiita
- 7. WebDriver API — Selenium Python Bindings 2 ドキュメント など。
GitHub
ソースコードはGitHub上でも公開しています。
https://github.com/kokokocococo555/QiitaBackup-demo
課題
- サーバ上やクラウド上で実行するシステムにすることで、ローカルのPCと切り離して運用する。
- 他の方も使えるように、Webサービス化・LINE bot化する。
- 大量の記事があってマイページで記事が複数ページにまたがっている場合に対応していない(自分の記事が増えたら対応させます)。
注意
Webスクレイピングでは著作権等で気をつけるべきことがあります。
以下記事を参考に、ルール・マナーを意識しておきましょう。
関連記事【スクレイピング・自動化】
-
基本的なスクレイピング(
BeautifulSoup4
) -
APIを利用したスクレイピング・データベースへの保存(
MongoDB
)・データ分析の一歩(pandas
) -
JavaScriptを用いたサイトのスクレイピング(
Selenium
,PhantomJS
) -
メール通知(
smtplib
)・定期的なプログラムの自動実行(タスクスケジューラ
) -
自動ログイン(
Selenium
,ChromeDriver
)
-
MacにはLaunchd、Linuxにはcronという似たようなツールが備わっているようです。 ↩