LWP与WEB的基本使用.docx
《LWP与WEB的基本使用.docx》由会员分享,可在线阅读,更多相关《LWP与WEB的基本使用.docx(15页珍藏版)》请在冰豆网上搜索。
LWP与WEB的基本使用
LWP与WEB的基本使用
简介
LWP(“LibraryforWWWinPerl”的缩写)是一个由多个模块组成,用来获取网络数据的的模块组。
和很多Perl的模块一样。
每一个LWP模块都自带详细的文档,做为对这个模块的完整介绍。
可是面对LWP里的众多模块,有时候即使是完成最简单的工作,新手们也常常不知道从那里开始。
要对LWP做全面的介绍需要一整本书,很幸运,Perl&LWP已经出版。
而这篇文章向你介绍了最常见的LWP用法。
使用LWP:
:
Simple获取网页
如果只是要拿到某个网页,那使用LWP:
:
Simple里的函数是最简单的。
通过调用get($url)函数,就可以得到相关网址的内容。
如果没有发生错误,get函数返回此网页,否则,返回undef。
例子如下:
my$url='http:
//freshair.npr.org/dayFA.cfm?
todayDate=current'
useLWP:
:
Simple;
my$content=get$url;
die"Couldn'tget$url"unlessdefined$content;
#$content里是网页内容,下面是对此内容作些分析:
if($content=~m/jazz/i){
print"They'retalkingaboutjazztodayonFreshAir!
\n";
}else{
print"FreshAirisapparentlyjazzlesstoday.\n";
}
如果要在命令行里运行,getprint函数非常方便。
如果没有发生错误,它会把网页内容输出到STDOUT,否则将会有错误信息输出到STDERR。
例如:
%perl-MLWP:
:
Simple-e"getprint'http:
//cpan.org/RECENT'"
上面的网址指向一个文本文件,列有最近两个星期内CPAN更新过的文件。
如果想要知道Acme:
:
的模块是否有更新,有就email自己,你可以把它和Shell结合到一起来实现。
如下:
%perl-MLWP:
:
Simple-e"getprint'http:
//cpan.org/RECENT'"|grep"/by-module/Acme"|mail-s"NewAcmemodules!
Joy!
"$USER
LWP:
:
Simple还有一些非常有用的函数,包括一个运行HEAD请求的函数,用来检查链接是否有效,网页是否更新。
另外两个用来保存和镜像网址的函数也值得一提。
具体请看LWP:
:
Simple的文档或Perl&LWP的第二章.
LWPClass模型基础
LWP:
:
Simple在做简单的工作时很方便。
但因为不支持cookies,用户认证,对HTTPrequestheader(请求标头)的编辑,和HTTPresonseheader(响应标头)的读写(主要是HTTP的errormessage)。
因此,当需要这些特性的时候,就要使用LWPClass模型。
在众多的LWPClass里,LWP:
:
UserAgent和HTTP:
:
Response是必须理解的。
LWP:
:
UserAgent就像一个虚拟浏览器用来作request(请求)。
HTTP:
:
Response用来储存request(请求)生成的response(响应)。
最基本的用法是$response=$browser->get($url),或写的更完整些:
#程序开始:
useLWP5.64;#载入较新版本的LWPclasses
my$browser=LWP:
:
UserAgent->new;
...
#getrequest:
my$url='http:
//freshair.npr.org/dayFA.cfm?
todayDate=current';
my$response=$browser->get($url);
die"Can'tget$url--",$response->status_line
unless$response->is_success;
die"Hey,我想要HTML格式而不是",$response->content_type
unless$response->content_typeeq'text/html';
#或者任何其他的content-type
#成功的话就对内容处理
if($response->content=~m/jazz/i){
print"FreshAir今天在讨论爵士乐!
\n";
}else{
print"FreshAir今天讨论的和爵士乐一点边都不沾.\n";
}
上面有两个相关的object:
$browser,是LWP:
:
UserAgent的一个object。
$response是属于HTTP:
:
Response类的一个object。
一个程序里只需要一个$browserobject,但是每次发出一个request,就会得到一个新的HTTP:
:
Responseobject。
HTTP:
:
Responseobject有以下一些有价值的属性:
∙一个statuscode(状态代码值),表示成功或失败。
你可以使用$response->is_success来检测它。
∙httpstatusline(http状态描述),观察$response->status_line的结果(比如“404NotFound”)会帮助你理解这个词的意思。
∙MIMEcontent-type(文件类型)通过$response->content_type来获得。
例如“text/html”,”image/gif”,”application/xml”等等。
∙contentoftheresponse(响应返回的内容)储存在$response->content。
内容可能是html格式。
如果是GIF格式,$response->content里是二进制的GIF数据。
∙许多其他methods都可以在HTTP:
:
Response和它的superclasses(父class)HTTP:
:
Message和HTTP:
:
Headers里找到。
添加其他HTTP请求headers
request(请求)常用的方法是$response=$browser->get($url),但如果需要,你可以在$url后跟一个键值的列表来给你的request加上其他HTTPheaders。
象这样:
$response=$browser->get($url,$key1,$value1,$key2,$value2,...);
举个例子,如果你要对一个只允许Netscape浏览器连入的网站发出请求,那就需要发出类似Netscape的header,如下:
my@ns_headers=(
'User-Agent'=>'Mozilla/4.76[en](Win98;U)',
'Accept'=>'image/gif,image/x-xbitmap,image/jpeg,
image/pjpeg,image/png,*/*',
'Accept-Charset'=>'iso-8859-1,*,utf-8',
'Accept-Language'=>'en-US',
);
...
$response=$browser->get($url,@ns_headers);
如果不打算重复使用这个array,你可以把它写到get函数里
$response=$browser->get($url,
'User-Agent'=>'Mozilla/4.76[en](Win98;U)',
'Accept'=>'image/gif,image/x-xbitmap,image/jpeg,
image/pjpeg,image/png,*/*',
'Accept-Charset'=>'iso-8859-1,*,utf-8',
'Accept-Language'=>'en-US',
);
如果只是打算修改User-Agent,可以通过LWP:
:
UserAgent的agent方法把缺省的agent‘libwww-perl/5.65’(或者别的)改掉。
$browser->agent('Mozilla/4.76[en](Win98;U)');
使用cookies
默认的LWP:
:
UserAgent对象像一个不支持cookies的浏览器一样工作。
有不只一种的办法可以设定它的cookie_jar属性,从而让它支持cookies。
“cookiejar”是一个用来储存HTTPcookie的容器。
你可以把它存到硬盘(像Netscape使用cookies.txt一样)或内存里。
存到内存里的cookies会在程序完成后消失。
内存式的cookie使用方法:
$browser->cookie_jar({});
也可以把cookie储存到硬盘的文件里:
useHTTP:
:
Cookies;
$browser->cookie_jar(HTTP:
:
Cookies->new(
'file'=>'/some/where/cookies.lwp',
#储存cookies的地址
'autosave'=>1,
#当完成后自动储存到硬盘里
));
文件里的cookie是以LWP自定的格式储存,如果你想在netscape里使用这个cookie文件,可以使用HTTP:
:
Cookies:
:
Netscapeclass:
useHTTP:
:
Cookies;
#yes,loadsHTTP:
:
Cookies:
:
Netscapetoo
$browser->cookie_jar(HTTP:
:
Cookies:
:
Netscape->new(
'file'=>'c:
/ProgramFiles/Netscape/Users/DIR-NAME-HERE/cookies.txt',
#wheretoreadcookies
));
你也可以象上面一样使用‘autosave’=>1。
但Netscape的cookie有时会在写入硬盘之前就被丢掉,至少在写这篇文章的时候还是这样。
通过POST提交表格
大部分HTML表格使用HTMLPOST向服务器提交数据,在这里你可以这样:
$response=$browser->post($url,
[
formkey1=>value1,
formkey2=>value2,
...
],
);
或者你也可以把HTTPheader也一起发出
$response=$browser->post($url,
[
formkey1=>value1,
formkey2=>value2,
...
],
headerkey1=>value1,
headerkey2=>value2,
);
下一个例子向AltaVista的搜索引擎发送HTTPPOST请求,然后从HTML里提取出符合匹配的总数。
usestrict;
usewarnings;
useLWP5.64;
my$browser=LWP:
:
UserAgent->new;
my$word='tarragon';
my$url='
my$response=$browser->post($url,
['q'=>$word,#theAltavistaquerystring
'pg'=>'q','avkw'=>'tgz','kl'=>'XX',
]
);
die"$urlerror:
",$response->status_line
unless$response->is_success;
die"Weirdcontenttypeat$url--",$response->content_type
unless$response->content_typeeq'text/html';
if($response->content=~m{AltaVistafound([0-9,]+)results}){
#从"AltaVistafound2,345results"里匹配出结果
print"$word:
\n";
}else{
print"Couldn'tfindthematch-stringintheresponse\n";
}
通过GET提交表格
一些HTML表格不使用POST请求,而是使用GET请求来传输数据。
例如,在里检索电影名字‘BladeRunner’,提交后在浏览器的网址栏里将显示:
下面是使用LWP实现同样的结果:
useURI;
my$url=URI->new(');
#makesanobjectrepresentingtheURL
$url->query_form(#Andheretheformdatapairs:
'title'=>'BladeRunner',
'restrict'=>'MoviesandTV',
);
my$response=$browser->get($url);
第5章详细描述了HTML表格和表格数据,第6章到第9章描述了怎样从获得的HTML数据里提取出有用的信息。
URL处理
上面提到的URIclass提供很多获取和修改URL的方法。
例如如果想要知道url是什么类型(http,ftp等等)可以使用$url->schema来得到,如果要提取网址里的主机名,可以使用$url->host。
不过,可能最有用的是我前面提到的query_form方法,以及把相对网址路径(如”../foo.html”)转换成绝对路径(如”
useURI;
$abs=URI->new_abs($maybe_relative,$base);
现在回忆一下获取最新CPAN模块的那个例子。
usestrict;
usewarnings;
useLWP5.64;
my$browser=LWP:
:
UserAgent->new;
my$url='http:
//www.cpan.org/RECENT.html';
my$response=$browser->get($url);
die"Can'tget$url--",$response->status_line
unless$response->is_success;
my$html=$response->content;
while($html=~m/chunk86920392chunklt;AHREF=\"(.*?
)\"/g){
print"\n";
}
输出的结果是
MIRRORING.FROM
RECENT
RECENT.html
authors/00whois.html
authors/01mailrc.txt.gz
authors/id/A/AA/AASSAD/CHECKSUMS
...
你可以使用URI模块的new_abs方法来得到完全网址路径,修改while循环:
while($html=~m/)\"/g){
printURI->new_abs(,$response->base),"\n";
}
$response->base方法可以在HTTP:
:
Message里找到。
它返回的URL通常被用来和相对路径合并来得到完全路径。
现在得到的结果是
http:
//www.cpan.org/MIRRORING.FROM
http:
//www.cpan.org/RECENT
http:
//www.cpan.org/RECENT.html
http:
//www.cpan.org/authors/00whois.html
http:
//www.cpan.org/authors/01mailrc.txt.gz
http:
//www.cpan.org/authors/id/A/AA/AASSAD/CHECKSUMS
...
请参考Perl&LWP的第四章,以得到对URIobjects更详细的描述。
当然,使用regexp(正则表达式)来匹配url相对简单,如果情况复杂,需要更强大的匹配工具,可以考虑HTML分析模块HTML:
:
LinkExtor或HTML:
:
TokeParser,甚至HTML:
:
TreeBuilder
其他浏览器属性
LWP:
:
UserAgentobjects有几个值得注意的属性:
∙$browser->timeout(15):
设定缺省request的timeout时间.超过这个时间就放弃请求。
∙$browser->protocols_allowed([‘http’,‘gopher’]):
这用来设定只接受http和gopher协议。
连接其他协议时就返回500错误值,”AccesstoftpURIshasbeendisabled”的错误消息。
∙useLWP:
:
ConnCache;$browser->conn_cache(LWP:
:
ConnCache->new()):
这告诉browserobject使用HTTP/1.1“keep-Alive”特性,即重复使用先前的socket来加快请求速度。
∙$browser->agent(‘SomeName/1.23(moreinfoheremaybe)’):
设置HTTP请求的User-Agent。
LWP缺省使用“libwww-perl/versionnumber”作为User-Agent,比如“libwww-perl/5.65”。
你可以加上更多的信息:
∙$browser->agent(‘SomeName/3.14(contact@robotplexus.int)’);
或者可以伪装为
$browser->agent(‘Mozilla/4.0(compatible;MSIE5.12;Mac_PowerPC)’);
∙push@{$ua->requests_redirectable},‘POST’:
告诉LWP在POST请求发送后如果发生重新定向就自动跟随(虽然RFC里不要求这么做)
详细请参见LWP:
:
UserAgent文档.
写一个有礼貌的机器人
如果想遵循robots.txt和避免在较短的时间发出太多的请求,你可以采用LWP:
:
RobotUA而不是LWP:
:
UserAgent。
LWP:
:
RobotUA用法与LWP:
:
UserAgent一样:
useLWP:
:
RobotUA;
my$browser=LWP:
:
RobotUA->new(
'YourSuperBot/1.34','you@');
#机器人名字和email地址
my$response=$browser->get($url);
HTTP:
:
RobotUA多了几个特性:
∙如果$url请求的服务器的robots.txt禁止了你对$url的访问,那么$browser就不会发出对于这个地址的请求,而是返回403代码和一个错误信息“Forbiddenbyrobots.txt”。
∙die"$url--",$response->status_line,"\nAborted"
∙unless$response->is_success;
然后你会得到这样的错误信息:
http:
//whatever.site.int/pith/x.html--403Forbidden
byrobots.txt
Abortedatwhateverprogram.plline1234
∙如果$browser发现请求的地址是刚刚请求过的,就会暂停(sleep)来避免发送太多的请求。
缺省暂停1分钟,但可以通过$browser->delay(minutes)来设定。
比如:
∙$browser->delay(7/60);
详细请参见LWP:
:
RobotUA文档.
使用代理
有时你希望(或者是必须)通过代理来连接某些站点或协议,就比如你的LWP程序是运行在某台处于防火墙之内的机器上。
代理通常储存在环境变量HTTP_PROXY里。
LWP可以通过user-agentobject里的env_proxy函数把环境变量里的代理地址装载。
useLWP:
:
UserAgent;
my$browser=LWP:
:
UserAgent->new;
#Andbeforeyougomakinganyrequests:
$browser->env_proxy;
详细请参照LWP:
:
UserAgent文档里的proxy,env_proxy和no_proxy方法.
HTTP认证
许多网站都是通过HTTP认证来限制连接.当用户请求一个限制页面时,HTTP服务器回复“Thatdocumentispartofaprotected‘realm’andyoucanaccessitonlyifyoure-requestitandaddsomespecialauthorizationheaderstoyourrequest”.(你现在请求了一个限制区域,如果你需要重新发送一个带有认证信息的header才可以连入.)
Unicode.org的管理员为了防止机器人访问邮件组获取发信人地址,