有些网站仅靠简单的GET和POST请求是不能访问的,他们需要cookie,验证,指定的Referer或者User-Agent头部信息。
cookie由服务器创建发送给请求者,再由客户端发出请求的时候在header中添加cookie发送给服务器。例如某个客户端给服务器发送了一个请求,然后服务器给客户端的应答头部为:
Date: Thu, 28 Feb 2002 04:29:13 GMT
Server: Apache/1.3.23 (Win32)
Content-Type: text/html
Set-Cookie: foo=bar; expires=Thu, 20 May 2010 01:23:45 GMT;
path=/
那么意味着客户端访问该服务器的任何网址都需要cookie,Cookie: foo=bar。要访问该站点,所有的请求头部都需要Cookie: foo=bar,直到Thu, 20 May 2010 01:23:45 GMT,在这之后,客户端就不用再发送cookie了。Set-Cookie行有时候(在session结束的时候,也即客户关闭了浏览器,cookie也就结束了)指定不了过期时间。并且有时候path可能会更具体些,比如说/dahut/,在这种情况下,那么客户端只会给http://thishost/dahut/开头的网址发送cookie。最后,cookie可以指定不止一个host,这样就给host下面的子域也发送cookie,例如path为search.mybazouki.com,那么在mybazouki.com下面的所有子域都会发送cookie,例如images.mybazouki.com, ads.mybazouki.com, extra.stuff.mybazouki.com等。
默认状态下LWP::UserAgent对象是不执行cookie的,要让LWP::UserAgent执行cookie,用下面的语句:
my $browser = LWP::UserAgent->new( );
$browser->cookie_jar( {} ); #注意cookie不被保存,当程序关闭的时候cookie被清除。
从文件中load cookie:
use HTTP::Cookies;
my $cookie_jar = HTTP::Cookies->new(file => "/some/where/cookies.lwp",);
my $browser = LWP::UserAgent->new;
$browser->cookie_jar( $cookie_jar );
这样当cook jar(HTTP cookie数据库)被创建的时候,文件就被读取,但是当$browser对象增加新的cookie的时候文件永远都不会更新!!
从Netscape cookies文件中读取和从LWP格式的cookie文件中读取是不一样的。请看实例:
use HTTP::Cookies::Netscape;
my $cookie_jar = HTTP::Cookies::Netscape->new(file => "c:/program files/netscape/users/shazbot/cookies.txt",);
my $browser = LWP::UserAgent->new;
$browser->cookie_jar( $cookie_jar );
将cookie保存到文件
为了能让文件及时更新cookie,应该加个参数autosave => 1,例如:
use HTTP::Cookies;
my $cookie_jar = HTTP::Cookies->new(file => "/some/where/cookies.lwp",autosave => 1,);
my $browser = LWP::UserAgent->new;
$browser->cookie_jar( $cookie_jar );
注意:在Netscape cookie文件情况下参数autosave => 1不起作用。
添加额外的请求heade行
如果你在浏览器中看到的网页和LWP中看到的网页是不一样的,首先应该考虑通过空cookie jar打开cookie支持。如果不行,就通过文件的方式打开cookie支持,如果还是不行,就该考虑该服务器是如何区分LWP和浏览器的。
每种浏览器发送的头部信息都是不一样的,例如LWP::UserAgent发送:User-Agent: libwww-perl/5.5394。Netscape 4.76发送:User-Agent: Mozilla/4.76 [en] (Win98; U)
另外还发送LWP不发送的:
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
image/png, */*
Accept-Charset: iso-8859-1,*,utf-8
Accept-Encoding: gzip
Accept-Language: en-US
Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。
Referer其实应该是英文单词Referrer,不过拼错的人太多了,所以编写标准的人也就将错就错了。
实例:
my $response = $browser->get(
# The URL of the image:
'http://pst.rbma.com/content/Dennis_The_Menace',
'Referer' => # The URL where I see the strip:
'http://www.sfgate.com/cgibin/article.cgi?file=/comics/Dennis_The_Menace.dtl',
);
open(OUT, ">today_dennis.gif") || die $!;
binmode(OUT);
print OUT $response->content;
close(OUT);
验证
请求一个需要验证的URL,会返回一个401未授权的的状态码,应答结果中含有WWW-Authenticate的header信息,它指定验证的方法:"basic"和realm(一段用来区分lock-off区域的字符串)。再次在头部中添加Authorization行,加入用户名和密码,如果正确,就能返回正确的页面。
验证方法:
$browser->credentials(
'servername:portnumber',
'realm-name',
'username' => 'password'
);
实例:
my $browser = LWP::UserAgent->new;
$browser->name('ReportsBot/1.01');
$browser->credentials(
'reports.mybazouki.com:80',
'web_server_usage_reports',
'plinky' => 'banjo123'
);
my $response = $browser->get('http://reports.mybazouki.com/this_week/');
---------------------------------------------------------------------------------------------------
LWP含登录COOKIES
#!/usr/bin/perl
#use strict;
use LWP::UserAgent;
#use HTTP::Cookies;
use HTTP::Request;
use HTTP::Response;
use DBI;
my $dbuser="movie";
my $dbpasswd="123456";
my $db="movie";
my $dbh=DBI->connect("DBI:mysql:$db",$dbuser,$dbpasswd);
my $ua=new LWP::UserAgent;
$ua->cookie_jar(HTTP::Cookies->new(file=>'mycookies.txt',autosave=>1));
my $request0=new HTTP::Request('get','http://www.7452.com/movie/wantlogin.asp?userid1=pc999&pws=123456');
my $request=new HTTP::Request('get','http://www.7452.com/movie/userpass.asp?userid=pc999&password=123456');
$ua->request($request0);
my $response=$ua->request($request);
$ii=1207;
while ($ii<2000) {
my $request_=new HTTP::Request('get','http://www.7452.com/movie/movie.asp?id='.$ii);
$response=$ua->request($request_);
$a=$response->content;
if ($a=~//[影片名称/][/w/W]{46}.*[^//"<>]/g) {
$title=$&;
$title=~/.*<//b>/;
$title=substr($&,3,length($&)-7);
print $title."/n/n";
$a=~//[影片类型/][/w/W]{46}.*[^//"<>]/;
$type=$&;
$type=~/">.*<///;
$type=substr($&,2,length($&)-4);
print $type."/n/n";
$a=~/IMG///w{2,5}/.gif/;
$movietype=$&;
print $movietype."/n/n";
$a=~//[影片介绍/][/w/W]*( ){8}[^td]*/;
$content=$&;
$content=substr($&,195,length($&)-197);
$content=~s/'//g;
print $content."/n/n";
$a=~/upload.*[jpgif]{3,4}/i;
$url=$&;
$movie1="";
while ($a=~/look/.asp/?id1=/d{3,6}/g) {
my $urlid=substr($&,13,length($&)-13);
my $request_g=new HTTP::Request('get','http://www.7452.com/movie/govodurl.asp?urlid='.$urlid.'&serverip=56');
$response=$ua->request($request_g);
my $leurl=$response->content;
#$leurl=~/.*:/d{2,5}//[^//]*/;
#my @leurl0=split(/:/d{1,4}//[^//]{0,20}/,$leurl);
$movie1=$movie1."||".$leurl;
#0[1];
print $leurl."/n/n";
}
my $query="insert into movie_le (title,url,content,type,movietype,movie1) values ('$title','$url','$content','$type','$movietype','$movie1')";
$sth=$dbh->prepare($query);
$rv=$sth->execute or die "Cant't execute the query:$sth->errstr/n";
print "OK!!!!/n/n/n";
}
$ii++;
}
exit;