とあるサイトの禁書目録(アクセスログ)
Post on 03-Jul-2015
696 Views
Preview:
DESCRIPTION
TRANSCRIPT
とあるサイトの禁書目録Rでアクセスログを触るというアレについて
Tsukuba.R#5@y_benjo
アクセスログ
自⼰紹介• twitter id : y_benjo
• hatena id : repose– http://d.hatena.ne.jp/repose
• Tsukuba.R履歴– やる夫で学ぶSVM with R (#2)– Rでtwitterのクラスタをあぶりだしてみた(#4)
最近• DBCLS(ライフサイエンス統合データベースセンター)で⾊々やってます
• 統合TV– DBCLSのコンテンツの⼀つ– データベースやツールの使い⽅を動画で配信
統合TV
統合TVをもっと便利に• 記事ごとのアクセスを記録してコンテン
ツに利用– アクセスの傾向を把握
• 特定のクエリ(検索ワード)が増えると「どこかでこれを必要とする課題が出たのかも…」
• A記事からB記事への遷移数を把握– 記事の推薦(レコメンド)
• これらの下準備として、今⽇はRでアクセスログを触ってみる
ログの収集• 「Web解析HACKS」を参考にページごとにスクリプトを埋め込む– 2009年5⽉22⽇~
• 取得できるのは– アクセス時刻– アクセスされたURL– ホスト名– リファラ– Cookieの値
写経したスクリプト#!/usr/bin/perl -wuse strict;my $logfile = '/var/log/benjo.log';my $cookie_name = 'Apache';
use CGI;my $cgi = new CGI;my $url = $cgi->param('url');my $ref = $cgi->param('ref');
$url =~ s!^https?://[^/]+!!;if($url && defined($ref)){
my $time = time();my $client = $cgi->remote_host();my $cookie_val = $cookie_name ? $cgi->cookie($cookie_name):"";
}else{
seek(LF,0,2);print LF "$time¥t$client¥t$url¥t$ref¥t$cookie_val¥n";close LF;}
収集したログ
• 非常にシンプル– しかしアクセスログとしては⼗分
まずはRで読む
> log <- read.csv("benjo.log",sep="¥t",header=T)> str(log)'data.frame': 6011 obs. of 5 variables:$ time : int 1242987013 1242987016 1242987019...$ ip : Factor w/ 1526 levels “**.**.**.jp",..: 293 293...
$ page : Factor w/ 400 levels "' escape(document.location) '",..: 358 358 ...
$ ref : Factor w/ 1615 levels $ cookie: logi NA NA NA NA NA NA ...
Rで触る前に下ごしらえ• ログの時刻書式はUnix timeなので変換
– 1242987013って何⽉何⽇何時何分何秒?• ホスト(IPアドレス)はカテゴリ化
– aaa.hoge.ac.jpとbbb.hoge.ac.jpを⼀つに• リファラの⽂字列がURLエンコードされたままなので変換– %E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8って何?
下ごしらえ(1) 時刻変換• 時刻を扱うdateパッケージが必要
– POSIXctクラスオブジェクトに変換(by @nozma)• POSIXltだとdata.frameで触るのがちょっと⾯倒
log$time <- sapply(log$time,function(x){return(as.POSIXct(x,origin="1970-01-01"))
})class(log$time) <- "POSIXct"
下ごしらえ(1) ホスト名変換• ホスト名をカテゴリ化
– 正規表現で– IPは上位2バイト、ホスト名は下位3つ
log$ip <- sapply(log$ip,function(x){if(length(grep("^([[:digit:]]+¥¥.){3}[[:digit:]]+$",x,value=T))!=0){
ip <- gsub("^([[:digit:]]+¥¥.[[:digit:]]+)(.+)","¥¥1",x)}else{ip <-gsub("^(.+)¥¥.(.+¥¥..+¥¥..+)$","¥¥2",x)
}return(ip)
})
下ごしらえ(3) クエリ変換• リファラのURLをデコードすればクエリ
だって楽々表⽰…– URLdecode
>URLdecode("%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8")[1] "パッケージ"
ここまでくれば• あとは好き勝⼿分析しましょう
– 本当はもう少し加⼯が必要• 統合TV内からのリファラを正規表現で切り出さな
いと別URLとして認識されてしまう……– むしろここまで下ごしらえをやるなら…
• 分析のたびに毎度やるのも⾯倒• ログを書き出すときに⼯夫するか• 定期的にスクリプトで変換する⽅がいいと思いま
す• というよりこれから僕がそうします
簡単なグラフ(1)
pie(sort(table(log$page),decreasing=T))
簡単なグラフ(2)
pie(sort(table(log$ip),decreasing=T))
分析例• 統合TV内においてユーザのページ遷移が
⼀番多いのはどのような経路かpagelist <- unique(log$page)size <- length(pegelist)logmat <- matrix(0,size,size)
for(i in 1:nrow(log)){nowpage <- log$page[i-1]now <- which(log$page[i-1]==pagelist)ref <- paste(log$ref[i-1])if(length(which(ref==pagelist))){logmat[which(ref==pagelist),now] <-logmat[which(ref==pagelist),now]+1
}}
リファラ上位5つ1724 : /269 : http://lifesciencedb.jp/242 : /?category=発現情報126 : /?category=遺伝⼦93 : /?category=ゲノム73 : /?category=パスウェイ解析
分析例• 多い順に並べると
– トップページから/20090525.html• [winxp][IE7][DBCLS] ⽣命科学系データベース
カタログを使い倒す 2009– トップページから/20090415-15.html
• [macosx][safari][タンパク質] Jpredを使ってタンパク質の⼆次構造予測をする2009
– トップページから/20090604.html• [macosx][Firefox][配列解析][アミノ酸][タンパ
ク質][遺伝⼦] InterProScanを使ってアミノ酸配列の特徴を検索する
分析例
plot(graph.adjacency(logmat>5,weighted=T),layout=layout.circle)
分析例• 簡単な考察
– ページ遷移はトップページからどこかの記事へがほとんど
– 1つのコンテンツだけ⾒て帰ってしまう– カテゴリ別で⾒てる⼈は13%程度– 記事を推薦する事によってもっと⾒て貰える
かも…?• 来週ぐらいからRubyでレコメンデーショ
ンできるようにします
分析案• 最初に書いた下ごしらえや基本的な分析
(前⽇のアクセス数)を定期的に実⾏してお知らせ– Rのバッチ処理 + cronで
• 大量に存在するパッケージの利用– 時系列に使えそうなパッケージを探しておき
ます– 外れ値検出を使ってアクセスの急な伸びを把
握したり– アクセス数予測モデルを作ったり
お疲れ様でした
top related