LoginSignup
7
6

More than 5 years have passed since last update.

サーバー上(Ubuntu16.04)で、Webブラウザを自動実行することで、Web上の特定のデータを定点観測する(3)〜Cron自動実行編〜

Last updated at Posted at 2016-09-01

背景

リアルタイムに値の変わるデータが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)値に一定の変動があった場合メールで知らせる → おまけ編で説明

Part1Part2で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上のデータを定点観測するプログラム全容

Part1Part2と本投稿を総合して、簡単な定点観測プログラムを書いてみます。

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ページの中のデータを定点観測することができるようになります。

7
6
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
7
6