LoginSignup
10
14

More than 5 years have passed since last update.

QiitaにSeleniumで自動ログインして全投稿を定期的にバックアップ【Python】

Last updated at Posted at 2018-09-20

はじめに

前回の記事に続き、今回もスクレイピングのデモ記事です。
「スクレイピング・作業自動化周りでできることを増やしていきたい」
ということで、今回はSeleniumを用いた自動ログインのデモです。

Qiitaにログインし、自分の全投稿のバックアップをとるプログラムです。
バックアップって手動で取ろうとすると手間ですし、定期的に行うのは面倒。
一定間隔で自動実行してくれると便利ですよね。

※前回の記事では途中でBeautifulSoup4をかませましたが、今回はSeleniumでやり遂げます。
※同じくPhantomJSを使用しましたが、今回はChromeDriverを使います。ページの移行が可視化されて分かりやすいです。
 画面が自動で切り替わっていくの、見ていて楽しいです。

何ができるのか

以下のようなマイページを対象にスクレイピングすることで
Qiita-posts.PNG

以下のようなcsvファイルが得られます。
QiitaBackup-csv.PNG
※csvファイルをExcelで読み込んだ画面のキャプチャ

時間指定しておけば、1ヶ月に1回自動でバックアップ、などの運用も可能です。

やること

Qiitaに投稿した全記事を対象に

  • 通し番号
  • タイトル
  • URL
  • タグ
  • Qiita記法テキスト

をcsvファイルに保存します。

流れ

  1. 以下の機能を持つプログラムを作成

    1. SeleniumでQiitaにログイン
    2. マイページから投稿一覧とURLを取得
    3. 各投稿の編集ページへ移行
    4. 編集ページからQiita記法のテキストを抽出
    5. csvファイルに保存
  2. 毎月自動実行されるように設定

環境

  • Windows10 64bit
  • Python3.7
  • Selenium 3.14.0
  • chromedriver 2.42

前準備

コード

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. 以下の機能を持つプログラムを作成

  1. SeleniumでQiitaにログイン
  2. マイページから投稿一覧とURLを取得
  3. 各投稿の編集ページへ移行
  4. 編集ページからQiita記法のテキストを抽出
  5. 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仮想環境内のJupyter Notebookを一瞬で起動する方法 - Qiita

pipenvで構築した仮想環境内で実行するため、今回はbatファイルを以下のように作成します。

QiitaBackup.bat
cd C:\Users\workspace\venv
pipenv run python C:\Users\workspace\venv\QiitaBackup\QiitaBackup.py qiitaaccount@xxxxx.com qiita-password qiitaaccount
pause >nul

コマンドライン引数に

  1. ログインに使用するメールアドレス
  2. パスワード
  3. Qiitaのアカウント名

を含めて実行することで、Pythonプログラムにこれらの変数を渡します。

pause >nulを入れておくことで、実行後すぐにコマンドプロンプトが終了してしまうことを防ぎます。

2. タスクスケジューラを設定

タスクスケジューラは任意のプログラムをスケジュールを組んで実行するためのツールです。1
設定方法は以下の記事をご覧ください。

「Python3のWindows環境における手動/自動実行方法+実行形式化まとめ。 | KodoCode」

以上で完了です。

まとめ

以上により、設定したタイミングにQiitaの全投稿がバックアップされます。

バックアップって面倒ですし、忘れがちですよね。そしていつしかやらなくなる…。
しかし、このように一度自動化してしまえばあとは放置で大丈夫です。
※ローカル環境での設定のため、PCの電源が切れていた場合は実行されませんが…。

ついにログインまで自動化できるようになりました。
スクレイピングでできることが広がっていきますね。

注意点としては、ログインしてスクレイピングをしてはいけないサービスもあるということです。
利用規約やrobots.txtを確認しましょう。
Twitterとかですと公式のAPI以外から自動操作するのは規約違反なようですし。
気をつけましょう。
(Qiitaさんは特に明記されていなかったはず…。問題がありましたらご指摘ください。)

参考

コードは主に以下を参考にさせていただきました。

GitHub

ソースコードはGitHub上でも公開しています。
https://github.com/kokokocococo555/QiitaBackup-demo

課題

  • サーバ上やクラウド上で実行するシステムにすることで、ローカルのPCと切り離して運用する。
  • 他の方も使えるように、Webサービス化・LINE bot化する。
  • 大量の記事があってマイページで記事が複数ページにまたがっている場合に対応していない(自分の記事が増えたら対応させます)。

注意

Webスクレイピングでは著作権等で気をつけるべきことがあります。
以下記事を参考に、ルール・マナーを意識しておきましょう。

関連記事【スクレイピング・自動化】


  1. MacにはLaunchd、Linuxにはcronという似たようなツールが備わっているようです。 

10
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
14