- 浏览: 530867 次
- 性别:
- 来自: 青岛
文章分类
- 全部博客 (222)
- 帖子来的 (3)
- JavaScript (25)
- Java (10)
- DataBase (2)
- el表达式 (1)
- html (4)
- FCKEDITOR和TINYMCE (3)
- tomcat (5)
- JavaEE (12)
- Eclipse (7)
- Windows (3)
- Dos命令 (1)
- Oracle (20)
- 乱搞 (1)
- AHK (3)
- TC (2)
- vim (12)
- Perl (13)
- ANT (6)
- Android (3)
- antlr (1)
- SSH (14)
- C/C++ (3)
- wordpress (4)
- CSS (3)
- java2D (1)
- Lucene (4)
- Linux (9)
- jquery (4)
- testsomething (7)
- JVM监控优化 (3)
- emacs (4)
- svn cvs版本控制 (2)
- 硬件 (1)
- j2me (2)
- maven (5)
- WebService (4)
- aspectJ (1)
- 算法 (2)
- mysql (1)
- project (2)
- 正则表达式 (2)
- firefox (1)
最新评论
-
直觉:
gua 顶
com.opensymphony.xwork2.inject.DependencyException -
fordfelix:
加了以后 任然存在这个异常 求解!!
struts2 json 插件 @JSON(serialize = false) -
fangyan_oracle:
谢谢了, 很受用
用IE修改当前页面内容的代码zzzz -
cfying:
[flash=200,200][/flash][url][/u ...
精解window.setTimeout()使用方式与参数传递问题!(转) -
qinglangee:
tiewazi 写道param必须是全局变量(即window对 ...
精解window.setTimeout()使用方式与参数传递问题!(转)
ref:LWP 与 WEB 的基本使用
简介
LWP (“Library for WWW in Perl” 的缩写) 是一个由多个模块组成,用来获取网络数据的的模块组。 和很多 Perl 的模块一样。每一个 LWP 模块都自带详细的文档,做为对这个模块的完整介绍。可是面对 LWP 里的众多模块,有时候即使是完成最简单的工作,新手们也常常不知道从那里开始。
要对 LWP 做全面的介绍需要一整本书,很幸运,Perl & LWP 已经出版。而这篇文章向你介绍了最常见的 LWP 用法。
使用 LWP::Simple 获取网页
如果只是要拿到某个网页,那使用 LWP::Simple 里的函数是最简单的。
通过调用 get($url) 函数,就可以得到相关网址的内容。如果没有发生错误,get 函数返回此网页,否则,返回 undef。例子如下:
如果要在命令行里运行,getprint 函数非常方便。如果没有发生错误,它会把网页内容输出到 STDOUT,否则将会有错误信息输出到 STDERR。 例如:
上面的网址指向一个文本文件,列有最近两个星期内 CPAN 更新过的文件。如果想要知道 Acme:: 的模块是否有更新,有就email 自己,你可以把它和 Shell 结合到一起来实现。如下:
LWP::Simple 还有一些非常有用的函数,包括一个运行HEAD请求的函数,用来检查链接是否有效,网页是否更新。另外两个用来保存和镜像网址的函数也值得一提。具体请看 LWP::Simple 的文档或 Perl & LWP 的第二章.
LWP Class 模型基础
LWP::Simple 在做简单的工作时很方便。但因为不支持 cookies,用户认证,对 HTTP request header (请求标头)的编辑,和 HTTP resonse header(响应标头)的读写(主要是 HTTP 的 error message)。因此,当需要这些特性的时候,就要使用 LWP Class 模型。
在众多的 LWP Class 里,LWP::UserAgent 和 HTTP::Response 是必须理解的。LWP::UserAgent 就像一个虚拟浏览器用来作 request (请求)。HTTP::Response 用来储存 request (请求) 生成的 response(响应)。
最基本的用法是 $response = $browser->get($url), 或写的更完整些 :
# 程序开始:
上面有两个相关的 object: $browser,是 LWP::UserAgent 的一个object。$response 是属于 HTTP::Response 类的一个object。一个程序里只需要一个 $browser object,但是每次发出一个 request,就会得到一个新的 HTTP::Response object。
HTTP::Response object 有以下一些有价值的属性:
* 一个 status code(状态代码值),表示成功或失败。你可以使用 $response->is_success 来检测它。
* http status line(http 状态描述),观察 $response->status_line 的结果 ( 比如 “404 Not Found” ) 会帮助你理解这个词的意思。
* MIME content-type(文件类型)通过 $response->content_type 来获得。例如 “text/html”,”image/gif”,”application/xml” 等等。
* content of the response(响应返回的内容)储存在 $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 加上其他 HTTP headers。象这样 :
$response = $browser->get( $url, $key1, $value1, $key2, $value2, ... );
举个例子,如果你要对一个只允许 Netscape 浏览器连入的网站发出请求,那就需要发出类似 Netscape 的 header,如下:
如果不打算重复使用这个 array,你可以把它写到 get 函数里
如果只是打算修改 User-Agent,可以通过 LWP::UserAgent 的 agent 方法把缺省的agent ‘libwww-perl/5.65’(或者别的)改掉。
使用 cookies
默认的LWP::UserAgent对象像一个不支持cookies的浏览器一样工作。有不只一种的办法可以设定它的cookie_jar属性,从而让它支持cookies。“cookie jar” 是一个用来储存 HTTP cookie 的容器。你可以把它存到硬盘(像Netscape使用cookies.txt一样)或内存里。存到内存里的 cookies 会在程序完成后消失。
内存式的 cookie 使用方法:
也可以把 cookie 储存到硬盘的文件里:
文件里的 cookie 是以 LWP 自定的格式储存,如果你想在 netscape 里使用这个 cookie 文件,可以使用 HTTP::Cookies::Netscape class :
你也可以象上面一样使用 ‘autosave’ => 1 。 但 Netscape 的 cookie 有时会在写入硬盘之前就被丢掉,至少在写这篇文章的时候还是这样。
通过 POST提交表格
大部分HTML表格使用HTML POST 向服务器提交数据,在这里你可以这样:
或者你也可以把 HTTP header 也一起发出
下一个例子向 AltaVista 的搜索引擎发送 HTTP POST 请求,然后从HTML里提取出符合匹配的总数。
通过 GET 提交表格
一些HTML表格不使用 POST 请求,而是使用 GET 请求来传输数据。例如,在 imdb.com 里检索电影名字 ‘Blade Runner’, 提交后在浏览器的网址栏里将显示 :
http://us.imdb.com/Tsearch?title=Blade%20Runner&restrict=Movies+and+TV
下面是使用 LWP 实现同样的结果 :
第5章详细描述了 HTML 表格和表格数据,第6章到第9章描述了怎样从获得的HTML数据里提取出有用的信息。
URL 处理
上面提到的 URI class 提供很多获取和修改 URL 的方法。例如 如果想要知道 url 是什么类型 (http, ftp 等等) 可以使用 $url->schema 来得到,如果要提取网址里的主机名,可以使用 $url->host。不过,可能最有用的是我前面提到的 query_form 方法,以及把相对网址路径(如”../foo.html”)转换成绝对路径(如”http: //www.perl.com/stuff/foo.html”)的 new_abs 方法。例子如下:
use URI;
$abs = URI->new_abs($maybe_relative, $base);
>现在回忆一下获取最新 CPAN 模块的那个例子。
输出的结果是
MIRRORING.FROM
RECENT
RECENT.html
authors/00whois.html
authors/01mailrc.txt.gz
authors/id/A/AA/AASSAD/CHECKSUMS
...
你可以使用 URI 模块的 new_abs 方法来得到完全网址路径,修改 while 循环:
$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 的第四章,以得到对 URI objects 更详细的描述。
当然,使用 regexp (正则表达式) 来匹配 url 相对简单,如果情况复杂,需要更强大的匹配工具,可以考虑 HTML 分析模块 HTML::LinkExtor 或 HTML::TokeParser,甚至 HTML::TreeBuilder
其他浏览器属性
LWP::UserAgent objects 有几个值得注意的属性 :
* $browser->timeout(15): 设定缺省 request 的 timeout 时间.超过这个时间就放弃请求。
* $browser->protocols_allowed( [ ‘http’, ‘gopher’] ): 这用来设定只接受 http 和 gopher 协议。连接其他协议时就返回 500 错误值,”Access to ftp URIs has been disabled” 的错误消息。
* use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()): 这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性,即重复使用先前的 socket 来加快请求速度。
* $browser->agent( ‘SomeName/1.23 (more info here maybe)’ ): 设置 HTTP 请求的 User-Agent。LWP 缺省使用 “libwww-perl/versionnumber” 作为 User-Agent,比如 “libwww-perl/5.65”。你可以加上更多的信息:
或者可以伪装为
* push @{ $ua->requests_redirectable }, ‘POST’: 告诉 LWP 在 POST 请求发送后如果发生重新定向就自动跟随 ( 虽然 RFC 里不要求这么做 )
详细请参见 LWP::UserAgent 文档.
写一个有礼貌的机器人
如果想遵循 robots.txt 和避免在较短的时间发出太多的请求,你可以采用 LWP::RobotUA 而不是 LWP::UserAgent。
LWP::RobotUA 用法与 LWP::UserAgent 一样:
HTTP::RobotUA 多了几个特性:
* 如果 $url 请求的服务器的 robots.txt 禁止了你对 $url的访问,那么 $browser 就不会发出对于这个地址的请求,而是返回 403 代码和一个错误信息 “Forbidden by robots.txt”。
然后你会得到这样的错误信息:
http://whatever.site.int/pith/x.html -- 403 Forbidden
by robots.txt
Aborted at whateverprogram.pl line 1234
* 如果 $browser 发现请求的地址是刚刚请求过的,就会暂停 (sleep) 来避免发送太多的请求。缺省暂停 1 分钟,但可以通过 $browser->delay( minutes ) 来设定。比如:
$browser->delay( 7/60 );
详细请参见 LWP::RobotUA文档.
使用代理
有时你希望(或者是必须)通过代理来连接某些站点或协议,就比如你的LWP程序是运行在某台处于防火墙之内的机器上。
代理通常储存在环境变量 HTTP_PROXY 里。LWP 可以通过 user-agent object 里的 env_proxy 函数把环境变量里的代理地址装载。
详细请参照 LWP::UserAgent 文档里的 proxy, env_proxy 和 no_proxy 方法.
HTTP 认证
许多网站都是通过 HTTP 认证来限制连接. 当用户请求一个限制页面时, HTTP 服务器回复 “That document is part of a protected ‘realm’ and you can access it only if you re-request it and add some special authorization headers to your request”. ( 你现在请求了一个限制区域 , 如果你需要重新发送一个带有认证信息的 header 才可以连入. )
Unicode.org 的管理员为了防止机器人访问邮件组获取发信人地址,要求先进行 HTTP 认证。用户名和密码是公开的:用户名: unicode-ml 密码: unicode
假设一个限制页面的地址是
http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
如果你在浏览器里请求这个地址,一个新的窗口跳出,显示 “Enter username and password for ‘Unicode-MailList-Archives’ at server ‘www.unicode.org’”。请你输入用户名和密码,就像这样:
单纯使用 LWP 请求这个网址 :
你将得到以下错误:
Error: Basic realm="Unicode-MailList-Archives"
401 Authorization Required
at http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
Aborting at auth1.pl line 9. [or wherever]
这是因为 LWP 不知道 host www.unicode.org 里的 “Unicode-MailList-Archives” 区的用户名和地址。解决这个问题最简单的方法是使用 credentials 方法来提供用户名和密码:
通常, 端口是 80. credentials 函数要在发请求之前调用.比如:
我们的 unicode.org 的例子可以写成
连接 HTTPs URLs
只要有安装 LWP 的HTTPs 的支持, 访问 HTTPs URLs 的方法和 HTTP 一样
如果没有 HTTPs 的支持, 如下错误信息会显示
Error at https://www.paypal.com/
501 Protocol scheme 'https' is not supported
Aborting at paypal.pl line 7. [or whatever program and line]
如果你安装了 LWP 的 HTTPS 支持的话,你的请求应该是成功的,你可以像对待普通的 HTTP 请求一样处理 $response 对象。
关于安装 HTTPS 支持的信息可以在libwww-perl 里的README.SSL 文件找到.
获取大文件
请求较大的文件时, 普通的请求方法 ( 例如 $response = $browser->get($url) ) 会给你带来内存问题. 因为 $response 储存着整个文件. 如果请求了一个 30MB 的文件, 那可能不是什么明智的做法.
一个解决方法是把文件存到硬盘
比如:
当使用 content_file 时, headers 还是在$response, 但$response->content 是空.
值得注意的是LWP 5.66 之前的版本不支持content_file . 你应该使用 use LWP 5.66; 如果你的程序可能运行在低版本的 LWP 上, 你也可以使用下面的例子来保证兼容性, 这与 content_file 有同样效果.
资源
以上只是对 LWP 常用函数的简介, 如果想了解更多关于 LWP 和 LWP 相关的东西, 请参阅以下文档
* LWP::Simple: 提供简易的 get, head, mirror 方法.
* LWP: libwww-perl 模块的综述
* HTTP::Response: 发出 LWP 请求后所得到的响应 , $response = $browser->get(...).
* HTTP::Message and HTTP::Headers: HTTP::Response 很多方法都是来自两者.
* URI: Class 处理完全和相对网址路径.
* URI::Escape: 来正确处理和转换 URL 里的不规则字符 (比如 “this & that” 和 “this%20%26%20that” 之间的转换).
* HTML::Entities: 来正确处理和转换 HTML 里的不规则字符 (比如 “C. & E. Bront??” 和 “C. & E. Bront??” 之间的转换).
* HTML::TokeParser and HTML::TreeBuilder: Classes 分析 HTML
* HTML::LinkExtor: Class :在 HTML 找到链接
* 当然还有我的 Perl & LWP.
与 Sean Burke 讨论后的一些笔记
在翻译这篇文章的时候,我联系到了文章作者, Sean Burke. 他同意把原文章
>现在回忆一下获取最新 CPAN 模块的那个例子。
输出的结果是
MIRRORING.FROM
RECENT
RECENT.html
authors/00whois.html
authors/01mailrc.txt.gz
authors/id/A/AA/AASSAD/CHECKSUMS
...
你可以使用 URI 模块的 new_abs 方法来得到完全网址路径,修改 while 循环:
$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 的第四章,以得到对 URI objects 更详细的描述。
当然,使用 regexp (正则表达式) 来匹配 url 相对简单,如果情况复杂,需要更强大的匹配工具,可以考虑 HTML 分析模块 HTML::LinkExtor 或 HTML::TokeParser,甚至 HTML::TreeBuilder
其他浏览器属性
LWP::UserAgent objects 有几个值得注意的属性 :
* $browser->timeout(15): 设定缺省 request 的 timeout 时间.超过这个时间就放弃请求。
* $browser->protocols_allowed( [ ‘http’, ‘gopher’] ): 这用来设定只接受 http 和 gopher 协议。连接其他协议时就返回 500 错误值,”Access to ftp URIs has been disabled” 的错误消息。
* use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()): 这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性,即重复使用先前的 socket 来加快请求速度。
* $browser->agent( ‘SomeName/1.23 (more info here maybe)’ ): 设置 HTTP 请求的 User-Agent。LWP 缺省使用 “libwww-perl/versionnumber” 作为 User-Agent,比如 “libwww-perl/5.65”。你可以加上更多的信息:
$browser->agent( ‘SomeName/3.14 (contact@robotplexus.int)’ );
或者可以伪装为
* push @{ $ua->requests_redirectable }, ‘POST’: 告诉 LWP 在 POST 请求发送后如果发生重新定向就自动跟随 ( 虽然 RFC 里不要求这么做 )
详细请参见 LWP::UserAgent 文档.
写一个有礼貌的机器人
如果想遵循 robots.txt 和避免在较短的时间发出太多的请求,你可以采用 LWP::RobotUA 而不是 LWP::UserAgent。
LWP::RobotUA 用法与 LWP::UserAgent 一样:
HTTP::RobotUA 多了几个特性:
* 如果 $url 请求的服务器的 robots.txt 禁止了你对 $url的访问,那么 $browser 就不会发出对于这个地址的请求,而是返回 403 代码和一个错误信息 “Forbidden by robots.txt”。
然后你会得到这样的错误信息:
http://whatever.site.int/pith/x.html -- 403 Forbidden
by robots.txt
Aborted at whateverprogram.pl line 1234
* 如果 $browser 发现请求的地址是刚刚请求过的,就会暂停 (sleep) 来避免发送太多的请求。缺省暂停 1 分钟,但可以通过 $browser->delay( minutes ) 来设定。比如:
$browser->delay( 7/60 );
详细请参见 LWP::RobotUA文档.
使用代理
有时你希望(或者是必须)通过代理来连接某些站点或协议,就比如你的LWP程序是运行在某台处于防火墙之内的机器上。
代理通常储存在环境变量 HTTP_PROXY 里。LWP 可以通过 user-agent object 里的 env_proxy 函数把环境变量里的代理地址装载。
详细请参照 LWP::UserAgent 文档里的 proxy, env_proxy 和 no_proxy 方法.
HTTP 认证
许多网站都是通过 HTTP 认证来限制连接. 当用户请求一个限制页面时, HTTP 服务器回复 “That document is part of a protected ‘realm’ and you can access it only if you re-request it and add some special authorization headers to your request”. ( 你现在请求了一个限制区域 , 如果你需要重新发送一个带有认证信息的 header 才可以连入. )
Unicode.org 的管理员为了防止机器人访问邮件组获取发信人地址,要求先进行 HTTP 认证。用户名和密码是公开的:用户名: unicode-ml 密码: unicode
假设一个限制页面的地址是
http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
如果你在浏览器里请求这个地址,一个新的窗口跳出,显示 “Enter username and password for ‘Unicode-MailList-Archives’ at server ‘www.unicode.org’”。请你输入用户名和密码,就像这样:
单纯使用 LWP 请求这个网址 :
你将得到以下错误:
Error: Basic realm="Unicode-MailList-Archives"
401 Authorization Required
at http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
Aborting at auth1.pl line 9. [or wherever]
这是因为 LWP 不知道 host www.unicode.org 里的 “Unicode-MailList-Archives” 区的用户名和地址。解决这个问题最简单的方法是使用 credentials 方法来提供用户名和密码:
通常, 端口是 80. credentials 函数要在发请求之前调用.比如:
我们的 unicode.org 的例子可以写成
连接 HTTPs URLs
只要有安装 LWP 的HTTPs 的支持, 访问 HTTPs URLs 的方法和 HTTP 一样
如果没有 HTTPs 的支持, 如下错误信息会显示
Error at https://www.paypal.com/
501 Protocol scheme 'https' is not supported
Aborting at paypal.pl line 7. [or whatever program and line]
如果你安装了 LWP 的 HTTPS 支持的话,你的请求应该是成功的,你可以像对待普通的 HTTP 请求一样处理 $response 对象。
关于安装 HTTPS 支持的信息可以在libwww-perl 里的README.SSL 文件找到.
获取大文件
请求较大的文件时, 普通的请求方法 ( 例如 $response = $browser->get($url) ) 会给你带来内存问题. 因为 $response 储存着整个文件. 如果请求了一个 30MB 的文件, 那可能不是什么明智的做法.
一个解决方法是把文件存到硬盘
比如:
当使用 content_file 时, headers 还是在$response, 但$response->content 是空.
值得注意的是LWP 5.66 之前的版本不支持content_file . 你应该使用 use LWP 5.66; 如果你的程序可能运行在低版本的 LWP 上, 你也可以使用下面的例子来保证兼容性, 这与 content_file 有同样效果.
use HTTP::Request::Common;
$response = $ua->request( GET($url), $filespec );
资源
以上只是对 LWP 常用函数的简介, 如果想了解更多关于 LWP 和 LWP 相关的东西, 请参阅以下文档
* LWP::Simple: 提供简易的 get, head, mirror 方法.
* LWP: libwww-perl 模块的综述
* HTTP::Response: 发出 LWP 请求后所得到的响应 , $response = $browser->get(...).
* HTTP::Message and HTTP::Headers: HTTP::Response 很多方法都是来自两者.
* URI: Class 处理完全和相对网址路径.
* URI::Escape: 来正确处理和转换 URL 里的不规则字符 (比如 “this & that” 和 “this%20%26%20that” 之间的转换).
* HTML::Entities: 来正确处理和转换 HTML 里的不规则字符 (比如 “C. & E. Bront??” 和 “C. & E. Bront??” 之间的转换).
* HTML::TokeParser and HTML::TreeBuilder: Classes 分析 HTML
* HTML::LinkExtor: Class :在 HTML 找到链接
* 当然还有我的 Perl & LWP.
与 Sean Burke 讨论后的一些笔记
在翻译这篇文章的时候,我联系到了文章作者, Sean Burke. 他同意把原文章 >现在回忆一下获取最新 CPAN 模块的那个例子。
输出的结果是
MIRRORING.FROM
RECENT
RECENT.html
authors/00whois.html
authors/01mailrc.txt.gz
authors/id/A/AA/AASSAD/CHECKSUMS
...
你可以使用 URI 模块的 new_abs 方法来得到完全网址路径,修改 while 循环:
$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 的第四章,以得到对 URI objects 更详细的描述。
当然,使用 regexp (正则表达式) 来匹配 url 相对简单,如果情况复杂,需要更强大的匹配工具,可以考虑 HTML 分析模块 HTML::LinkExtor 或 HTML::TokeParser,甚至 HTML::TreeBuilder
其他浏览器属性
LWP::UserAgent objects 有几个值得注意的属性 :
* $browser->timeout(15): 设定缺省 request 的 timeout 时间.超过这个时间就放弃请求。
* $browser->protocols_allowed( [ ‘http’, ‘gopher’] ): 这用来设定只接受 http 和 gopher 协议。连接其他协议时就返回 500 错误值,”Access to ftp URIs has been disabled” 的错误消息。
* use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()): 这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性,即重复使用先前的 socket 来加快请求速度。
* $browser->agent( ‘SomeName/1.23 (more info here maybe)’ ): 设置 HTTP 请求的 User-Agent。LWP 缺省使用 “libwww-perl/versionnumber” 作为 User-Agent,比如 “libwww-perl/5.65”。你可以加上更多的信息:
或者可以伪装为
* push @{ $ua->requests_redirectable }, ‘POST’: 告诉 LWP 在 POST 请求发送后如果发生重新定向就自动跟随 ( 虽然 RFC 里不要求这么做 )
详细请参见 LWP::UserAgent 文档.
写一个有礼貌的机器人
如果想遵循 robots.txt 和避免在较短的时间发出太多的请求,你可以采用 LWP::RobotUA 而不是 LWP::UserAgent。
LWP::RobotUA 用法与 LWP::UserAgent 一样:
HTTP::RobotUA 多了几个特性:
* 如果 $url 请求的服务器的 robots.txt 禁止了你对 $url的访问,那么 $browser 就不会发出对于这个地址的请求,而是返回 403 代码和一个错误信息 “Forbidden by robots.txt”。
die "$url -- ", $response->status_line, "\nAborted"
unless $response->is_success;
然后你会得到这样的错误信息:
http://whatever.site.int/pith/x.html -- 403 Forbidden
by robots.txt
Aborted at whateverprogram.pl line 1234
* 如果 $browser 发现请求的地址是刚刚请求过的,就会暂停 (sleep) 来避免发送太多的请求。缺省暂停 1 分钟,但可以通过 $browser->delay( minutes ) 来设定。比如:
$browser->delay( 7/60 );
详细请参见 LWP::RobotUA文档.
使用代理
有时你希望(或者是必须)通过代理来连接某些站点或协议,就比如你的LWP程序是运行在某台处于防火墙之内的机器上。
代理通常储存在环境变量 HTTP_PROXY 里。LWP 可以通过 user-agent object 里的 env_proxy 函数把环境变量里的代理地址装载。
详细请参照 LWP::UserAgent 文档里的 proxy, env_proxy 和 no_proxy 方法.
HTTP 认证
许多网站都是通过 HTTP 认证来限制连接. 当用户请求一个限制页面时, HTTP 服务器回复 “That document is part of a protected ‘realm’ and you can access it only if you re-request it and add some special authorization headers to your request”. ( 你现在请求了一个限制区域 , 如果你需要重新发送一个带有认证信息的 header 才可以连入. )
Unicode.org 的管理员为了防止机器人访问邮件组获取发信人地址,要求先进行 HTTP 认证。用户名和密码是公开的:用户名: unicode-ml 密码: unicode
假设一个限制页面的地址是
http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
如果你在浏览器里请求这个地址,一个新的窗口跳出,显示 “Enter username and password for ‘Unicode-MailList-Archives’ at server ‘www.unicode.org’”。请你输入用户名和密码,就像这样:
单纯使用 LWP 请求这个网址 :
你将得到以下错误:
Error: Basic realm="Unicode-MailList-Archives"
401 Authorization Required
at http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
Aborting at auth1.pl line 9. [or wherever]
这是因为 LWP 不知道 host www.unicode.org 里的 “Unicode-MailList-Archives” 区的用户名和地址。解决这个问题最简单的方法是使用 credentials 方法来提供用户名和密码:
通常, 端口是 80. credentials 函数要在发请求之前调用.比如:
我们的 unicode.org 的例子可以写成
连接 HTTPs URLs
只要有安装 LWP 的HTTPs 的支持, 访问 HTTPs URLs 的方法和 HTTP 一样
如果没有 HTTPs 的支持, 如下错误信息会显示
Error at https://www.paypal.com/
501 Protocol scheme 'https' is not supported
Aborting at paypal.pl line 7. [or whatever program and line]
如果你安装了 LWP 的 HTTPS 支持的话,你的请求应该是成功的,你可以像对待普通的 HTTP 请求一样处理 $response 对象。
关于安装 HTTPS 支持的信息可以在libwww-perl 里的README.SSL 文件找到.
获取大文件
请求较大的文件时, 普通的请求方法 ( 例如 $response = $browser->get($url) ) 会给你带来内存问题. 因为 $response 储存着整个文件. 如果请求了一个 30MB 的文件, 那可能不是什么明智的做法.
一个解决方法是把文件存到硬盘
比如:
当使用 content_file 时, headers 还是在$response, 但$response->content 是空.
值得注意的是LWP 5.66 之前的版本不支持content_file . 你应该使用 use LWP 5.66; 如果你的程序可能运行在低版本的 LWP 上, 你也可以使用下面的例子来保证兼容性, 这与 content_file 有同样效果.
资源
以上只是对 LWP 常用函数的简介, 如果想了解更多关于 LWP 和 LWP 相关的东西, 请参阅以下文档
* LWP::Simple: 提供简易的 get, head, mirror 方法.
* LWP: libwww-perl 模块的综述
* HTTP::Response: 发出 LWP 请求后所得到的响应 , $response = $browser->get(...).
* HTTP::Message and HTTP::Headers: HTTP::Response 很多方法都是来自两者.
* URI: Class 处理完全和相对网址路径.
* URI::Escape: 来正确处理和转换 URL 里的不规则字符 (比如 “this & that” 和 “this%20%26%20that” 之间的转换).
* HTML::Entities: 来正确处理和转换 HTML 里的不规则字符 (比如 “C. & E. Bront??” 和 “C. & E. Bront??” 之间的转换).
* HTML::TokeParser and HTML::TreeBuilder: Classes 分析 HTML
* HTML::LinkExtor: Class :在 HTML 找到链接
* 当然还有我的 Perl & LWP.
与 Sean Burke 讨论后的一些笔记
在翻译这篇文章的时候,我联系到了文章作者, Sean Burke. 他同意把原文章
里需要补充和更新的地方指出. 我与作者也通过 MSN 交流了一下. 这里我把自己对 LWP 的理解和作者的补充写在这里.
* 在文章里提到了使用
这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性, 即重复使用先前的 socket 来加快请求速度.
你也可以在 new LWP::UserAgent 时为 $browser 加上 “keep-Alive” 特性, 如下
* 不要忘记 response object 的 header 通常有很多非常值得注意的信息, 你可以通过 headers_as_string 和 as_string 函数来得到. 下面是使用 headers_as_string 返回的例子
输出结果:
Cache-Control: private, max-age=0
Connection: close
Date: Sun, 16 Jan 2005 04:18:26 GMT
Server: Microsoft-IIS/6.0
Content-Length: 432
Content-Type: text/html
Content-Type: text/html; charset=iso8859-1
Client-Date: Sun, 16 Jan 2005 04:18:09 GMT
Client-Peer: 207.61.136.40:80
Client-Response-Num: 1
REFRESH: 0;URL=http://www.pulse24.com/Front_Page/page.asp
X-Meta-Robots: noindex
X-Powered-By: ASP.NET
你也可以通过 $response->header(‘field’) 来获得想要的特别 header. 象上面的例子, 如果要访问的网页使用了 meta refresh :
<META HTTP-EQUIV="REFRESH" CONTENT="0;URL=http://www.pulse24.com/Front_Page/page.asp">
你可以使用 $response->header(‘refresh’) 来拿到 refresh 的 url 地址, 选择是否继续跟进.
* 有些时候, 浏览器可以正常访问到的地址, LWP 却不行. 一般是因为你的 LWP 的 header, referer , cookie 或 user-agent 等的设定与对方网络服务器允许连入的不同. 为了找到问题所在, 你需要比较浏览器发出的请求和你的 LWP 发出的请求有何不同, 然后修改再尝试. 很多时候这是反反复复的工作. 我最早使用 Ethereal 来监视,抓取数据, 目前使用 Firefox 的 LiveHTTPHeaders 插件. 现在LWP 也自带一个数据分析模块 LWP::DebugFile 来帮助你找到问题.
* 另外, 文章里提到了 HTTP::Cookies::Netscape , 现在LWP Cookies 模块支持更多浏览器 Mozilla , Safari , Omniweb
* 很多时候表格与 javascript 一起使用, LWP 没有分析 Javascript 的引擎,所以你必须分析网页源码里 Javascript 来决定怎样处理.
上面的这个例子通过表格提交来触动 javascript 的 submit 函数, 最后调用了 verify.php. 现在你就可以跳过所有的 javascript 而直接对 verify.php 来提交.
上面的这个例子通过表格提交来触动 javascript 的 submit 函数, 最后调用了 verify.php. 现在你就可以跳过所有的 javascript 而直接对 verify.php 来提交.
简介
LWP (“Library for WWW in Perl” 的缩写) 是一个由多个模块组成,用来获取网络数据的的模块组。 和很多 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' use LWP::Simple; my $content = get $url; die "Couldn't get $url" unless defined $content; # $content 里是网页内容,下面是对此内容作些分析: if($content =~ m/jazz/i) { print "They're talking about jazz today on Fresh Air!\n"; } else { print "Fresh Air is apparently jazzless today.\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 "New Acme modules! Joy!" $USER
LWP::Simple 还有一些非常有用的函数,包括一个运行HEAD请求的函数,用来检查链接是否有效,网页是否更新。另外两个用来保存和镜像网址的函数也值得一提。具体请看 LWP::Simple 的文档或 Perl & LWP 的第二章.
LWP Class 模型基础
LWP::Simple 在做简单的工作时很方便。但因为不支持 cookies,用户认证,对 HTTP request header (请求标头)的编辑,和 HTTP resonse header(响应标头)的读写(主要是 HTTP 的 error message)。因此,当需要这些特性的时候,就要使用 LWP Class 模型。
在众多的 LWP Class 里,LWP::UserAgent 和 HTTP::Response 是必须理解的。LWP::UserAgent 就像一个虚拟浏览器用来作 request (请求)。HTTP::Response 用来储存 request (请求) 生成的 response(响应)。
最基本的用法是 $response = $browser->get($url), 或写的更完整些 :
# 程序开始:
use LWP 5.64; # 载入较新版本的 LWP classes my $browser = LWP::UserAgent->new; ... # get request: my $url = 'http://freshair.npr.org/dayFA.cfm?todayDate=current'; my $response = $browser->get( $url ); die "Can't get $url -- ", $response->status_line unless $response->is_success; die "Hey, 我想要 HTML 格式而不是 ", $response->content_type unless $response->content_type eq 'text/html'; # 或者任何其他的 content-type # 成功的话就对内容处理 if($response->content =~ m/jazz/i) { print "Fresh Air 今天在讨论爵士乐!\n"; } else { print "Fresh Air 今天讨论的和爵士乐一点边都不沾.\n"; }
上面有两个相关的 object: $browser,是 LWP::UserAgent 的一个object。$response 是属于 HTTP::Response 类的一个object。一个程序里只需要一个 $browser object,但是每次发出一个 request,就会得到一个新的 HTTP::Response object。
HTTP::Response object 有以下一些有价值的属性:
* 一个 status code(状态代码值),表示成功或失败。你可以使用 $response->is_success 来检测它。
* http status line(http 状态描述),观察 $response->status_line 的结果 ( 比如 “404 Not Found” ) 会帮助你理解这个词的意思。
* MIME content-type(文件类型)通过 $response->content_type 来获得。例如 “text/html”,”image/gif”,”application/xml” 等等。
* content of the response(响应返回的内容)储存在 $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 加上其他 HTTP headers。象这样 :
$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。“cookie jar” 是一个用来储存 HTTP cookie 的容器。你可以把它存到硬盘(像Netscape使用cookies.txt一样)或内存里。存到内存里的 cookies 会在程序完成后消失。
内存式的 cookie 使用方法:
$browser->cookie_jar({});
也可以把 cookie 储存到硬盘的文件里:
use HTTP::Cookies; $browser->cookie_jar( HTTP::Cookies->new( 'file' => '/some/where/cookies.lwp', # 储存 cookies 的地址 'autosave' => 1, # 当完成后自动储存到硬盘里 ));
文件里的 cookie 是以 LWP 自定的格式储存,如果你想在 netscape 里使用这个 cookie 文件,可以使用 HTTP::Cookies::Netscape class :
use HTTP::Cookies; # yes, loads HTTP::Cookies::Netscape too $browser->cookie_jar( HTTP::Cookies::Netscape->new( 'file' => 'c:/Program Files/Netscape/Users/DIR-NAME-HERE/cookies.txt', # where to read cookies ));
你也可以象上面一样使用 ‘autosave’ => 1 。 但 Netscape 的 cookie 有时会在写入硬盘之前就被丢掉,至少在写这篇文章的时候还是这样。
通过 POST提交表格
大部分HTML表格使用HTML POST 向服务器提交数据,在这里你可以这样:
$response = $browser->post( $url, [ formkey1 => value1, formkey2 => value2, ... ], );
或者你也可以把 HTTP header 也一起发出
$response = $browser->post( $url, [ formkey1 => value1, formkey2 => value2, ... ], headerkey1 => value1, headerkey2 => value2, );
下一个例子向 AltaVista 的搜索引擎发送 HTTP POST 请求,然后从HTML里提取出符合匹配的总数。
use strict; use warnings; use LWP 5.64; my $browser = LWP::UserAgent->new; my $word = 'tarragon'; my $url = 'http://www.altavista.com/sites/search/web'; my $response = $browser->post( $url, [ 'q' => $word, # the Altavista query string 'pg' => 'q', 'avkw' => 'tgz', 'kl' => 'XX', ] ); die "$url error: ", $response->status_line unless $response->is_success; die "Weird content type at $url -- ", $response->content_type unless $response->content_type eq 'text/html'; if( $response->content =~ m{AltaVista found ([0-9,]+) results} ) { # 从 "AltaVista found 2,345 results" 里匹配出结果 print "$word: $1\n"; } else { print "Couldn't find the match-string in the response\n"; }
通过 GET 提交表格
一些HTML表格不使用 POST 请求,而是使用 GET 请求来传输数据。例如,在 imdb.com 里检索电影名字 ‘Blade Runner’, 提交后在浏览器的网址栏里将显示 :
http://us.imdb.com/Tsearch?title=Blade%20Runner&restrict=Movies+and+TV
下面是使用 LWP 实现同样的结果 :
use URI; my $url = URI->new( 'http://us.imdb.com/Tsearch' ); # makes an object representing the URL $url->query_form( # And here the form data pairs: 'title' => 'Blade Runner', 'restrict' => 'Movies and TV', ); my $response = $browser->get($url);
第5章详细描述了 HTML 表格和表格数据,第6章到第9章描述了怎样从获得的HTML数据里提取出有用的信息。
URL 处理
上面提到的 URI class 提供很多获取和修改 URL 的方法。例如 如果想要知道 url 是什么类型 (http, ftp 等等) 可以使用 $url->schema 来得到,如果要提取网址里的主机名,可以使用 $url->host。不过,可能最有用的是我前面提到的 query_form 方法,以及把相对网址路径(如”../foo.html”)转换成绝对路径(如”http: //www.perl.com/stuff/foo.html”)的 new_abs 方法。例子如下:
use URI;
$abs = URI->new_abs($maybe_relative, $base);
>现在回忆一下获取最新 CPAN 模块的那个例子。
use strict; use warnings; use LWP 5.64; my $browser = LWP::UserAgent->new; my $url = 'http://www.cpan.org/RECENT.html'; my $response = $browser->get($url); die "Can't get $url -- ", $response->status_line unless $response->is_success; my $html = $response->content; while( $html =~ m/chunk86920392chunklt;A HREF=\"(.*?)\"/g ) { print "$1\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/<A HREF=\"(.*?)\"/g ) { print URI->new_abs( $1, $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 的第四章,以得到对 URI objects 更详细的描述。
当然,使用 regexp (正则表达式) 来匹配 url 相对简单,如果情况复杂,需要更强大的匹配工具,可以考虑 HTML 分析模块 HTML::LinkExtor 或 HTML::TokeParser,甚至 HTML::TreeBuilder
其他浏览器属性
LWP::UserAgent objects 有几个值得注意的属性 :
* $browser->timeout(15): 设定缺省 request 的 timeout 时间.超过这个时间就放弃请求。
* $browser->protocols_allowed( [ ‘http’, ‘gopher’] ): 这用来设定只接受 http 和 gopher 协议。连接其他协议时就返回 500 错误值,”Access to ftp URIs has been disabled” 的错误消息。
* use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()): 这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性,即重复使用先前的 socket 来加快请求速度。
* $browser->agent( ‘SomeName/1.23 (more info here maybe)’ ): 设置 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; MSIE 5.12; Mac_PowerPC)’ );
* push @{ $ua->requests_redirectable }, ‘POST’: 告诉 LWP 在 POST 请求发送后如果发生重新定向就自动跟随 ( 虽然 RFC 里不要求这么做 )
详细请参见 LWP::UserAgent 文档.
写一个有礼貌的机器人
如果想遵循 robots.txt 和避免在较短的时间发出太多的请求,你可以采用 LWP::RobotUA 而不是 LWP::UserAgent。
LWP::RobotUA 用法与 LWP::UserAgent 一样:
use LWP::RobotUA; my $browser = LWP::RobotUA->new( 'YourSuperBot/1.34', 'you@yoursite.com'); # 机器人名字和 email 地址 my $response = $browser->get($url);
HTTP::RobotUA 多了几个特性:
* 如果 $url 请求的服务器的 robots.txt 禁止了你对 $url的访问,那么 $browser 就不会发出对于这个地址的请求,而是返回 403 代码和一个错误信息 “Forbidden by robots.txt”。
die "$url -- ", $response->status_line, "\nAborted" unless $response->is_success;
然后你会得到这样的错误信息:
http://whatever.site.int/pith/x.html -- 403 Forbidden
by robots.txt
Aborted at whateverprogram.pl line 1234
* 如果 $browser 发现请求的地址是刚刚请求过的,就会暂停 (sleep) 来避免发送太多的请求。缺省暂停 1 分钟,但可以通过 $browser->delay( minutes ) 来设定。比如:
$browser->delay( 7/60 );
详细请参见 LWP::RobotUA文档.
使用代理
有时你希望(或者是必须)通过代理来连接某些站点或协议,就比如你的LWP程序是运行在某台处于防火墙之内的机器上。
代理通常储存在环境变量 HTTP_PROXY 里。LWP 可以通过 user-agent object 里的 env_proxy 函数把环境变量里的代理地址装载。
use LWP::UserAgent; my $browser = LWP::UserAgent->new; # And before you go making any requests: $browser->env_proxy;
详细请参照 LWP::UserAgent 文档里的 proxy, env_proxy 和 no_proxy 方法.
HTTP 认证
许多网站都是通过 HTTP 认证来限制连接. 当用户请求一个限制页面时, HTTP 服务器回复 “That document is part of a protected ‘realm’ and you can access it only if you re-request it and add some special authorization headers to your request”. ( 你现在请求了一个限制区域 , 如果你需要重新发送一个带有认证信息的 header 才可以连入. )
Unicode.org 的管理员为了防止机器人访问邮件组获取发信人地址,要求先进行 HTTP 认证。用户名和密码是公开的:用户名: unicode-ml 密码: unicode
假设一个限制页面的地址是
http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
如果你在浏览器里请求这个地址,一个新的窗口跳出,显示 “Enter username and password for ‘Unicode-MailList-Archives’ at server ‘www.unicode.org’”。请你输入用户名和密码,就像这样:
单纯使用 LWP 请求这个网址 :
use LWP 5.64; my $browser = LWP::UserAgent->new; my $url = 'http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html'; my $response = $browser->get($url); die "Error: ", $response->header('WWW-Authenticate') || 'Error accessing', # ('WWW-Authenticate' is the realm-name) "\n ", $response->status_line, "\n at $url\n Aborting" unless $response->is_success;
你将得到以下错误:
Error: Basic realm="Unicode-MailList-Archives"
401 Authorization Required
at http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
Aborting at auth1.pl line 9. [or wherever]
这是因为 LWP 不知道 host www.unicode.org 里的 “Unicode-MailList-Archives” 区的用户名和地址。解决这个问题最简单的方法是使用 credentials 方法来提供用户名和密码:
$browser->credentials( 'servername:portnumber', 'realm-name', 'username' => 'password' );
通常, 端口是 80. credentials 函数要在发请求之前调用.比如:
$browser->credentials( 'reports.mybazouki.com:80', 'web_server_usage_reports', 'plinky' => 'banjo123' );
我们的 unicode.org 的例子可以写成
$browser->credentials( # add this to our $browser 's "key ring" 'www.unicode.org:80', 'Unicode-MailList-Archives', 'unicode-ml' => 'unicode' );
连接 HTTPs URLs
只要有安装 LWP 的HTTPs 的支持, 访问 HTTPs URLs 的方法和 HTTP 一样
use LWP 5.64; my $url = 'https://www.paypal.com/'; # Yes, HTTPS! my $browser = LWP::UserAgent->new; my $response = $browser->get($url); die "Error at $url\n ", $response->status_line, "\n Aborting" unless $response->is_success; print "Whee, it worked! I got that ", $response->content_type, " document!\n";
如果没有 HTTPs 的支持, 如下错误信息会显示
Error at https://www.paypal.com/
501 Protocol scheme 'https' is not supported
Aborting at paypal.pl line 7. [or whatever program and line]
如果你安装了 LWP 的 HTTPS 支持的话,你的请求应该是成功的,你可以像对待普通的 HTTP 请求一样处理 $response 对象。
关于安装 HTTPS 支持的信息可以在libwww-perl 里的README.SSL 文件找到.
获取大文件
请求较大的文件时, 普通的请求方法 ( 例如 $response = $browser->get($url) ) 会给你带来内存问题. 因为 $response 储存着整个文件. 如果请求了一个 30MB 的文件, 那可能不是什么明智的做法.
一个解决方法是把文件存到硬盘
$response = $ua->get($url, ':content_file' => $filespec, );
比如:
$response = $ua->get('http://search.cpan.org/', ':content_file' => '/tmp/sco.html' );
当使用 content_file 时, headers 还是在$response, 但$response->content 是空.
值得注意的是LWP 5.66 之前的版本不支持content_file . 你应该使用 use LWP 5.66; 如果你的程序可能运行在低版本的 LWP 上, 你也可以使用下面的例子来保证兼容性, 这与 content_file 有同样效果.
use HTTP::Request::Common; $response = $ua->request( GET($url), $filespec );
资源
以上只是对 LWP 常用函数的简介, 如果想了解更多关于 LWP 和 LWP 相关的东西, 请参阅以下文档
* LWP::Simple: 提供简易的 get, head, mirror 方法.
* LWP: libwww-perl 模块的综述
* HTTP::Response: 发出 LWP 请求后所得到的响应 , $response = $browser->get(...).
* HTTP::Message and HTTP::Headers: HTTP::Response 很多方法都是来自两者.
* URI: Class 处理完全和相对网址路径.
* URI::Escape: 来正确处理和转换 URL 里的不规则字符 (比如 “this & that” 和 “this%20%26%20that” 之间的转换).
* HTML::Entities: 来正确处理和转换 HTML 里的不规则字符 (比如 “C. & E. Bront??” 和 “C. & E. Bront??” 之间的转换).
* HTML::TokeParser and HTML::TreeBuilder: Classes 分析 HTML
* HTML::LinkExtor: Class :在 HTML 找到链接
* 当然还有我的 Perl & LWP.
与 Sean Burke 讨论后的一些笔记
在翻译这篇文章的时候,我联系到了文章作者, Sean Burke. 他同意把原文章
>现在回忆一下获取最新 CPAN 模块的那个例子。
use strict; use warnings; use LWP 5.64; my $browser = LWP::UserAgent->new; my $url = 'http://www.cpan.org/RECENT.html'; my $response = $browser->get($url); die "Can't get $url -- ", $response->status_line unless $response->is_success; my $html = $response->content; while( $html =~ m/chunk86920392chunklt;A HREF=\"(.*?)\"/g ) { print "$1\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/<A HREF=\"(.*?)\"/g ) { print URI->new_abs( $1, $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 的第四章,以得到对 URI objects 更详细的描述。
当然,使用 regexp (正则表达式) 来匹配 url 相对简单,如果情况复杂,需要更强大的匹配工具,可以考虑 HTML 分析模块 HTML::LinkExtor 或 HTML::TokeParser,甚至 HTML::TreeBuilder
其他浏览器属性
LWP::UserAgent objects 有几个值得注意的属性 :
* $browser->timeout(15): 设定缺省 request 的 timeout 时间.超过这个时间就放弃请求。
* $browser->protocols_allowed( [ ‘http’, ‘gopher’] ): 这用来设定只接受 http 和 gopher 协议。连接其他协议时就返回 500 错误值,”Access to ftp URIs has been disabled” 的错误消息。
* use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()): 这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性,即重复使用先前的 socket 来加快请求速度。
* $browser->agent( ‘SomeName/1.23 (more info here maybe)’ ): 设置 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; MSIE 5.12; Mac_PowerPC)’ );
* push @{ $ua->requests_redirectable }, ‘POST’: 告诉 LWP 在 POST 请求发送后如果发生重新定向就自动跟随 ( 虽然 RFC 里不要求这么做 )
详细请参见 LWP::UserAgent 文档.
写一个有礼貌的机器人
如果想遵循 robots.txt 和避免在较短的时间发出太多的请求,你可以采用 LWP::RobotUA 而不是 LWP::UserAgent。
LWP::RobotUA 用法与 LWP::UserAgent 一样:
use LWP::RobotUA; my $browser = LWP::RobotUA->new( 'YourSuperBot/1.34', 'you@yoursite.com'); # 机器人名字和 email 地址 my $response = $browser->get($url);
HTTP::RobotUA 多了几个特性:
* 如果 $url 请求的服务器的 robots.txt 禁止了你对 $url的访问,那么 $browser 就不会发出对于这个地址的请求,而是返回 403 代码和一个错误信息 “Forbidden by robots.txt”。
die "$url -- ", $response->status_line, "\nAborted" unless $response->is_success;
然后你会得到这样的错误信息:
http://whatever.site.int/pith/x.html -- 403 Forbidden
by robots.txt
Aborted at whateverprogram.pl line 1234
* 如果 $browser 发现请求的地址是刚刚请求过的,就会暂停 (sleep) 来避免发送太多的请求。缺省暂停 1 分钟,但可以通过 $browser->delay( minutes ) 来设定。比如:
$browser->delay( 7/60 );
详细请参见 LWP::RobotUA文档.
使用代理
有时你希望(或者是必须)通过代理来连接某些站点或协议,就比如你的LWP程序是运行在某台处于防火墙之内的机器上。
代理通常储存在环境变量 HTTP_PROXY 里。LWP 可以通过 user-agent object 里的 env_proxy 函数把环境变量里的代理地址装载。
use LWP::UserAgent; my $browser = LWP::UserAgent->new; # And before you go making any requests: $browser->env_proxy;
详细请参照 LWP::UserAgent 文档里的 proxy, env_proxy 和 no_proxy 方法.
HTTP 认证
许多网站都是通过 HTTP 认证来限制连接. 当用户请求一个限制页面时, HTTP 服务器回复 “That document is part of a protected ‘realm’ and you can access it only if you re-request it and add some special authorization headers to your request”. ( 你现在请求了一个限制区域 , 如果你需要重新发送一个带有认证信息的 header 才可以连入. )
Unicode.org 的管理员为了防止机器人访问邮件组获取发信人地址,要求先进行 HTTP 认证。用户名和密码是公开的:用户名: unicode-ml 密码: unicode
假设一个限制页面的地址是
http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
如果你在浏览器里请求这个地址,一个新的窗口跳出,显示 “Enter username and password for ‘Unicode-MailList-Archives’ at server ‘www.unicode.org’”。请你输入用户名和密码,就像这样:
单纯使用 LWP 请求这个网址 :
use LWP 5.64; my $browser = LWP::UserAgent->new; my $url = 'http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html'; my $response = $browser->get($url); die "Error: ", $response->header('WWW-Authenticate') || 'Error accessing', # ('WWW-Authenticate' is the realm-name) "\n ", $response->status_line, "\n at $url\n Aborting" unless $response->is_success;
你将得到以下错误:
Error: Basic realm="Unicode-MailList-Archives"
401 Authorization Required
at http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
Aborting at auth1.pl line 9. [or wherever]
这是因为 LWP 不知道 host www.unicode.org 里的 “Unicode-MailList-Archives” 区的用户名和地址。解决这个问题最简单的方法是使用 credentials 方法来提供用户名和密码:
$browser->credentials( 'servername:portnumber', 'realm-name', 'username' => 'password' );
通常, 端口是 80. credentials 函数要在发请求之前调用.比如:
$browser->credentials( 'reports.mybazouki.com:80', 'web_server_usage_reports', 'plinky' => 'banjo123' );
我们的 unicode.org 的例子可以写成
$browser->credentials( # add this to our $browser 's "key ring" 'www.unicode.org:80', 'Unicode-MailList-Archives', 'unicode-ml' => 'unicode' );
连接 HTTPs URLs
只要有安装 LWP 的HTTPs 的支持, 访问 HTTPs URLs 的方法和 HTTP 一样
use LWP 5.64; my $url = 'https://www.paypal.com/'; # Yes, HTTPS! my $browser = LWP::UserAgent->new; my $response = $browser->get($url); die "Error at $url\n ", $response->status_line, "\n Aborting" unless $response->is_success; print "Whee, it worked! I got that ", $response->content_type, " document!\n";
如果没有 HTTPs 的支持, 如下错误信息会显示
Error at https://www.paypal.com/
501 Protocol scheme 'https' is not supported
Aborting at paypal.pl line 7. [or whatever program and line]
如果你安装了 LWP 的 HTTPS 支持的话,你的请求应该是成功的,你可以像对待普通的 HTTP 请求一样处理 $response 对象。
关于安装 HTTPS 支持的信息可以在libwww-perl 里的README.SSL 文件找到.
获取大文件
请求较大的文件时, 普通的请求方法 ( 例如 $response = $browser->get($url) ) 会给你带来内存问题. 因为 $response 储存着整个文件. 如果请求了一个 30MB 的文件, 那可能不是什么明智的做法.
一个解决方法是把文件存到硬盘
$response = $ua->get($url, ':content_file' => $filespec, );
比如:
$response = $ua->get('http://search.cpan.org/', ':content_file' => '/tmp/sco.html' );
当使用 content_file 时, headers 还是在$response, 但$response->content 是空.
值得注意的是LWP 5.66 之前的版本不支持content_file . 你应该使用 use LWP 5.66; 如果你的程序可能运行在低版本的 LWP 上, 你也可以使用下面的例子来保证兼容性, 这与 content_file 有同样效果.
use HTTP::Request::Common;
$response = $ua->request( GET($url), $filespec );
资源
以上只是对 LWP 常用函数的简介, 如果想了解更多关于 LWP 和 LWP 相关的东西, 请参阅以下文档
* LWP::Simple: 提供简易的 get, head, mirror 方法.
* LWP: libwww-perl 模块的综述
* HTTP::Response: 发出 LWP 请求后所得到的响应 , $response = $browser->get(...).
* HTTP::Message and HTTP::Headers: HTTP::Response 很多方法都是来自两者.
* URI: Class 处理完全和相对网址路径.
* URI::Escape: 来正确处理和转换 URL 里的不规则字符 (比如 “this & that” 和 “this%20%26%20that” 之间的转换).
* HTML::Entities: 来正确处理和转换 HTML 里的不规则字符 (比如 “C. & E. Bront??” 和 “C. & E. Bront??” 之间的转换).
* HTML::TokeParser and HTML::TreeBuilder: Classes 分析 HTML
* HTML::LinkExtor: Class :在 HTML 找到链接
* 当然还有我的 Perl & LWP.
与 Sean Burke 讨论后的一些笔记
在翻译这篇文章的时候,我联系到了文章作者, Sean Burke. 他同意把原文章 >现在回忆一下获取最新 CPAN 模块的那个例子。
use strict; use warnings; use LWP 5.64; my $browser = LWP::UserAgent->new; my $url = 'http://www.cpan.org/RECENT.html'; my $response = $browser->get($url); die "Can't get $url -- ", $response->status_line unless $response->is_success; my $html = $response->content; while( $html =~ m/chunk86920392chunklt;A HREF=\"(.*?)\"/g ) { print "$1\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/<A HREF=\"(.*?)\"/g ) { print URI->new_abs( $1, $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 的第四章,以得到对 URI objects 更详细的描述。
当然,使用 regexp (正则表达式) 来匹配 url 相对简单,如果情况复杂,需要更强大的匹配工具,可以考虑 HTML 分析模块 HTML::LinkExtor 或 HTML::TokeParser,甚至 HTML::TreeBuilder
其他浏览器属性
LWP::UserAgent objects 有几个值得注意的属性 :
* $browser->timeout(15): 设定缺省 request 的 timeout 时间.超过这个时间就放弃请求。
* $browser->protocols_allowed( [ ‘http’, ‘gopher’] ): 这用来设定只接受 http 和 gopher 协议。连接其他协议时就返回 500 错误值,”Access to ftp URIs has been disabled” 的错误消息。
* use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()): 这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性,即重复使用先前的 socket 来加快请求速度。
* $browser->agent( ‘SomeName/1.23 (more info here maybe)’ ): 设置 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; MSIE 5.12; Mac_PowerPC)’ );
* push @{ $ua->requests_redirectable }, ‘POST’: 告诉 LWP 在 POST 请求发送后如果发生重新定向就自动跟随 ( 虽然 RFC 里不要求这么做 )
详细请参见 LWP::UserAgent 文档.
写一个有礼貌的机器人
如果想遵循 robots.txt 和避免在较短的时间发出太多的请求,你可以采用 LWP::RobotUA 而不是 LWP::UserAgent。
LWP::RobotUA 用法与 LWP::UserAgent 一样:
use LWP::RobotUA; my $browser = LWP::RobotUA->new( 'YourSuperBot/1.34', 'you@yoursite.com'); # 机器人名字和 email 地址 my $response = $browser->get($url);
HTTP::RobotUA 多了几个特性:
* 如果 $url 请求的服务器的 robots.txt 禁止了你对 $url的访问,那么 $browser 就不会发出对于这个地址的请求,而是返回 403 代码和一个错误信息 “Forbidden by robots.txt”。
die "$url -- ", $response->status_line, "\nAborted"
unless $response->is_success;
然后你会得到这样的错误信息:
http://whatever.site.int/pith/x.html -- 403 Forbidden
by robots.txt
Aborted at whateverprogram.pl line 1234
* 如果 $browser 发现请求的地址是刚刚请求过的,就会暂停 (sleep) 来避免发送太多的请求。缺省暂停 1 分钟,但可以通过 $browser->delay( minutes ) 来设定。比如:
$browser->delay( 7/60 );
详细请参见 LWP::RobotUA文档.
使用代理
有时你希望(或者是必须)通过代理来连接某些站点或协议,就比如你的LWP程序是运行在某台处于防火墙之内的机器上。
代理通常储存在环境变量 HTTP_PROXY 里。LWP 可以通过 user-agent object 里的 env_proxy 函数把环境变量里的代理地址装载。
use LWP::UserAgent; my $browser = LWP::UserAgent->new; # And before you go making any requests: $browser->env_proxy;
详细请参照 LWP::UserAgent 文档里的 proxy, env_proxy 和 no_proxy 方法.
HTTP 认证
许多网站都是通过 HTTP 认证来限制连接. 当用户请求一个限制页面时, HTTP 服务器回复 “That document is part of a protected ‘realm’ and you can access it only if you re-request it and add some special authorization headers to your request”. ( 你现在请求了一个限制区域 , 如果你需要重新发送一个带有认证信息的 header 才可以连入. )
Unicode.org 的管理员为了防止机器人访问邮件组获取发信人地址,要求先进行 HTTP 认证。用户名和密码是公开的:用户名: unicode-ml 密码: unicode
假设一个限制页面的地址是
http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
如果你在浏览器里请求这个地址,一个新的窗口跳出,显示 “Enter username and password for ‘Unicode-MailList-Archives’ at server ‘www.unicode.org’”。请你输入用户名和密码,就像这样:
单纯使用 LWP 请求这个网址 :
use LWP 5.64; my $browser = LWP::UserAgent->new; my $url = 'http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html'; my $response = $browser->get($url); die "Error: ", $response->header('WWW-Authenticate') || 'Error accessing', # ('WWW-Authenticate' is the realm-name) "\n ", $response->status_line, "\n at $url\n Aborting" unless $response->is_success;
你将得到以下错误:
Error: Basic realm="Unicode-MailList-Archives"
401 Authorization Required
at http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html
Aborting at auth1.pl line 9. [or wherever]
这是因为 LWP 不知道 host www.unicode.org 里的 “Unicode-MailList-Archives” 区的用户名和地址。解决这个问题最简单的方法是使用 credentials 方法来提供用户名和密码:
$browser->credentials( 'servername:portnumber', 'realm-name', 'username' => 'password' );
通常, 端口是 80. credentials 函数要在发请求之前调用.比如:
$browser->credentials( 'reports.mybazouki.com:80', 'web_server_usage_reports', 'plinky' => 'banjo123' );
我们的 unicode.org 的例子可以写成
$browser->credentials( # add this to our $browser 's "key ring" 'www.unicode.org:80', 'Unicode-MailList-Archives', 'unicode-ml' => 'unicode' );
连接 HTTPs URLs
只要有安装 LWP 的HTTPs 的支持, 访问 HTTPs URLs 的方法和 HTTP 一样
use LWP 5.64; my $url = 'https://www.paypal.com/'; # Yes, HTTPS! my $browser = LWP::UserAgent->new; my $response = $browser->get($url); die "Error at $url\n ", $response->status_line, "\n Aborting" unless $response->is_success; print "Whee, it worked! I got that ", $response->content_type, " document!\n";
如果没有 HTTPs 的支持, 如下错误信息会显示
Error at https://www.paypal.com/
501 Protocol scheme 'https' is not supported
Aborting at paypal.pl line 7. [or whatever program and line]
如果你安装了 LWP 的 HTTPS 支持的话,你的请求应该是成功的,你可以像对待普通的 HTTP 请求一样处理 $response 对象。
关于安装 HTTPS 支持的信息可以在libwww-perl 里的README.SSL 文件找到.
获取大文件
请求较大的文件时, 普通的请求方法 ( 例如 $response = $browser->get($url) ) 会给你带来内存问题. 因为 $response 储存着整个文件. 如果请求了一个 30MB 的文件, 那可能不是什么明智的做法.
一个解决方法是把文件存到硬盘
$response = $ua->get($url, ':content_file' => $filespec, );
比如:
$response = $ua->get('http://search.cpan.org/', ':content_file' => '/tmp/sco.html' );
当使用 content_file 时, headers 还是在$response, 但$response->content 是空.
值得注意的是LWP 5.66 之前的版本不支持content_file . 你应该使用 use LWP 5.66; 如果你的程序可能运行在低版本的 LWP 上, 你也可以使用下面的例子来保证兼容性, 这与 content_file 有同样效果.
use HTTP::Request::Common; $response = $ua->request( GET($url), $filespec );
资源
以上只是对 LWP 常用函数的简介, 如果想了解更多关于 LWP 和 LWP 相关的东西, 请参阅以下文档
* LWP::Simple: 提供简易的 get, head, mirror 方法.
* LWP: libwww-perl 模块的综述
* HTTP::Response: 发出 LWP 请求后所得到的响应 , $response = $browser->get(...).
* HTTP::Message and HTTP::Headers: HTTP::Response 很多方法都是来自两者.
* URI: Class 处理完全和相对网址路径.
* URI::Escape: 来正确处理和转换 URL 里的不规则字符 (比如 “this & that” 和 “this%20%26%20that” 之间的转换).
* HTML::Entities: 来正确处理和转换 HTML 里的不规则字符 (比如 “C. & E. Bront??” 和 “C. & E. Bront??” 之间的转换).
* HTML::TokeParser and HTML::TreeBuilder: Classes 分析 HTML
* HTML::LinkExtor: Class :在 HTML 找到链接
* 当然还有我的 Perl & LWP.
与 Sean Burke 讨论后的一些笔记
在翻译这篇文章的时候,我联系到了文章作者, Sean Burke. 他同意把原文章
里需要补充和更新的地方指出. 我与作者也通过 MSN 交流了一下. 这里我把自己对 LWP 的理解和作者的补充写在这里.
* 在文章里提到了使用
use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()):
这告诉 browser object 使用 HTTP/1.1 “keep-Alive” 特性, 即重复使用先前的 socket 来加快请求速度.
你也可以在 new LWP::UserAgent 时为 $browser 加上 “keep-Alive” 特性, 如下
use LWP; $browser = new LWP::UserAgent(keep_alive => 1);
* 不要忘记 response object 的 header 通常有很多非常值得注意的信息, 你可以通过 headers_as_string 和 as_string 函数来得到. 下面是使用 headers_as_string 返回的例子
use LWP; my $br = LWP::UserAgent->new; my $resp = $br ->get('http://www.pulse24.com'); print $resp->headers_as_string";
输出结果:
Cache-Control: private, max-age=0
Connection: close
Date: Sun, 16 Jan 2005 04:18:26 GMT
Server: Microsoft-IIS/6.0
Content-Length: 432
Content-Type: text/html
Content-Type: text/html; charset=iso8859-1
Client-Date: Sun, 16 Jan 2005 04:18:09 GMT
Client-Peer: 207.61.136.40:80
Client-Response-Num: 1
REFRESH: 0;URL=http://www.pulse24.com/Front_Page/page.asp
X-Meta-Robots: noindex
X-Powered-By: ASP.NET
你也可以通过 $response->header(‘field’) 来获得想要的特别 header. 象上面的例子, 如果要访问的网页使用了 meta refresh :
<META HTTP-EQUIV="REFRESH" CONTENT="0;URL=http://www.pulse24.com/Front_Page/page.asp">
你可以使用 $response->header(‘refresh’) 来拿到 refresh 的 url 地址, 选择是否继续跟进.
* 有些时候, 浏览器可以正常访问到的地址, LWP 却不行. 一般是因为你的 LWP 的 header, referer , cookie 或 user-agent 等的设定与对方网络服务器允许连入的不同. 为了找到问题所在, 你需要比较浏览器发出的请求和你的 LWP 发出的请求有何不同, 然后修改再尝试. 很多时候这是反反复复的工作. 我最早使用 Ethereal 来监视,抓取数据, 目前使用 Firefox 的 LiveHTTPHeaders 插件. 现在LWP 也自带一个数据分析模块 LWP::DebugFile 来帮助你找到问题.
* 另外, 文章里提到了 HTTP::Cookies::Netscape , 现在LWP Cookies 模块支持更多浏览器 Mozilla , Safari , Omniweb
* 很多时候表格与 javascript 一起使用, LWP 没有分析 Javascript 的引擎,所以你必须分析网页源码里 Javascript 来决定怎样处理.
function Submit() { ......... self.document.location.href="verify.php"; return false; } ........ <form> ...... * <input type=button value="Submit your page" onClick="javascript:Submit();return false;//">
上面的这个例子通过表格提交来触动 javascript 的 submit 函数, 最后调用了 verify.php. 现在你就可以跳过所有的 javascript 而直接对 verify.php 来提交.
<input type=button value="Submit your page" onClick="javascript:Submit();return false;//">
上面的这个例子通过表格提交来触动 javascript 的 submit 函数, 最后调用了 verify.php. 现在你就可以跳过所有的 javascript 而直接对 verify.php 来提交.
发表评论
-
perl对中文的处理(encode,decode)(转)
2011-02-10 21:10 1584原文:http://www.cnblogs.com/slaug ... -
perl 函数
2011-02-05 20:32 13281. bless() bless有两个参数:对象的引 ... -
perl 语法 及其它
2011-02-02 10:24 14911. perl根据上下文context ... -
perl的零散东西
2011-01-31 21:40 1065print "$_\n" for $set ... -
分析ps和free HASH的用法
2010-01-21 17:05 1053#!/usr/bin/perl use warnings; ... -
下载图片
2010-01-21 09:21 1077#!/usr/bin/perl use warnings; ... -
getPic.pl 文件操作
2010-01-19 23:45 1466#!/usr/bin/perl use warnings; ... -
文件操作
2010-01-11 15:39 999open INDEX_FILE, "<in ... -
morning 早晨叫床.pl
2010-01-05 22:56 1279#!/usr/bin/perl use warnings ... -
Gtk2-Perl 的安装(ZZ)
2010-01-01 14:56 5739Gtk2-Perl 的安装 Gtk2-perl ... -
Perl命令 -- 安装.命令行之类的
2010-01-01 12:03 17461. 查看安装的模块 $>perldoc p ... -
Perl的相关文章
2009-11-29 11:42 1018Perl中的文件包含 Perl命令行应用介绍 Perl 之L ...
相关推荐
LWP 是一个Perl模块集合,允许开发人员编写能够与Web服务器交互的程序,包括发送HTTP请求并处理响应。以下是对Perl和LWP网络爬虫的深入解释: 首先,Perl是一种功能强大的脚本语言,广泛应用于文本处理、系统管理...
本章为读者介绍了Web自动化的基本概念,阐述了为什么使用Perl和LWP来完成Web自动化任务,以及如何开始编写一个简单的网络爬虫脚本。 第二章:Web基础。本章讲述了Web工作的基础知识,包括Web服务器、HTTP协议以及...
LWP ("Library for WWW in Perl" 的缩写) 是一个由多个模块组成,用来获取网络数据的的模块组。...要对 LWP 做全面的介绍需要一整本书,很幸运,Perl & LWP 已经出版。而这篇文章向你介绍了最常见的 LWP 用法。
离线安装包,亲测可用
LWP(Library for Web access in Perl):perl网页爬取工具。 原版chm,转成pdf方便打印。删去了一些冗余信息。后附附录和索引。
离线安装包,亲测可用
通过研究这个脚本,读者不仅可以掌握LWP模块的使用,还能了解网络编程的基本原理,以及如何与Web服务进行交互。这对于任何想要进行Web爬虫开发或者需要处理网络数据的Perl开发者来说,都是极其宝贵的实践经验。
4. **Web服务和APIs**:Perl可以用来开发RESTful API,利用LWP::UserAgent库来消费第三方API,或者使用JSON和XML模块来处理数据交换格式。 5. **数据库交互**:Perl的DBI模块提供了一种标准的方式来与各种关系型...
perl的lwp详解,讲的比较详细,还是蛮有用的 看不了的朋友,右击这个文档选择属性,然后下面有一个解除锁定的按钮,点一下接触锁定,然后就可以看了,给大家带来不便了,呵呵
【Perl.Web开发技术】.zip 文件包包含了关于使用Perl进行Web开发的相关教程,这是一份深入探讨Perl在Web开发中的应用的资料。Perl是一种强大的脚本语言,由于其灵活、可扩展的特性,在Web开发领域有着广泛的应用。...
Perl5 基础与实例.pdf:提供 Perl 语言的基础知识和实践经验,涵盖了 Perl 语言的基本语法、数据类型和控制结构等。 Perl 语言入门.pdf:为 Perl 语言的新手提供了一份入门指南,涵盖了 Perl 语言的基础知识和...
在Perl编程中,LWP::UserAgent是一个核心模块,它提供了与Web服务器交互的基本功能,如发送GET和POST请求、处理响应等。而"LWP::UserAgent::ProxyAny"扩展了这个模块,添加了对通过任意类型的代理服务器(如HTTP、...
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
Perl也常用于Web开发,尤其是与CGI(Common Gateway Interface)一起使用,允许Perl脚本生成动态网页。尽管现代Web框架如Django和Rails更为流行,但Perl的CGI和后来的Mod_perl仍然是很多旧系统的基础。 在实际应用...
Perl是一种强大的、跨平台的脚本编程语言,广泛用于文本处理、系统管理、网络编程以及Web开发等多个领域。"Perl开发环境.zip" 提供的是在Windows操作系统上搭建Perl开发环境的资源,具体是"strawberry-perl-5.32.0.1...
模块的使用也是Perl的一大特色,通过导入第三方模块,可以快速扩展功能,如LWP::UserAgent用于Web请求,DBI用于数据库连接等。 Perl还具有强大的错误处理和调试机制,包括警告、die、warn和 Carp 模块,这些将在...
Perl是一种广泛使用的高级编程语言,尤其适用于文本处理、系统管理任务以及Web开发等领域。本书以其详尽的内容和易于理解的示例,成为学习Perl的理想选择。 #### 二、Perl语言的基本概念 - **变量类型:** - 标量...