Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема PERL+MySQL, А точнее со скриптом статисктики 
:(
    Опции темы
SantaXP
  Дата 29.6.2005, 02:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 5.6.2003

Репутация: нет
Всего: нет



Именно так. У мен возникла проблема, при изучении книги "Разработка CGI-приложений на PERL". То есть там есть пример скрипта составления статистики посещения сайта. То есть инфо о посетителе выводится скриптом "viewlog.cgi", собирается информация с помощью "vislog.cgi" + собственный модуль LogConnect.pm для подключения к базе данных visitors на MySQL сервере localhost. smile
Так вот. Несмотря на многочисленные проблемы, я привёл скрипты вот в такой результат, который я вам сейчас продемонстрирую.
LogConnect.pm:
Код

package LogConnect;
use DBI;
use strict;
use CGI::Carp qw(fatalsToBrowser);
sub connect {
 my $log_dsn = "DBI:mysql:database=visitors;host=localhost";
 my $log_dbh = DBI->connect($log_dsn, "mysql", "");
 if (!defined($log_dbh)) {
  print "Content-Type: text/html\n\n";
  print qq(
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=KOI8-R">
  <title>\u041e\u0448\u0438\u0431\u043a\u0430!</title>
  </head>
  <body bgcolor="white">);
  print "<p><font color='red'>error: \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043a \u0434\u0430\u043d\u043d\u044b\u0445 MySQL:</font></p>";
  print "<p><font color='blue'>";
  print DBI->errstr;
  print "</font></p>";
  print "-" x.25."\n";
  return;
  }
 }
 1;

vislog.cgi:
Код

#!/usr/local/bin/perl5 -wT
#\u0420\u0443\u0441\u0441\u043a\u0438\u0439
#\u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u043e\u044e (SantaXP) \u0434\u043b\u044f \u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u0439 \u0441\u0430\u0439\u0442\u0430
#\u0421\u043e\u0437\u0434\u0430\u043d 25 \u0438\u044e\u043d\u044f 2005 \u0433\u043e\u0434\u0430
#\u0412\u0441\u0435 \u043f\u0440\u0430\u0432\u0430 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442 SantaXP
#English
#This csript was written by me (SantaXP) to make a statistic of visitors of my web-sait
#Made in june 25 2005 year
#All rigths reserved by SantaXP 
#\u041e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0438\u0437 \u043a\u043d\u0438\u0433\u0438 \u041a\u0435\u0432\u0438\u043d\u0430 \u041c\u0435\u043b\u044c\u0442\u0446\u0435\u0440\u0430 \u0438 \u0411\u0440\u0435\u043d\u0442\u0430 \u041c\u0438\u0445\u0430\u043b\u044c\u0441\u043a\u0438 "\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 CGI \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 PERL"

use POSIX;
use Socket;
use lib qw(.);
use LogConnect;
use CGI::Carp qw(fatalsToBrowser);

my $dbh = LogConnect->connect;
my $ip = $ENV{'REMOTE_ADDR'};
my $browser = $ENV{'HTTP_USER_AGENT'};
my $referer = $ENV{'HTTP_REFERER'}; 
my $here = $ENV{'REQUEST_URI'};

my @digits = split(/\./, $ip);
my $adress = pack("C4", @digits);
my $host = gethostbyaddr($address, AF_INET);

my $time = strftime("%Y-%m-%d %H:%M:%S",gmtime);

my $query = qq(
 insert into acess_log values
  ("$ip","$host","$browser","$here","$referer","$time"));
my $sth = $dbh->prepare($query);
$sth->execute;
$dbh->disconnect;

viewlog.cgi:
Код

#!/usr/local/bin/perl5 -wT
#\u0420\u0443\u0441\u0441\u043a\u0438\u0439
#\u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u043e\u044e (SantaXP) \u0434\u043b\u044f \u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u0439 \u0441\u0430\u0439\u0442\u0430
#\u0421\u043e\u0437\u0434\u0430\u043d 25 \u0438\u044e\u043d\u044f 2005 \u0433\u043e\u0434\u0430
#\u0412\u0441\u0435 \u043f\u0440\u0430\u0432\u0430 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442 SantaXP
#English
#This csript was written by me (SantaXP) to make a statistic of visitors of my web-sait
#Made in june 25 2005 year
#All rigths reserved by SantaXP 
#\u041e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0438\u0437 \u043a\u043d\u0438\u0433\u0438 \u041a\u0435\u0432\u0438\u043d\u0430 \u041c\u0435\u043b\u044c\u0442\u0446\u0435\u0440\u0430 \u0438 \u0411\u0440\u0435\u043d\u0442\u0430 \u041c\u0438\u0445\u0430\u043b\u044c\u0441\u043a\u0438 "\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 CGI \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 PERL"

use strict;
use lib qw(.);
use LogConnect;
use CGI::Carp qw(fatalsToBrowser);
print "Content-Type: text/html\n\n";

my $dbh = LogConnect->connect;
my $query = qq(select CLIENT from acess_log);
my $sth = $dbh->prepare($query);
$sth->execute;
my %clients;
while (x$_ = $sth->fetchrow) {
 $clients{$_}++;
 }
 $dbh->disconnect;
 my @clients = sort {$clients{$b} <=> $clients{$a}}
 keys %clients;
 print <<HTML;
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=KOI8-R">
 <title>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043e\u0442\u0447\u0451\u0442</title>
 </head>
 <body bgcolor="white">
 <center><h2>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043e\u0442\u0447\u0451\u0442</h2></center>
 <center><h3>\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 Web-\u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432</h3></center>
 <hr noshade>
<center>
<table border=1 cellpadding=3 cellspacing=3>
HTML
foreach (@clients) {
print qq(<td align=center>$_</td><td align=center>
 $clients{$_}</td><tr>);
 }
 print qq(
 </table>
 </center>
 </body>
 </html>);

Раньше ко всем 3-ём скриптам прилагалась строка:
use strict;
Однако, от неё было больше проблем, чем пользы. И так, при запуске, либо viewlog.cgi, либо vislog.cgi выдаётся лишь вот такое сообщение, отличающееся в двух вариантах, лишь номером строки с prepare:
Цитата

Content-type: text/html
Software error:

Can't call method "prepare" without a package or object reference at /usr/local/apache/cgi-bin/viewlog.cgi line 20.

For help, please send mail to the webmaster (santaxp@localhost), giving this error message and the time and date of the error.

-----
smile Спасибо всем за внимание, я с большим трудом проделал многое, чтобы дойти до того варианта, в котором я задаю вопрос вам и, поскольку, я активно занят обучением CGI программирования на PERL этот вопрос для меня крайне актуален и посему я решил попросить помощи у более опытных и лучших программистов, чем я. Заранее спасибо за внимание! smile
PM MAIL   Вверх
SantaXP
Дата 29.6.2005, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 5.6.2003

Репутация: нет
Всего: нет



smile Спасибо, сейчас же попробую, только вот один вопросик, а что такое ООП??? smile
PM MAIL   Вверх
chaos
Дата 29.6.2005, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: нет
Всего: 44



объекьно-ориентированное программирование
PM WWW   Вверх
SantaXP
Дата 29.6.2005, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 5.6.2003

Репутация: нет
Всего: нет



smile Мда... Ничего не получается. В любом случае выдаёт ошибку. Пожалуйста, не могли бы вы написать код этих 3-ёх скриптов в рабочем варианте (то есть, как у вас)... smile
PM MAIL   Вверх
korob2001
Дата 29.6.2005, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Код

package LogConnect;
use DBI;
use strict;
use CGI::Carp qw(fatalsToBrowser);
sub connect {
 my $log_dbh = DBI->connect("DBI:mysql:host=localhost;database=visitors", "mysql", "",
                            { PrintError => 1, RaiseError => 0 });
 if (!defined($log_dbh)) {
  print "Content-Type: text/html\n\n";
  print qq(
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=Windows-1251">
  <title>ОШИБКА</title>
  </head>
  <body bgcolor="white">);
  print "<p><font color='red'>error: Ошибка при подключении  к MySQL:</font></p>";
  print "<p><font color='blue'>";
  print DBI->errstr;
  print "</font></p>";
  print "-" x.25."\n";
  return;
  }
  return $log_dbh;
 }
 1;


Код

#!/usr/local/bin/perl5 -w
use strict;
use lib qw(.);
use LogConnect;
use CGI::Carp qw(fatalsToBrowser);
print "Content-Type: text/html\n\n";

my $dbh = LogConnect->connect;
my $query = qq(SELECT * FROM AutoGeneral);
my $sth = $dbh->prepare($query);
$sth->execute;
my %clients;
while ($_ = $sth->fetchrow) {
 $clients{$_}++;
 }
 $dbh->disconnect();
 my @clients = sort {$clients{$b} <=> $clients{$a}}
 keys %clients;
 print <<HTML;
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=Windows-1251">
 <title>Просто тест</title>
 </head>
 <body bgcolor="white">
 <center><h2>Просто тест</h2></center>
 <center><h3>Ппрсто тест</h3></center>
 <hr noshade>
<center>
<table border=1 cellpadding=3 cellspacing=3>
HTML
foreach (@clients) {
print qq(<td align=center>$_</td><td align=center>
 $clients{$_}</td><tr>);
 }
 print qq(
 </table>
 </center>
 </body>
 </html>);


Код

#!/usr/local/bin/perl5 -w

use POSIX;
use Socket;
use lib qw(.);
use LogConnect;
use CGI::Carp qw(fatalsToBrowser);


my $ip = $ENV{ HTTP_X_FORWARDED_FOR } || $ENV{'REMOTE_ADDR'};
my $browser = $ENV{'HTTP_USER_AGENT'};
my $referer = $ENV{'HTTP_REFERER'};
my $here = $ENV{'REQUEST_URI'};

my @digits = split(/\./, $ip);
my $adress = pack("C4", @digits);
my $host = gethostbyaddr($adress, AF_INET);

my $time = strftime("%Y-%m-%d %H:%M:%S",gmtime);


my $dbh = LogConnect->connect();
my $query = "INSERT INTO acess_log VALUES ("$ip","$host","$browser","$here","$referer","$time")";
my $sth = $dbh->prepare($query);
$sth->execute();

$sth->finish();
$dbh->disconnect();


Удачи.

Это сообщение отредактировал(а) korob2001 - 29.6.2005, 20:16


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
SantaXP
Дата 29.6.2005, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 5.6.2003

Репутация: нет
Всего: нет



smile Спасибо огромное. Вроде всё прекрасно работает (по крайней мере viewlog.cgi не выдаёт ошибок). Однако осталась одна маленькая проблемка:
Цитата
Software error:

syntax error at /usr/local/apache/cgi-bin/vislog.cgi line 16, near ""INSERT INTO acess_log VALUES ("$ip"
Execution of /usr/local/apache/cgi-bin/vislog.cgi aborted due to compilation errors.

For help, please send mail to the webmaster (santaxp@localhost), giving this error message and the time and date of the error.

Честно говоря, ошибку в вашем коде не нашёл. Если заменить все двойные скобки на одинарные, то пишет это:
Цитата
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, santaxp@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.

Apache/1.3.20 Server at localhost Port 80

Однако, когда я порылся в логах апача - понял, что вы неправильно указали название таблицы (access_log).
Теперь пишет вот это:
Цитата
sSoftware error:

syntax error at /usr/local/apache/cgi-bin/vislog.cgi line 16, near ""INSERT INTO access_log VALUES ("$ip"
Execution of /usr/local/apache/cgi-bin/vislog.cgi aborted due to compilation errors.

For help, please send mail to the webmaster (santaxp@localhost), giving this error message and the time and date of the error. 

Есди снова заменить все двойны на одинарные кавычки пишет в логах:
Цитата
[Wed Jun 29 23:49:07 2005] vislog.cgi: Use of uninitialized value in concatenation (.) or string at /usr/local/apache/cgi-bin/vislog.cgi line 16.
[Wed Jun 29 23:49:07 2005] [error] [client 127.0.0.1] Premature end of script headers: /usr/local/apache/cgi-bin/vislog.cgi

smile

Это сообщение отредактировал(а) SantaXP - 29.6.2005, 22:49
PM MAIL   Вверх
korob2001
Дата 30.6.2005, 01:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Попробуй так:
Код

my $query = "INSERT INTO acess_log VALUES ('$ip','$host','$browser','$here', '$referer','$time')";

или попробуй указать явно поля в запросе:
Код

my $query = "INSERT INTO acess_log (Ip, Host, Browser, Here, Referer, Time ) VALUES ('$ip','$host','$browser','$here', '$referer','$time')";

Удачи.

Это сообщение отредактировал(а) korob2001 - 30.6.2005, 01:49


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
SantaXP
Дата 30.6.2005, 15:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 5.6.2003

Репутация: нет
Всего: нет



smile Так, с vislog.cgi я разобрался, спасибо огромное! Вот такой запрос оказался верным:
Код

my $query = "INSERT INTO access_log (IP, DOMAIN, CLIENT, PAGE_TO, PAGE_FROM, TIME_STAMP ) VALUES ('$ip','$host','$browser','$here', '$referer','$time')";

----
ОК, vielog.cgi работает замечательно!!! smile Преогромное спасибо за ваше терпение! Однако, пожалуйста, у меня ещё одна маленькая просьба. Взгляните вот на этот код:
Код

#!/usr/local/bin/perl5 -w    
use strict;    
use lib qw(.);    
use LogConnect;    
use CGI::Carp qw(fatalsToBrowser);
    
print "Content-Type: text/html\n\n";    
my $dbh = LogConnect->connect;    

#\u041f\u043e\u043b\u0435 CLIENT
my $query = qq(SELECT CLIENT FROM access_log);    
my $sth = $dbh->prepare($query);    
$sth->execute;
    
my %clients;    
while ($_ = $sth->fetchrow) 
{    
$clients{$_}++;    
}    
$dbh->disconnect();    
 
my @clients = sort {$clients{$b} <=> $clients{$a}}    
keys %clients;    

#\u041f\u043e\u043b\u0435 IP
my $query_ip = qq(SELECT IP FROM access_log);    
my $sth = $dbh->prepare($query_ip);    
$sth->execute;
    
my %ip;    
while ($_ = $sth->fetchrow) 
{    
$ip{$_}++;    
}    
$dbh->disconnect();    
 
my @ip = sort {$ip{$b} <=> $ip{$a}}    
keys %ip;    

print qq(
 <html>    
 <head>    
 <meta http-equiv="Content-Type" content="text/html; charset=Windows-1251">    
 <title>\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0439</title>    
 </head>    
 <body bgcolor="white">
 <center><h1>\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0439</h1></center>        
 <hr noshade>    
<center>    
<table border=1 cellpadding=3 cellspacing=3>    
);

foreach (@clients) {    
print qq(<td align=center>$_</td>);
 foreach (@ip)
 {print qq(<td align=center>$_</td>);}
 print qq(<td align=center>    
 $clients{$_}</td><tr>);    
 }    
 
print qq(    
 </table>    
 </center>    
 </body>    
 </html>);

У меня имеется в таблице access_log шесть полей. Из них в данном скрипте я вывел только 2 (имена полей смотрите в верхнем, моём отредактированном запросе). Однако такой скрипт на мой взгляд далёк от оптимизации. немогли бы вы, как профессионал рассказать мне, что и как тут оптимизировать, однако несколько проще. Чтобы я смог этот скрипт (оптимизированный вами) понять и переварить в своей голове. smile Ещё раз огромное спасибо!
PM MAIL   Вверх
korob2001
Дата 1.7.2005, 03:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



1.) Удали эту строку:
Код

use CGI::Carp qw(fatalsToBrowser);

Она нужна только на стадии разработки, юзеру совсем даже не нужно видеть подробностей.

2. ) Если ты сортируешь строки, в этой части кода:
Код

my @clients = sort {$clients{$b} <=> $clients{$a}}    
keys %clients;

Тогда замени её на такую:
Код

my @clients = sort {$clients{$b} cmp $clients{$a}}    
keys %clients;


3. ) Может подумать над тем, что бы вместо двух запросов подряд к базе данных, сделать один?? Темболее ты обращаешься к одной таблице.
Например:
Код

