#**********************************************************#
#
# ロリポップのアクセスログ解析クラス
#
# 【2006/1/31 更新】
#
#**********************************************************#
class LolipopAccessLog
# 各ログ項目のソート用配列格納後のインデックス
IDX_IP = 0
IDX_DATE = 1
IDX_CMD = 2
IDX_RETCODE = 3
IDX_SIZE = 4
IDX_REFERER = 5
IDX_AGENT = 6
CNT_INVALID_FLD = 2 # IP fieldの後ろにある無効なfieldの数
CNT_EXTRA_FLD = 1 # Shellwords.shellwords()でDATE fieldが
# 2つに分割されるためにずれるインデックス数
# 検索エンジン種
SE_GGL = 0
SE_YAH = 1
SE_MSN = 2
# 検索エンジンリファラ識別用
SE_URL_YAH_1 = /http:\/\/search\.yahoo\.co\.jp\/search\?/
SE_URL_YAH_2 = /http:\/\/search\.yahoo\.co\.jp\/bin\/search\?/
SE_URL_YAH_3 = /http:\/\/cache\.yahoofs\.jp\/search\/cache\?/
SE_URL_MSN_1 = /http:\/\/search\.msn\.co\.jp\/results\.aspx\?/
SE_URL_MSN_2 = /http:\/\/search\.msn\.co\.jp\/spresults\.aspx\?/
SE_URL_MSN_3 = /http:\/\/search\.msn\.co\.jp\/previewx\.aspx\?/
SE_URL_GGL_1 = /http:\/\/www\.google\.co\.jp\/search\?/
SE_URL_GGL_2 = /http:\/\/www\.google\.com\/search\?/
GGL_IP_1 = 'http://216.239.'
GGL_IP_2 = 'http://66.102.'
GGL_IP_3 = 'http://64.233.'
GGL_IP_4 = 'http://66.249.'
GGL_IP_5 = 'http://72.14.'
GGL_SFX = '/search?'
# 検索語句入力文字コード種
IE_SJIS_1 = 'sjis'
IE_SJIS_2 = 'shift-jis'
IE_EUC = 'euc'
IE_UTF8 = 'utf-8'
# ログ読み込み
def initialize(logdata)
@records = Array.new
logdata.each do |line|
items = Shellwords.shellwords(line) # 1件分を分割し
record = Array.new
record << items[IDX_IP] # 項目ごとに配列に格納
record << items[ IDX_DATE + CNT_INVALID_FLD ] +
' ' + items[ IDX_DATE + CNT_INVALID_FLD + CNT_EXTRA_FLD ]
record << items[ IDX_CMD + CNT_INVALID_FLD + CNT_EXTRA_FLD ]
record << items[ IDX_RETCODE + CNT_INVALID_FLD + CNT_EXTRA_FLD ]
record << items[ IDX_SIZE + CNT_INVALID_FLD + CNT_EXTRA_FLD ]
record << items[ IDX_REFERER + CNT_INVALID_FLD + CNT_EXTRA_FLD ]
record << items[ IDX_AGENT + CNT_INVALID_FLD + CNT_EXTRA_FLD ]
@records << record # それをさらに配列に
end
# 検索エンジンのリファラを含むレコードを抽出 #
@records_yah = Array.new
@records_msn = Array.new
@records_ggl = Array.new
@records.each do |record|
if (record[IDX_REFERER] =~ SE_URL_YAH_1)==0 then @records_yah << record
elsif (record[IDX_REFERER] =~ SE_URL_YAH_2)==0 then @records_yah << record
elsif (record[IDX_REFERER] =~ SE_URL_YAH_3)==0 then @records_yah << record
elsif (record[IDX_REFERER] =~ SE_URL_MSN_1)==0 then @records_msn << record
elsif (record[IDX_REFERER] =~ SE_URL_MSN_2)==0 then @records_msn << record
elsif (record[IDX_REFERER] =~ SE_URL_MSN_3)==0 then @records_msn << record
elsif (record[IDX_REFERER] =~ SE_URL_GGL_1)==0 then @records_ggl << record
elsif (record[IDX_REFERER] =~ SE_URL_GGL_2)==0 then @records_ggl << record
elsif record[IDX_REFERER] =~ /^#{GGL_IP_1}[0-9]+\.[0-9]+#{GGL_SFX}/
@records_ggl << record
elsif record[IDX_REFERER] =~ /^#{GGL_IP_2}[0-9]+\.[0-9]+#{GGL_SFX}/
@records_ggl << record
elsif record[IDX_REFERER] =~ /^#{GGL_IP_3}[0-9]+\.[0-9]+#{GGL_SFX}/
@records_ggl << record
elsif record[IDX_REFERER] =~ /^#{GGL_IP_4}[0-9]+\.[0-9]+#{GGL_SFX}/
@records_ggl << record
elsif record[IDX_REFERER] =~ /^#{GGL_IP_5}[0-9]+\.[0-9]+#{GGL_SFX}/
@records_ggl << record
end
end
end
# ユニークホスト数
def count_uniqhost
ips = Array.new
@records.each do |record|
ips << record[IDX_IP] # IPアドレスのみ配列に抽出
end
ips.uniq.length
end
# 検索エンジンからの総アクセス数
def count_access_from_se(se)
if se == SE_GGL then @records_ggl.length
elsif se == SE_YAH then @records_yah.length
elsif se == SE_MSN then @records_msn.length
else return(0)
end
end
# 検索エンジンからのユニークホスト数
def count_uniqhost_from_se(se)
if se == SE_GGL then records = @records_ggl
elsif se == SE_YAH then records = @records_yah
elsif se == SE_MSN then records = @records_msn
else return(0)
end
ips = Array.new
records.each do |record|
ips << record[IDX_IP] # IPアドレスのみ配列に抽出
end
ips.uniq.length
end
# レコードごとのリクエストファイル名と検索語句を抽出
def get_files_and_searchwords(se)
if se == SE_GGL
records = @records_ggl
qname = 'q' # 「検索語句」パラメータ名
iename = 'ie' # 「検索語句入力文字コード」パラメータ名
elsif se == SE_YAH
records = @records_yah
qname = 'p'
iename = 'ei'
elsif se == SE_MSN
records = @records_msn
qname = 'q'
iename = ''
else
return(nil)
end
files_and_searchwords = Array.new
records.each do |record|
file_and_words = Array.new # ひと組のリクエストファイル名と検索語句
# リクエストファイル名を取得
file_and_words << (record[IDX_CMD].split)[1]
# 検索語句を切り出し
ref = record[IDX_REFERER]# + '&'
q = ref.scan(/#{qname}=[^&]+/) # "(「検索語句」パラメータ名)="から"&"の前までを切り取り
if q[0] == nil # 見つからなければそのレコードは無視
next
else
q[0].sub!(/^#{qname}=/,'') # "(「検索語句」パラメータ名)="切り落とし
words = q[0]
end
# 検索語句入力文字コードを取得
enc = ''
if iename != ''
ie = ref.scan(/#{iename}=[^&]+/) # "(「検索語句入力文字コード」パラメータ名)="から"&"の前までを切り取り
if ie[0] != nil
ie[0].sub!(/^#{iename}=/,'') # "(「検索語句入力文字コード」パラメータ名)="切り落とし
enc = ie[0].downcase
end
end
# 検索語句をURLデコード
words = CGI.unescape(words)
# 検索語句文字コードをsjisに
if (enc =~ /#{IE_SJIS_1}/) || (enc =~ /#{IE_SJIS_2}/) # 検索語句入力文字コードがsjis
elsif enc =~ /#{IE_EUC}/
words = words.kconv(Kconv::SJIS,Kconv::EUC)
elsif enc =~ /#{IE_UTF8}/
words = words.kconv(Kconv::SJIS,Kconv::UTF8)
else # 指定なしまたは不明
words = words.kconv(Kconv::SJIS,Kconv::AUTO)
end
file_and_words << words
files_and_searchwords << file_and_words
end
files_and_searchwords
end
end
|