ちょっとPythonを使うことがあったのでメモ。
なかなかクソなwebアプリからログを取りたいのだがcsv出力の機能がなかったのでスクレイピングで拾ってきました。
存在以上のページを指定すると404が出るわけではないので(文字化けしてページが永遠に作成される)、どこかに書いてある最大ログ数を取って来てループを回しています。(次へが押せなくなるとかもない)
HTMLタグにidとかclassがついていれば”Beautiful Soup”というモジュールを使えば10行くらいで完成するのですが、一つもタグになかったのでXPathを使って指定しています。
また、ブラウザでXPathをコピーするとTBodyタグが抽出出来たのですが実際のソースには無かったみたで、めちゃくちゃハマりました。(ブラウザが補完している模様)
正規表現を使うためだけに”re”をimportしたり、モジュールを使いまくる感じでした。
初めてPythonを触ったのでぐちゃぐちゃなコードですが。。。
import requests
import lxml.html
import re
from time import sleep
from datetime import datetime,timedelta
import os
# クラス宣言の時には引数にobjectが入るのがトレンド
class Logger(object):
''' クラス変数で使うならこっち
counter = 0
end = ''
flag = True
done = False
# w:上書き r:追記
filePath = "XXXX.txt"
'''
# インスタンス変数
def __init__(self,counter,end,flag,done,filePath):
self.counter = counter
self.end = end
self.flag = flag
self.done = done
self.filePath = filePath
# 自作関数の宣言時引数にselfが必要
def putLog(self):
# withで自動でストリーム閉じる(C#でいうusing)
with open(self.filePath, 'a') as file:
while self.flag:
# format関数を使って文字列の{}に値を埋め込む
uri = 'http://XXXX/log_page&page={}'.format(self.counter)
# Basic認証対策
res = requests.get(uri,auth=('userID','Password'))
# アクセス出来た時のみ
if res.status_code == 200:
html = res.text
root = lxml.html.fromstring(html)
# XPathでピンポイントで取得する
targets = root.xpath("/html/body/font/table/tr[5]/td/table/tbody/tr")
if self.counter == 0:
# 1ページ目でMaxレコードの数字拾う
fin = root.xpath("/html/body/font/table/tr[5]/td/table/tbody/tr[24]/td[1]")
s = str(fin[0].text_content())
self.end = re.search(r'([0-9]+)',s).group()
# 1ページのログをひたすらスクレイピング
for c in range(2,len(targets) - 3 ):
day = root.xpath("/html/body/font/table/tr[5]/td/table/tbody/tr[{}]/td[4]".format(c + 1))[0].text_content()
time = root.xpath("/html/body/font/table/tr[5]/td/table/tbody/tr[{}]/td[5]".format(c + 1))[0].text_content()
userid = root.xpath("/html/body/font/table/tr[5]/td/table/tbody/tr[{}]/td[2]".format(c + 1))[0].text_content()
name = root.xpath("/html/body/font/table/tr[5]/td/table/tbody/tr[{}]/td[3]".format(c + 1))[0].text_content()
# 謎にmm/dd/YYYY形式なので変換
dayTime = day[6:10] + '/' + day[0:5] + ' ' + time
baseDay = day[6:10] + '/' + day[0:5]
# 日付型で比較するとき用
#dt = datetime.strptime(baseDay, '%Y/%m/%d')
# 取って来た日の前日を取得
yesterday = datetime.today() - timedelta(days=1)
yesterday = datetime.strftime(yesterday, '%Y/%m/%d')
# 取って来た日付が昨日なら書く
if baseDay == yesterday:
file.write(dayTime + ' ' + userid + ' ' + name + '\n')
if str(targets[c].text_content()).find(self.end) != -1:
self.flag = False
break
elif baseDay < yesterday:
# 昨日分を書き終わり一昨日になったら処理終了
self.flag = False
break
else:
break
if self.flag:
self.counter += 1
sleep(1)
else:
break
# インスタンス化
log = Logger(0, '', True, False, "XXXXX.txt")
# オブジェクトの関数使用
log.putLog()おまけ
コマンドライン引数の使い方
import sys # コマンドライン引数取得(0番目にはこのpyファイルのパスが入っている) args = sys.argv
実行する時にファイル名の後ろに文字列をいれますが、Pythonでは0番目にファイル名が自動で入ります。
なので文字列の最初はargs[1]なんです。
おもしろい!
ご指摘や改善点ありましたらどんどんコメントください


コメント