$sql = "SELECT CLIENT, IP FROM access_log ORDER BY CLIENT";
my $dbh = LogConnect->connect();
$dbh->prepare( $sql );
$sth->execute();
while ( $href = $sth->fetchrow_hashref() ) {
         print $href->{ CLIENT } . " => " . $href->{ IP } . "<br>";
}
$sth->finish();
$dbh->disconnect();

Данный код выдаст в браузер всех клиентов и их IP, отсортированных по полю CLIENT.

ЗЫ:
Это работать бует не верно, да и расходы большие:
Код

foreach (@clients) {    
print qq(<td align=center>$_</td>);
 foreach (@ip)
 {print qq(<td align=center>$_</td>);}
 print qq(<td align=center>    
 $clients{$_}</td><tr>);    
 } 

Работать будет не верно из за того, что ты сначала получаешь список клиентов, сортируешь его:
Код

my @clients = sort {$clients{$b} <=> $clients{$a}}    
keys %clients; 

затем получаешь список ip, сортируешь его не зависимо от списка клиентов
Код

my @ip = sort {$ip{$b} <=> $ip{$a}}    
keys %ip;

потому у тебя каждый клиент, будет иметь не свой IP.

И запомни, что строки нельзя сортировать как числа. Для строк cmp, для чисел <=>. Это так же касается операторов сравнения.

Удачи.

Это сообщение отредактировал(а) korob2001 - 1.7.2005, 03:28


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
SantaXP
Дата 1.7.2005, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 5.6.2003

Репутация: нет
Всего: нет



smile Спасибо огромное, буду работать над собой и над кодом. smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: разработка для Web | Следующая тема »


 




[ Время генерации скрипта: 0.0616 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.