質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

222閲覧

複数行あるlogファイルの内容から、ある一定のパラメータに属する引数が、「○○」の行のタイムスタンプのみを抽出したい

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/10/17 05:03

以下複数行あるlogファイルの内容から、python3を使用して、ある一定のパラメータに属する引数が、「○○」の行のタイムスタンプのみを抽出したいのですが、こちらどのような方法があるか教えて頂けないでしょうか。

2018-10-15 05:41:52+0000 10_90_27_126 pycre5 on0000 9900008015918 INFO: redirect: redirect.jsp?prod=KRGJxxxx&prod=PRGJYW0052&num=9&cust=22 2018-10-15 06:41:52+0000 10_90_27_126 pycre5 on0000 9900008015918 INFO: redirect: redirect.jsp?prod=KRGJxxxx&prod=PRGJYW0052&num=9&cust=11 2018-10-15 07:01:52+0000 10_90_27_126 pycre5 on0000 9900008015918 INFO: redirect: redirect.jsp?prod=KRGJxxxx&prod=PRGJYW0052&num=9&cust=22 ・・・ ・・・ ・・・ ・・・

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun68ykt

2018/10/17 05:32

ご質問の主旨を確認させてください。”ある一定のパラメータに属する引数が、「○○」の行” とは、たとえば、 「cust=22の行」あるいは「prod=KRGJxxxxの行」といったように、行の末尾にある URLの一部と思われる文字列のクエリパラメータの値が、何らか指定の値である○○に該当する行と解釈してよいでしょうか?
退会済みユーザー

退会済みユーザー

2018/10/17 06:04

はい、そうです。宜しくお願い致します。
jun68ykt

2018/10/17 06:14

ご返信ありがとうございます。すみませんが、もう1点だけ確認ですが、 「python3を使用して」というのは必須なのでしょうか? というのは、ぱっと見、よく使うシェルコマンドの組み合わせ(grep、 egrep , cut , awk など)でいけるのでは? と思いましたので。pythonでコード書かなくてもシェルスクリプトだけでいければそれも回答としてOKでしょうか?
退会済みユーザー

退会済みユーザー

2018/10/17 06:18

すみません。こちらpython3を使用しての記述方法を知りたいです。
jun68ykt

2018/10/17 06:22

ご返信ありがとうございます。了解しました。
jun68ykt

2018/10/17 06:56

URLのクエリパラメータのパースを自作せずに、そのためのパッケージを使うtiitoi さんのご回答がスマートだと思いました。
退会済みユーザー

退会済みユーザー

2018/10/17 07:04

以下の場合、list index out of rangeエラーが出た場合は、if文などで対応する必要があるのでしょうか。
guest

回答2

0

ベストアンサー

まずログの各行を解析してあげましょう。

クエリの解析は以下の手順でできます。

  1. parsed_url = parse.urlparse(url_txt) で URL の解析
  2. parse.parse_qs(parsed_url.query) でクエリ部分の解析

python

1from datetime import datetime as dt 2from urllib import parse 3 4# ファイルを読み込む。 5with open('log.txt', newline='') as f: 6 log = f.read().splitlines() 7print(log) 8 9# ログを整形する。 10def sanitize(line): 11 cols = line.split() 12 # 日付部分を datetime にする。 13 datetime_txt = ' '.join(cols[:2]) 14 datetime = dt.strptime(datetime_txt, '%Y-%m-%d %H:%M:%S%z') 15 # URL部分を解析する。 16 url_txt = cols[8] 17 parsed_url = parse.urlparse(url_txt) 18 params = parse.parse_qs(parsed_url.query) 19 20 return {'datetime': datetime, 'params': params} 21 22parsed_log = [sanitize(l) for l in log] 23from pprint import pprint 24pprint(parsed_log)
[{'datetime': datetime.datetime(2018, 10, 15, 5, 41, 52, tzinfo=datetime.timezone.utc), 'params': {'cust': ['22'], 'num': ['9'], 'prod': ['KRGJxxxx', 'PRGJYW0052']}}, {'datetime': datetime.datetime(2018, 10, 15, 6, 41, 52, tzinfo=datetime.timezone.utc), 'params': {'cust': ['11'], 'num': ['9'], 'prod': ['KRGJxxxx', 'PRGJYW0052']}}, {'datetime': datetime.datetime(2018, 10, 15, 7, 1, 52, tzinfo=datetime.timezone.utc), 'params': {'cust': ['22'], 'num': ['9'], 'prod': ['KRGJxxxx', 'PRGJYW0052']}}]

あとは、指定した引数が存在し、かつそれがある値である要素だけ抜き出せばよいです。

python

1for l in parsed_log: 2 # パラメータ 'cust' が存在し、かつその値が 11 の場合 3 if 'cust' in l['params'] and l['params']['cust'] == ['11']: 4 print(l['datetime'])
2018-10-15 06:41:52+00:00

投稿2018/10/17 06:16

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/10/17 07:52

こちら解決しました。有難うございました。
退会済みユーザー

退会済みユーザー

2018/10/17 09:32

すみません。もう1つだけ教えてほしのですが、こちら以下は8列目にurlがある前提だと思いますが、9列目、10列目にもある行がある場合は、どのような記載をすればよろしいでしょうか。 何度も申し訳ございませんが、宜しくお願い致します。
退会済みユーザー

退会済みユーザー

2018/10/17 09:32

url_txt = cols[8]
tiitoi

2018/10/17 09:40 編集

9列目、10列目にもなんらかの値が入っているということでしょうか? 上のサンプルコードでは動きませんか? line.split() で各行をスペースで分割しているので、cols のインデックスを調整すればなんとかならないでしょうか?
退会済みユーザー

退会済みユーザー

2018/10/17 10:52

解決できました。 ご丁寧にありがとうございます。
guest

0

とりあえずpandas を使うとよいのではないでしょうかね。

https://pandas.pydata.org/

以下は超適当なサンプル

Python

1import pandas as pd 2# LOGデータを読み込む 3# - File名は 'log.txt' 4# - Header行なし 5# - 区切文字 ' ' によって列を別ける(区切文字の後のスペースは無視) 6# - 0列目と1列目はまとめてDatetime型のデータとして扱う 7df = pd.read_csv('log.txt', header=None, sep=' ', skipinitialspace=True, parse_dates=[[0,1],]) 8 9# カラム名を設定(datetime以外は適当) 10df.columns = ['datetime', 'A','B','C','D','E','F','G'] 11 12# とりあえずデータを表示 13print(df) 14 15# 'A' 列のデータが '10_90_24_126' の行の 'datetime' 列 を表示 16print(df.loc[df['A'] == '10_90_27_126', 'datetime']) 17#0 2018-10-15 05:41:52 18#1 2018-10-15 06:41:52 19#2 2018-10-15 07:01:52

投稿2018/10/17 05:52

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問