-
检查是否安装了PWL
perl-MLWP -le “print(LWP->VERSION)”
-
安装
perl有两种方式一种是通过CPAN的方式自动化安装,一种是手动安装,这里只介绍一下CPAN安装,关于手动安装看帮助文档吧。其实这里说的自动化安装很想debian的apt-get首先我们先要配置一下CPAN这个工具,它帮我们实现了下载和安装。
sudoperl -MCPAN -eshell运行后就会出现一系列选项,如果不知道选项的含义就一路next吧,默认选项有时候也是很不错的。配置完成后我们就可以安装我们想要的模块了。再次运行perl-MCPAN -eshell然后就会出现命令提示符。这里假设我们要安装HTML::Tree那么我们就键入installHTML::Tree等一会CPAN就自动帮我们全部都安装完成了。
-
URLs结构
这个就是我们通常所说的地址,它的构成为:scheme://username@server:port/path?query(URL构成)。他是由几部份构成的,scheme这里我理解成你要什么服务,是http、ftp、还是mail这些,username也就是主机名,path为你要访问的服务器上的相对地址,query就是发给服务器的表单,注意到这里的表单是编码过的。
-
Request和Response
先看request,它是又一个header和一个body组成的,header包含我要走哪里去-URL,我是谁-浏览器类型,我是坐车还是乘飞机-GETorPOST,其中body是一些可选内容,有时候我们需要向服务器发送一些信息,提交一些表单(POST)等。下面是一个典型的request的样子:
---------------------------------------------------------------------------------------------------------------------------------------------------------
GET (传递表单的方法) /daily/2001/01/05/1.html (服务器的哪个页面接收表单) HTTP/1.1(使用的协议是什么)
Host: www.suck.com
User-Agent: Super Duper Browser 14.6 (这个就叫做header)
[blank line]
---------------------------------------------------------------------------------------------------------------------------------------------------------
那么Response就好理解了,同样是包含了header和body其中body包含了失败或者成功的code和返回文本的类型,以及文本的长度(不可靠)。那body就很 久简单了,成功了就返回你想要的页面,失败了就返回错误页面。
-
LWP::Simple
这个模块提供了一些很方便的函数提供给我们快速的获取网页。
LWP::Simpleget($url)只要我们输入url就可以获取网页。但是这个函数也有缺陷我们得不到错误代码,当我们失败的时候我们唯一得到的就是undef。
LWP::Simplegetstore($url,$where)这个函数可以帮助我们把网页储存在本地硬盘,并且返回一个statuscode,这个状态码没有多大的用出我们只有把它传递给is_success()和is_error()这另个函数的返回值是true或者false。
Simple里面还有一个很奇葩的函数head(),这个函数在标量的环境返回真和假表示我们是否能够通过get()函数获取网页,但是有一个问题就是,如果服务器不支持返回header的话,不论是否可以通过get()获取都直接返回false。如果是在列表的环境的话返回一个列表里面包含五个值:
(content_type,document_length, modified_time, expires, server)
content_type指的就是MIME其中的一种类型或者子类型
document_length返回页面的长度,以字节为单位,通常这个数据不靠谱
modified_time最后修改时间,在目前的web2.0网页都是动态生成了,最后修改时间意义不大了
expires失效时间
server也就是服务器的类型,你是使用的apache还是nginx等等
最重要的一点LWP::Simple只支持GET不支持POST,啊,简直就是一出悲剧!
-
子程序是如何确定自己处在什么环境中的啦?
perl给我们提供了一个wantarray函数,如果一旦子程序在调用的时候处于列表环境中,那么这个函数就会返回真,否着返回假,这样我们就可以给子程序设计两种返回值,一种返回列表,一种返回标量。
-
HTTPPOST
告诉了我们两个事实,GET方法传递的参数是编码到URL中,而POST方法传递的参数是编码在body中。
-
perl的上下文环境(context)
还是perl中一个很重要的问题,在变量的使用过程中要严格的区分是列表上下文,还是标量上下文。有一个关于数组切片的问题,第一遍看的时候没有认真看,导致了理解错误。下面我们先看看两个例子:
@language[rand@language]与$language[rand@language]这两个看起来非常相似,但是有一点细微的差别造成了意义相当不一样,那就是第一个字符不一样,第一个表示一个数组的切片返回的总是一个列表,而第二个表示取出数组里面的一个元素,返回的总是一个标量。
细节啊!!!细节!!
-
引用问题
刚才顺带的把引用问题看了一下,不得不说在hash中使用的brace造成的问题,brace在编程中广泛使用,比如说if、while、until等,如果我们要返回一个匿名的hash的话如:
subhash_example{ {@_} }你说说,那个大括号是表示一个匿名hash呀,还是表示一个程序块。为了解决这一个冲突,perl提出了两种方案:
1.sub hash_example{+{@_}}
2.sub hash_example{return {@_}}
在想要返回的匿名hash的语句块前面放一个+号或者使用return就可以解决这个问
-
LWP::UserAgent和HTTP::Response细节探讨
LWP::UserAgent是一个类可以通过它声明一个对象,然后对象里面包含了很多方法,使用这些方法可以做各种各样的关于request的事情。
对象申明:$brower= LWP::UserAgent->new(%option);怪怪的
其中%option是一个hash包含了有关request的参数,我们接下来讨论这些参数:
链接相关的:
$oldval=$browser->timeout([newval]);可以设置等待服务器响应的时间,一般的程序就可以设置长点,但是像爬虫这样的程序的话,呵呵肯定是非常短咯,时间第一哈。这个函数可以设置时间值,也可以取出设置好的时间值.
$size= $browser ->max_size([bytes])设置字节响应的字节长度。
$cache= $browser->conn_cache(LWP::ConnCache->new());这个cache是用来保持这个链接的。
$brower->conn_cache->total_capacity(10);这个属性是设置可以cache的链接数,默认只有一个链接。如果传入的参数是undef那么将是没有连接数限制。
Request相关:
$oldval= $browser->agent([agent_string]);这个agent方法主要是用来是设置User-Agentheader,换句话说,你要把你的程序伪装成什么浏览器,就把浏览器的agent拷贝过来,直接传出去就可以了。
$old_address= $browser->from([email_address]);可以设置你的邮件,这个不多说,你回忆一下每当你在浏览网页的时候,点击一个email地址后就会弹出一个邮件编写的程序,那个from的格子,就会被自动你的email_address。
$old_cj_obj= $browser->cookie_jar([cj_obj]);这个罐子就是用来装cookie对象的),其中cookie对象是又HTTP::Cookies生成。其中cookies可以临时使用也可以保存在文件中,这个就看自己的喜好了。
协议相关(protocol):
这里其实就是几个很简单的函数,你允许使用哪些协议、你不允许使用哪些协议、
$aref_maybe= $browser->protocols_allowed([\@protocols])
$aref_maybe= $browser->protocols_forbidden([\@protocols])
重定向问题,以前一直不知道是什么东西,现在总算是搞清楚了,就是访问一个网页的时候,服务器告诉agent网址遭般到了一个新地方,这样agent要看看自己的规则到底自己跟或者不跟下去。这几个函数于上面的协议函数类似:
$aref= $browser->requests_redirectable([\@methods])
$boolean= $browser->redirect_ok(request)
网页认证:
这个认证就是每次登录路由器的哪种认证,不是网页那种异步弹出表单叫你填的那种。
$browser->credentials(“intranet.example.int:80”,”finances”,”fred”,”234234”)
代理服务:
代理服务就是,我们的perl不是直接向目的服务器取我们想要的内容,而是把我们想要的东西通知给代理服务器,然后代理服务器帮我们取了以后,在发送给我们。
$browser->env_proxy();设置代理服务,如果我们没有添加代理服务器的信息就没有效
$browser->proxy(\@scheme,proxy)添加代理服务
$proxy= $browser->proxu(scheme)返回代理服务的信息。
$browser->no_proxy([domain,....])把一些域名加入禁止访问的列表
Request方法:
不用多说,这就就三种方法:
$resp = $browser->get(url)
$resp= $browser->head(url)
$resp= $browser->post(url, \@form_data)
如果我们访问的东西不是一个网页而是一个很大的文件,那么把它放在内存里面就不划算了,这样我们更愿意把它放入硬盘。那么perl提供给我们了一种fakeheader的技术可以帮助我们完成存盘的工作;
$resp= $browser->get(url,':content_file' => filename,...)
$resp= $browser->head(url,':content_file' => filename, …)
$resp= $browser->psot(url, \@form_data,':content_file' =>filename,…)
有时候我们为了更好的封装的效果,我们通常把fetch下来的东西直接传给函数(子例程)处理,perl同样给我们提供了很好的方法:
$resp= $browser->get(url, ':content_cb' =>\&mysub,...)其余几个和上面的三个非常类似。
把一个URL和文件映射下来
$response= $browser->mirror(url_to_get, filename);
这个原理和makefile很相似,如果url_to_get的文件比filename的文件新的话就下载,否着返回失败
上面那一串串函数都是用来处理request的下面我们要看看如何处理response,其实也没有什么好难的,主要是处理content状态码、错误信息、等,我就简要的列出来了。先说说HTTP::Response这个对象,这个对象不是new出来的,而是又UserAgent对象返回的。这里要注意到。
处理状态码statuscode $response->code()
response成功与否$response->is_success()
状态行$response->status_line()是由statuscode和message构成
返回解释信息$response->message()
返回正文内容$response->content()
返回正文的引用,注意,这里和c++的引用观点有点相似,引用第一节约了空间,第二节约了拷贝的时间。$data_ref= $response->content_ref()
获取header:$value= $response->header(header_name)
里面有很多很多,选择你自己感兴趣的获取,eg:
$response->header('Description')
返回content_type注意这里返回的是MIME类型或者是其子类型
$type= $response->content_type()
返回content长度$conten_length(),通常这是不靠谱的
返回上次修改的时间戳$lm= $response->last_modified()
返回编码方式$encoding= $response->content_encoding()
返回发送文件使用的时间$age= $response->current_age()
返回还有好久该文件到期$lifetime= $response->freshness_lifetime()
确定该文件是否到期$boolean= $response->is_fresh()
返回什么时候文件到期$expires= $response->fresh_until()
注意上面关于时间的全都是秒数,还要通过相关的本地函数把他们转换成时间、小时、天等
返回URL的绝对地址$url= $response->base()
我们在访问一个网址时,服务器可能通知我们,我们要访问的网页已经般到了其他地方去了,所以我们等重定向一下,我们要跳到下一个网页,这样我们在访问一个网页的时候我们可能要重定向很多次。这个过程就像我们是在有一个链上行走一样,最后达到了我们想要的网址。perl给我们提供了一个强大的函数,我们不知可以一直往前面走我们还可以倒退。
$previous_response= $response->previous()
这样我们还可以沿着redirection走回来。
-
URLs组成于操作
这一页更加细致的讲解了URL的组成和基本的作用,下面是一张摘要图:
http://joeshome@stuff.int:8012/hooboy/things.html?yikes=3#results
scheme user info host port path query fragment
很容易看出来我们的URL是由那几部分组成的,但是要注意的是对于一些scheme一些部分是没有的。
为了对其很方便的操作,perl给我们提供了一个很方便的类。Use URI;
$uri= URI->new($url)这样我们就可以使用对象里面大量的方法操作URL了,请记住千万不要重复的发明轮子。
有scheme()userinfo() host() port() path() query()这些方法,一看就明了了。
-
绝对URL和相对URL之间的转换
这个小节没有什么好记录的,主要有两个方法是用来相对转绝对,绝对转相对的。
$relative= $absolute_goal->rel(absolute_base);
$abs_url= URI->new_abs(relative,base);
一看就知道干什么的。
-
Form
拿到一个form我们首先要看得就是使用的是什么方法POSTor GET,然后看action部分是哪一个URL接收这个参数,最后要看的就是输入区域,到底我们应该输入些什么。
----------------------------------------------------------------------------------------------
<form method=get action =/cgi-bin/gazetteer> 告诉我们使用的是get方法
<hr noshade>
<h3>
<font size=+2>S</font>each for a <font size=+2>P</font>lace in the
<font size=+2>US</font>
</h3>
<p>
Name:<input name="city" size=15> 这里就是要输入的东西
State (optional):<input name="state" size=3><br>
or a 5-digit zip code:<input name="zip" size=8>
<p>
<input type="submit" value="Search">
</form>
---------------------------------------------------------------------------------------------- -
GET 与query_form()
在处理GET访问的时候如果使用硬编码非常麻烦,这是我们可以使用URI生成的url对象来实现很复杂的表单编码
$url_obj= URI->new($your_url);
$url_obj->query_form(...);
然后就可一使用UserAgent对象来操作了。
-
Cookie
刚开始的时候觉得cookie很烦,但是其实很是被设计得多简单的,只要在申请的UserAgent对象把cookie开启就行了,其他的perl就帮我们负责管了
$browser= LWP::UserAgent->new();
$brwoser->cookie_jar();打开cookie
$response= ….按你自己的步骤访问网页