Как извлечь внешние ссылки из журнала доступа Apache с помощью Perl? - PullRequest
1 голос
/ 14 января 2009

Мне нужна помощь в получении регулярного выражения для работы со всеми реферерами из файла журнала доступа apache, который исходит от реальных ссылок вне сайта и которые являются действительными рефералами от реальных людей, а не ботов или пауков. Я работаю в Perl.

Этот бит кода почти уже работает [журнал доступа открывается с помощью дескриптора файла $ fh]:

my $totalreferals = 0;
while ( my $line = <$fh> ) {
    if ($line !~ m!

        \[\d{2}/\w{3}/\d{4}(?::\d\d){3}.+?\]
        \s"GET\s\S+\sHTTP/\d.\d"
        \s\S+
        \s\S+
        \s("-"|"http://(www\.|)mywebsite\.com.*"                

        !xi
        )
    {
          $totalreferals++;  
    }

    $line =~ m!

        \[(\d{2}/\w{3}/\d{4})(?::\d\d){3}.+?\]
        \s"GET\s(\S+)\sHTTP/\d.\d"
        \s(\S+)
        \s\S+
        \s"http://w{1,3}\.google\.
        (?:[a-z]{2}|com?\.[a-z]{2}|com)\.?/
        [^\"]*q=([^\"&]+)[^\"]*"

    !xi or next;

    my ( $datestr, $path, $status, $query ) = ( $1, $2, $3, $4 );
    .
    .
    #do other stuff  
    .
    .
}

Вышеупомянутое регулярное выражение успешно удаляет все внутренние ссылки, записанные в записях access_log плюс, которые не имеют реферера, но дает $ totalreferals, которое в противном случае слишком велико.

Примеры log $ line, которые подсчитываются по 1-му регулярному выражению, но которые я хочу исключить:

61.247.221.45 - - [02/Jan/2009:20:51:41 -0600] "GET /oil-paintings/section.php/2451/0 HTTP/1.1" 200 85856 "-" "Yeti/1.0 (NHN Corp.; http://help.naver.com/robots/)"

- Кажется, паук из Кореи


93.84.41.131 - - [31/Dec/2008:02:36:54 -0600] "GET /paintings/artists/w/Waterhouse_John_William/oil-big/Waterhouse_Destiny.jpg HTTP/1.1" 200 19924 "http://smrus.web-box.ru/Schemes" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5"

- Запрос на изображение, встроенное в другой веб-сайт (мы разрешаем это)


87.115.8.230 - - [31/Dec/2008:03:08:17 -0600] "GET /paintings/artists/recently-added/july2008/big/Crucifixion-of-St-Peter-xx-Guido-Reni.JPG HTTP/1.1" 200 37348 "http://images.google.co.uk/im........DN&frame=small" "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5" 

- запрос от изображений Google (может быть просмотр изображения в полном размере или его показ)


216.145.5.42 - - [31/Dec/2008:02:21:49 -0600] "GET / HTTP/1.1" 200 53508 "http://whois.domaintools.com/mywebsite.com" "SurveyBot/2.3 (Whois Source)" 

- Запрос от бота whois


Ответы [ 5 ]

3 голосов
/ 14 января 2009

Если у вас нет действительно странного требования изобретать велосипед,

http://search.cpan.org/search?query=apache+log&mode=all

1 голос
/ 14 января 2009

Предложение Манни исключить POST и HEAD действительно было правильным, потому что я искал отрицательные совпадения (поэтому не должен ограничиваться GET, как при разборе строк запроса). Аналогично с ошибкой в ​​точке перед хостом без www, а также с необходимостью устранения "-" (без реферера)

Кроме того, я исключил все совпадения с файлами изображений, которые чаще всего не являются прямыми рефералами с внешних сайтов, но встроены в эти сайты или индексируются поисковой системой (в основном Google Images).

Я также обнаружил, что многие файлы изображений сервера содержат пробелы в именах файлов, что нарушает регулярное выражение, где \ S + использовалось для имени файла, я изменил это на. +

Наконец, поскольку мне не нужно было опровергать дату при удалении записей, я мог упростить первую часть регулярного выражения.

Результат намного ближе к ожидаемым цифрам. Хотя мне еще предстоит найти хороший способ устранить все запросов от ботов и пауков.

Для тех, кто заинтересован, финальный код выглядит следующим образом:

my $totalreferals = 0;
while ( my $line = <$fh> ) {
    if ($line !~ m!

        \[.+\]
        \s("\S+\s.+\sHTTP/\d.\d"
        \s\S+
        \s\S+
        \s("-"|"http://(www\.|)mywebsite\.com.*")|
        "\S+\s.+\.(jpg|jpeg|gif|png)\sHTTP/\d.\d"
        \s\S+
        \s\S+
        \s".*")
        !xi
        )
    {   
      $totalreferals++;  
    }

    $line =~ m!

        \[(\d{2}/\w{3}/\d{4})(?::\d\d){3}.+?\]
        \s"GET\s(\S+)\sHTTP/\d.\d"
        \s(\S+)
        \s\S+
        \s"http://w{1,3}\.google\.
        (?:[a-z]{2}|com?\.[a-z]{2}|com)\.?/
        [^\"]*q=([^\"&]+)[^\"]*"

    !xi or next;

    my ( $datestr, $path, $status, $query ) = ( $1, $2, $3, $4 );
    .
    .
    #do other stuff  
    .
    .
}

Редактировать : В ходе моего исследования кажется, что единственный действительно жизнеспособный способ отличить автоматических сканеров от реальных посетителей - это отслеживание файлов cookie. Я сомневаюсь, что есть способ объяснить это с помощью чистого анализа журнала. Если кто-нибудь знает способ сделать это путем анализа журналов, пожалуйста, дайте мне знать. Насколько я знаю, я просто добавлю сноску к своим отчетам в журналах, в которой указано, что они включают трафик ботов.

1 голос
/ 14 января 2009

Я думаю, что ваша проблема здесь:

\s"http://w{0,3}\.mywebsite\.com[^\"]*" 

Это не будет отражать случай "http://mywebsite.com"", потому что перед "mywebsite" всегда будет требоваться точка.

Также вы исключаете только GET-запросы. А как насчет POST и HEAD?

Edit: Если вы по-прежнему получаете числа, которые кажутся неправильными, вам обязательно нужно перехватить реферрера с помощью регулярного выражения и распечатать его.

0 голосов
/ 22 мая 2009

В данный момент я выбираю фильтрацию журнала по IP. Самые активные боты - это Google, Yahoo, MSN и т. Д. Итак, я взял диапазон IP-адресов и удалил их из записи.

0 голосов
/ 14 января 2009

Для соответствия URI Regex, попробуйте Regex :: Common (или, точнее, Regexp :: Common :: URI :: http).

...