背景
リアルタイムに値の変わるデータがWEB上にありました。その値を定期的にチェックするプログラムを作ることになったわけですが、ページにログインする必要があったりと、スクレイピングのコードを書くのが面倒でした。その対策としてseleniumを使ってWebブラウザを操作し、スクレイピングをすることにしました。その過程を備忘録的にまとめていきます。
なお、手元のPCを使い、Webブラウザをバッチ処理で自動実行しても良かったのですが、、、普段使いの自身のPC上で、勝手にWebブラウザが立ち上げるのは邪魔だったので、レンタルサーバ上(Ubuntu16.04)で勝手に動かすようにします。
より具体的には以下のイメージになります。
(1)python経由でWebブラウザを立ち上げる → Part1で説明
(2)seleniumでWebブラウザを操作し、WEBデータを処理する → Part2で説明
(3)処理したデータをmongoDBに格納する → Part3(本投稿)で説明
(4)(1)〜(3)を実行するpyプログラムをcronで自動実行する → Part3(本投稿)で説明
(5)値に一定の変動があった場合メールで知らせる → おまけ編で説明
Part1とPart2でWeb上の特定のデータを自動取得するプログラムはできているので、後はそのプログラムをCRONで自動実行する設定をします。
環境
OS : Ubuntu16.04(さくらVPS)
python : version 3.5
mongoDB : version 2.6.10
PhantomJS : version 2.1.1
Step1) CRONの設定を行う
# cronの動作確認
sudo service cron status
# cronの設定ファイルを編集
crontab -e
crontabには以下のように記述
*/5 * * * * <path_to_python>/python3 /<path_to_file/test.py >> /<path_to_log>/test.log 2>>&1
上記のようにPart1,Part2で作ったpythonプログラムをジョブに指定してあげれば、5分置きにブラウザが勝手に立ち上がり、特定のサイトの特定のデータを取ってきてくれます。
Step2) 取ってきたデータをDBに保存する準備
ここからはおまけです。初期設定のUbuntuでこの定点観測プログラムを作ったので、ついでなのでDB格納のメモもしておきましょう。
txtファイルへの出力で良い場合は、書くまでもないですが、
f = open( "test.txt", "a+" )
f.write( data )
f.close
で良いでしょう。
私は実際にはMongoDBで格納しています。
MongoDBのインストール
以下の手順でインストールします。
1) 公開鍵の設定
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
2) mongodb.listの作成
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
3) 実際にインストールする
sudo apt-get update
#sudo apt-get install mongodb-10gen
4) mongod.serviceの作成
sudo vim /lib/systemd/system/mongod.service
▼mongod.serviceの中身
[Unit]
Description=MongoDB Database Service
Wants=network.target
After=network.target
[Service]
ExecStart=/usr/bin/mongod --config /etc/mongod.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
User=mongodb
Group=mongodb
StandardOutput=syslog
StandardError=syslog
[Install]
WantedBy=multi-user.target
(参考URL) http://qiita.com/pelican/items/bb9b5290bb73acedc282
pymongoのインストール
pythonからMongoDBを操作するpymongoパッケージをインストールする
pip3 install pymongo
MongoDBの起動
sudo systemctl start mongod
Step3) ブラウザの自動実行により、WEB上のデータを定点観測するプログラム全容
Part1とPart2と本投稿を総合して、簡単な定点観測プログラムを書いてみます。
Part2と同様、実際に私が観測しているデータは公開できないため、今回もQiitaのトップのフィード内にある投稿を自動取得するプログラムを書いてみましょう。
プログラムの中身を整理するとこうなります。
(1)ブラウザPhantomJSを立ち上げる
(2)Qiitaに自動的にログインをしてフィードの上から20個の投稿名を自動取得します。
(3)(2)で得た投稿名をリストに格納し、MongoDBに出力します。
実際のプログラムコードは以下のようになります。
import time
import datetime
from selenium import webdriver
from bs4 import BeautifulSoup
URL = "https://qiita.com/"
USERID = "<YOUR_USER_ID>"
PASS = "<YOUR_PASSWORD>"
#PhantomJSの自動起動とQiitaへのアクセス
browser = webdriver.PhantomJS(executable_path='<path/to/phantomjs>')
browser.get(URL)
time.sleep(3)
#ログインページ
browser.find_element_by_id("identity").send_keys(USERID)
browser.find_element_by_id("password").send_keys(PASS)
browser.find_element_by_xpath('//input[@name="commit"]').click()
time.sleep(5)
#ホーム画面の投稿一覧の取得
html = browser.page_source.encode('utf-8')
soup = BeautifulSoup(html, "lxml")
posts_source = soup.select(".item-box-title > h1 > a")
#投稿名のデータ整理
posts = []
for i in (0,len(posts_source)):
posts[i] = post.text.strip()
#定点観測の時刻を取得
output = {}
output["date"] = str(datetime.date.today())
output["datetime"] = str(datetime.datetime.today().strftime("%H:%M:%S"))
output["content"] = posts
#MongoDBへ格納
mongo = MongoClient('localhost:27017')
db = mongo_client["qiita"]
new_posts = db_connect["new_posts"]
new_posts.insert(output)
#ブラウザを閉じる
browser.close()
こんな感じです。このプログラムをcronで定期実行することで、Qiitaのログイン後のフィードから最新の投稿名を20件記録します。(投稿用のテストプログラムのため実用性はないかと思います^^;)
このプログラムを応用すれば、GET/POSTの有無に関わらず、様々なWEBページの中のデータを定点観測することができるようになります。