ちょっと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]なんです。
おもしろい!
ご指摘や改善点ありましたらどんどんコメントください
コメント