perl模块和包的使用

上一篇 / 下一篇  2008-11-18 22:33:19 / 个人分类:python

  • 文件版本: V1.0
  • 开发商: 本站原创
  • 文件来源: 本地
  • 界面语言: 简体中文
  • 授权方式: 免费
  • 运行平台: Win9X/Win2000/WinXP
模块解释51Testing软件测试网;Cn(K+rs

链接检查

%WfEA\-jS7]7]0

u,A_ FC0~I~0网页增长得很快,每个网站可能有很多的(比如千个以上的连接),现在该是我们做某些事的时候了。特别是,寻找,修正,删除他们的时候。51Testing软件测试网;WD6@xF#dh j#j6@#v
我当然不会点击这么多的连接去看他们是否正常。我们需要一个程序来做这些事情。yahoo列出了这些检查网页的程序,但是没有发现任何一个程序是:简单,免费,为了我的连接。

g1]}x;? ymi0

QVjS*s0s A W4|0特性

CXnAh051Testing软件测试网;oe)e S$^8r+Lfl

我们称这个“linkcheck”。为了在网页上检查这个连接,我们可以这样写:
-zDQs n3D0linkcheck http://my.isp.com/page.html51Testing软件测试网^'O_T~l
这个程序会给我们这样的报告 :51Testing软件测试网8S6Fot.r$`'q

v${0Kt} J0Checked 1 pages, 49 links
y'_];A4eGFN'H.~0Found 0 broken links51Testing软件测试网jY{?SY

;j6@&Atg@(J0-r51Testing软件测试网 `F)de|]EvD
正如所展示的,linkcheck检查一个网页上的所有的连接,但是我们希望检查在一个站点上的所有的连接。我们可以通过找到到其它网页的连接,再检查那些网页来做到。
+E%J!Dp L c9q}6C?s,mo0linkcheck -r http://my.isp.com/page.html
2e8Xc1L/l6^E!t0Checked 144 pages, 1025 links
E^?M:VwF0Found 3 broken links

f&^(^&E_;wr051Testing软件测试网+{|EY |

如果我们检查所有的连接,我们可能不可能结束像蜘蛛网一样的网络。为了避免这些,我们应该仅仅只检查在我们自己网页上的连接 。

#b.y0bIg;P051Testing软件测试网w dG UE

-o

;{Y3?d_9}0

\NQ0[7~#fO s0我们一般不想检查那些脱机的网页,但是我们仍有可能要检查这些脱机的网页。如果我们想要检查脱机的网页的话,我们可以设置-o这个标志位。51Testing软件测试网8AV+H4BZ,n5S
linkcheck -o -r http://my.isp.com/page.html51Testing软件测试网`.@'E8Mg#^)H
Checked 144 pages, 1131 links51Testing软件测试网Gb:N@ ?4G A
Found 3 broken links

Y9{7C.vX6?0

j%Ce&D {)z0-v verbosity51Testing软件测试网 R)g1[pef~

51Testing软件测试网oU^&K;^1I

如果我们找到了那些坏的连接,我们有可能想知道这些连接是什么。-v verbosity 这个标志位控莆颐堑玫降氖涑龅氖俊?51Testing软件测试网,q+Y8yP FFu*Ps&k'x
-v 0
YI9[sy3L$a"czCF0显示 坏连接的数量 (默认)51Testing软件测试网'r*_(dA7q9L8k
-v 1
f} ^P-`Pi0同时列出坏连接51Testing软件测试网F\kXXp
-v 2
;w_sT-F:[0同时列出检查的网页51Testing软件测试网U$g8K-}gZ v"nB!O0]
-v 351Testing软件测试网(]${%J0Te R%k%PLmE-C
同时列出检查的连接51Testing软件测试网HT;s?OH

51Testing软件测试网X%X G7@ \"n

-t twiddle

5]2H8f-{xT;Cj051Testing软件测试网*}g Gg9AGZ,M/Z D c

网页可能要花很长的时间来下载。当我们在等待的时候,我们总想看一些输出的结果,以此来知道程序在做一些事情,也因此我们不会感到太无聊。我们可以使用 -v 标志,但是可能要把结果输出到一个文件或是一个管道。因此,我们提供了这个标志。

\9~? K w jq0

:T SFA n9q)Q0-t 0
PO:g6PI3xP0什么也没有(默认)51Testing软件测试网| X y.Ec W&Xr
-t 1
mg I U:t SG2w7c'\0徽调控制项: | / -51Testing软件测试网Ip CK^
-t 2
[i3T9gL0程序报告:"$Pages pages, $Links links, $Broken brokenr"
q$^0j'~fY8p6L {0输出是输出到标准输出,twiddle的是从标准错误输出的。这个我们是可以重定向的。它也确保了twiddle不会从缓冲中读取,它展示的是实时的。51Testing软件测试网S,[g%}'d-O0Q#o e _*G@

t/k6e tv R)gx1Q0运算法则
:L)j^ dAs0这是检查一个网页的大体的大钢。
%z/{([O%kb,Th |@0给定一个url,我们必须51Testing软件测试网'? fD:X$tWv4O
从url解析主机名,51Testing软件测试网v1{'\O O4B
打开一个tcp连接到服务器,
l ON7V A#P*R$c0发送一个http请求,51Testing软件测试网H o$z8|atN
接收一个http响应,
\!_`$~%\w1ik4M0处理重定向 ,
mac-_jJTe0从http响应中解开html网页,
(Uax:E*e0解释出这个网页中的所有的连接,
Z][6Cbd)j&t2U0处理相关连接,
"A]I;S ??1_0检查每个连接的后辍名,
)U ug9LtK N]0为了把这个算法转化成一个程序,我们必须
+n1wX5It2M0解析命令行,
$EeT$yq*S3Y0确定腹鸣机连接,
D+|)\E\;k9b"kju0为已经访问的网页和检查的连接做个记号 ,51Testing软件测试网p3d ]4Vf q7Y,I
产生文件 ,51Testing软件测试网:N~D }(f? a3c
从最原始的开始做这个工作将是个很大的工作。幸运的是,我们不必这么做。大多数繁重的工作别人已经做好了,而且做成了模块提供了。这里是linkcheck所用到的模块,51Testing软件测试网9V-yne%v
Getopt::Std
Hje5zo(?+f)T0HTML::Parser51Testing软件测试网b&K BlI ` h*I
LWP::UserAgent51Testing软件测试网7{0_,u.k0R;|.r7k
Pod::Usage
r:v\,qQ8@0URI

"k8kr/Tp&U0

0Rt @ zr0使用这些模块,我们可以使用仅仅几百行的代码来构成这个程序。在以下的部份,我们展示怎样编写这个程序。

Q/y%VIy!~:w0

z*r hW:B#G0模块51Testing软件测试网8Xwu,H:}

$Gxd r/J)g-D+P0首先,我们复习一下模块51Testing软件测试网ze]e3d
Getopt::Std
G!\/p*U"f0Getopt::Std 解析命令行的选项。更详细的说明参见GetOpt::.51Testing软件测试网R_U Cg'?M)g

}J$^$o0hk VA0URL
H;tef'{ YQi1b0URL管理URL: 每个URL的对象代表一个单一的URL。URL可以有很多的方法来构建操作,分析URL,但是我们仅仅需要其中的 一些功能。
c0r1E[)i hJ,^0创建一个URL对象,我们这样写:
Gd%fQ8|6{F#|$J0$uri = new URI 'http://my.isp.com/page1.html#section1';
|,H Vb3g0我们可以用new_abs来分解相关连接
`/W}#m#s2@ kL8S0$uri2 = new_abs 'page2.html', $uri; # http://my.isp.com/page2.html51Testing软件测试网.k1j&Sy#BfE

51Testing软件测试网 yH'iB2@1H's

访问器解开一个url的成分:
-YWu3u&i0q"k#Dz0$uri->scheme; # http
EU&OK"v2|R0$uri->authority; # my.isp.com51Testing软件测试网,ue+L$G;iL G
$uri->fragment; # section151Testing软件测试网!kvw%my?N!mn

51Testing软件测试网"V A^I:x

传送一个参数到访问器,设置那个成份。空的成份代表没有定义:51Testing软件测试网 O l*C-I-e}
$uri->fragment('section2'); # http://my.isp.com/page1.html#section2
uV|H? H}0$uri->fragment(undef); # http://my.isp.com/page1.html51Testing软件测试网&s3N7^hF~ R4[

51Testing软件测试网 |:S#i8r6t5R t3ow V;_

as_string() 方法返回一个代表url对象的字符。我们可以使用Url对象在任何可以使用字符的地方:51Testing软件测试网?)j O,X!T*@.f
print "$urin";51Testing软件测试网 z~,GLK U%@
$Visited{$uri} = 1;

C3bYw'H~*u0

${#^ON0s`f0LWP::UserAgent

6j!aV,X#y)m7h n/?Aqh051Testing软件测试网8G:d!S A2F#N] i+{

LWP是在perl中用来访问www的一个库。我们用它来得到web页面。也许得到一个网页的最简单的方法是使用LWP::Simple这个模块。
(w!u_ Ub0P0use LWP::Simple;51Testing软件测试网] S,m+o"a M;t%M
$content = get($uri);
TP&c} _q$G$P(G0get() 这个方法返回了web页面的内容,失败时返回undef.然而,我们需要更进一步的信息,所以我们应该使用LWP::UserAgent这个模块。51Testing软件测试网 _vC9[9fs
一个user agent是任何http client类型。LWP::UserAgent在perl中执行一个http client.为了得到一个web页面,我们产生一个LWP::UserAgent对象, 发送一个http请求,接收一个http响应。

:Y+K8D"@$~.V jJ7V0

;C9I-[,C+x0$ua = new LWP::UserAgent;
(z!~.WMv v;q0$request = new HTTP::Request GET => $uri;
Bpp a"y-K0$response = $ua->request($request);

:K8Hy3msR0r,T051Testing软件测试网X"r] NY

$response 包括web页面的内容:51Testing软件测试网1GQ;E,qu,L
$content = $response->content;
Mwg Wm$s)~,lb0如果我们只需要http头来检查一个页面的修改时间,或是它的存在,我们可以使用一个head的请求:51Testing软件测试网$A ?}2ev
$request = new HTTP::Request HEAD => $uri;
9qZv\6ZH0request()方法自动处理重定向。我们可以从最后得到的页面覆盖原来的url,就像这样 :
z PH5Ug~0$uri = $response->request->uri;
pI"L~_]F bf051Testing软件测试网yDe}]9Y

51Testing软件测试网5M!B~T,bc6p"~

HTML::Parser
:T`0y5a2s3z:b j0一旦我们有了一个web页面,我们希望找到上面的所有的网页。HTML::Parser解析web页面。我们并不是直接使用HTML::Parser这个模块。然而我们创建使用它的一个子程序:
8}ioI)k.{3[0use HTML::Parser;

\ R\ jn!`D051Testing软件测试网r#EV-y7PT%u

package HTML::Parser::Links;

0m LX N t-`^t8k y0

q |z9H/A0}Z0use base qw(HTML::Parser);
z;uV P(mWF/z2I'c0为了解析一个web页面,我们创建一个我们子程序的对象,传递网页的内容到parse方法。51Testing软件测试网#_B"XdH.gJ2}8G
$parser = new HTML::Parser::Links;
CR_R e3_$}0$parser->parse($content);
I0QPs?"S}g0$parser->eof;
`&AR$~F:i-Z0parse像回调一样调用我们子程序中的方法:
ti4Re[ Ab-\0sub start51Testing软件测试网p0hb9Xh4?5T }4U?&|
{51Testing软件测试网$]Apue7j E8k(x
my($parser, $tag, $attr, $attrseq, $origtext) = @_;
3a;p e*rbj0无论什么时候parse定义了一个html标签的开始,它就调用start子程序。参数是:51Testing软件测试网7_,h!\0r2L9KS
$parser51Testing软件测试网 gg[ Ns}$x`z8q
HTML::Parser::Links 对象
x@Pzi{w.P&R:K0$tag51Testing软件测试网gb'U)Go(nC9[
html的名字,比如:h1,a,strong51Testing软件测试网Fa]3Pm}j
%$attr51Testing软件测试网a0X+t-hU[1d
一个键值对的哈希列表
/x.y`F2n0@$attrseq
*yA1G.iFiiD+U0?0在列表中的属性列表,以它们最初的排列
#jP+k2L&N(eM(J0$origtext51Testing软件测试网#Pqir,T Z
标签的原始文本51Testing软件测试网^`-AkiZ L
我们只是关心一些标签和它们的属性。如果找到一个基本的标签,我们捕获这个url,以便我们可以解析相关的连接

-a&EveZ(al0

-y2p"R-hE2B0$tag eq 'base' and51Testing软件测试网8?o f:U7D
$base = $attr->{href};51Testing软件测试网!N M3M r zz
我们找到一个(锚)标签,我们捕获href标签51Testing软件测试网7]0Q!y ^@ML

6CHO,F"ZzDB0$tag eq 'a' and $attr->{href} and51Testing软件测试网(kVbKs/K
$href = $attr->{href};51Testing软件测试网aIH x;? Jp I
还有name(为了碎片)标签

5v1c$I*i#Ps051Testing软件测试网_6p/yF#Vw

$tag eq 'a' and $attr->{name} and51Testing软件测试网iZ0Xp)t${(a
$name = $attr->{name};51Testing软件测试网k)dIy7X Rq"]1| A

2b"xT5r]y_$Qvh0Pod::Usage
aV)A!nD#J^0使用pod格式在程序中嵌入一个perl文档是很平常的。Pod::Usage这个模块解析它所找到的所有的源程序中的pod格式的文本,并把它打印出来 。这使得增加程序的说明和帮助很容易。51Testing软件测试网7O{(Ih+E
pod2usage(); # print synopsis
x;i4J[2b[h"k0pod2usage(VERBOSE=>1); # print synopsis and options
y@kQo#{'ecC0pod2usage(VERBOSE=>2); # print entire man page
[4M/Hsd8et0当命令行上有错误时,pod2usage这个模块是被经常用的,它使得在打印出pod文档以前退出程序。51Testing软件测试网p9u[/qA)F5D~+?

51Testing软件测试网6z b w,eb3jq

Packages51Testing软件测试网g&y;n9R6{$d2y\ @?

51Testing软件测试网L;~W D#_P7N

模块和包是相关的,但却又是不同的概念。一个模块是包含perl源代码的文档。一个包是包含perl子程序或者变量的名字空间。51Testing软件测试网P$FEp*@5nY*`{C
模块的作者一般都把他们的代码放在模块后面命名的包里。这样可以把它们封装起来,并避免名字的冲突。相反的,包的作者可能把包放在模块里,以便其他人可以使用这个程序。51Testing软件测试网.~1](K$jI F/P

51Testing软件测试网8W z;` y+tVzg!K

不过,我们还可以通过申明一个包,把包直接嵌入我们的程序里。
6[7dU Z2Y(Jg"p8B0V0package Spinner;
2b8n q}*Y{Sp C0我们在我们的程序里使用包是为了:51Testing软件测试网Z-}1Bt"ci
产生一个内部的界面51Testing软件测试网-l#];f'mi7rr
支持封装51Testing软件测试网#H|t$Rc3sY
避免名字的冲突51Testing软件测试网Aj%B$w2@3W'D.^
如果我们写模块的话,我们应该51Testing软件测试网ND6bX3a7]*mZ
产生一个完整的,一般性的界面
"S Sw6V_*eo3[ M0选择一个好的模块的名字51Testing软件测试网0kZ,]$`2CL L@
提供文档51Testing软件测试网"_M+V4Pf] _7R0S7c&H
然而,包仅仅在我们的程序里才是可见的,因此,我们不必太正式:我们可以以我们的方便来创建和使用包。这里有我们在linkcheck里使用的包
)GOD4UY@0Spinner51Testing软件测试网[T lRqdZ0@1z
HTML::Parser::Links
QY8P&t&rV:~0Page51Testing软件测试网pj9v3g&rb
Link51Testing软件测试网,eW$^,{w6I S^+b M5J
Spinner51Testing软件测试网 V+xO F U*j| }9|
-t 选项显示一个微调控制项。这是一个1个字符的操作,由下列字符分割:
4P-r9W"a Q!d4Cs&s0| / -51Testing软件测试网#L x.D._N+F/Y*@#x
下面是这个完整的包:
r9d4K8EM }T$A?+W0package Spinner;51Testing软件测试网4qcn M'f

51Testing软件测试网6IH:T+u!e\:^1Q

use vars qw($N @Spin);51Testing软件测试网&Y^&N { D3A-V

"N W)YVZ C/e v0@Spin = ('|', '/', '-', '');

;QXN[w#q:`^0

L/M+B`c3Fp0sub Spin51Testing软件测试网3r?g gx vs
{
n&?N6r'c0print STDERR $Spin[$N++], "r";51Testing软件测试网@@:VUf2a$m,bT
$N==4 and $N=0;
1obWPq|+d y0}51Testing软件测试网\"[GF{#I1V4y(oE~2q~

-}2h~-]0LH#W7y6?0这个包并不是太大。$N,@Spin,&Spin都在Spinner::这个包的名字空间里。为了预备这个spinner,我们这样调用 :51Testing软件测试网A*ZBvl ^3T S
Spinner::Spin();

6uYU._'] M[}051Testing软件测试网5^)j+S}/{#a

package Spinner;
XjLO)}Y7\X-u0my $N;
/b"M-Wz/[0my @Spin = ('|', '/', '-', '');
FqfR-XpVTH0如果Spinner是一个模块,这也许会更好 。然而,在这里这并不会真正提供任何的封装。File-scoping并不妨碍包的声明,所以任何的File-scoping词汇都会分享同个名字空间,从而和在整修文档的其它的File-scoping词汇产生名字冲突。51Testing软件测试网*ol7t;[i1r5mY

0u-A3A M z^ auy/_0HTML::Parser::Links51Testing软件测试网2c2Z9o'B4MVp vh7u
是HTML::Parser的一个子程序。上面展示的一些片断说明了它的基本的界面接口。在我们的子程序中,我们有额外的实时的数据来代替解析后的html页面。以及访问器(accessors)返回关于这个页面的信息。51Testing软件测试网-\1KY2OTZ0ZX

51Testing软件测试网h P:MM:W[f*P3p

新的方法是我们的构造器:51Testing软件测试网+[3Z,S"@$cJ D `'DV
sub new51Testing软件测试网?^%W i5M2B)V9ZM
{
C8pA{9vT.E#?&X0my($class, $base) = @_;

xG$B%Y)a7U*hr8x]0

IF@ A;EQ!R/A(h2q#g;v0my $parser = new HTML::Parser;
lzeH3s0$parser->{base } = $base;
gjF@6Ml0$parser->{links} = [];
cLs+XX [l0$parser->{fragment} = {};51Testing软件测试网Z d7[}*v

.Gc] ~k&nf)N6E0bless $parser, $class
xl$yj/i1]#_ R0}51Testing软件测试网%va'v|:a/d

)}:q LR@ B0为了产生一个HTML::Parser::Links对象,我们
|cdlwh N8W0产生一个HTML::Parser对象
4R sVs*x8j2JK0增加我们的即时的变量到对象51Testing软件测试网Ad u+vX.WL%q.k V
在我们的类中重新神圣引用
7CZ.P:a7ti0下面是完整的开始的方法:
V5xVzG^B _gxm0sub start
+GqUa&Im"T$cg7^0{
/Y"_&O!vi'|I0my($parser, $tag, $attr, $attrseq, $origtext) = @_;

[/Q:U$aoUs0eX1W_051Testing软件测试网U8_9F,W"B#?g

$tag eq 'base' and51Testing软件测试网/wBXw8}6W ^@(H2H
$parser->{base} = $attr->{href};

Y(@N|&SM+r051Testing软件测试网 wb.Z3qIOMG

$tag eq 'a' and $attr->{href} and do
N6^#W7@ K6v@R0{
2]Gv3uR4H0my $base = $parser->{base};51Testing软件测试网;p l}Uun"E f
my $href = $attr->{href};51Testing软件测试网/i?u1W8}L9Y*]
my $uri = new_abs URI $href, $base;
LA^)F3mX&Q%e w0push @{$parser->{links}}, $uri;51Testing软件测试网{0q b:P#?3p
};

b|iK#H3T_/mL051Testing软件测试网$h3IVe f

$tag eq 'a' and $attr->{name} and do
%|f&};Q0O&Z.LCY0{
e I(po7Nl+q [!I0my $name = $attr->{name};51Testing软件测试网$Su4q1Co,[_
$parser->{fragment}{$name} = 1;51Testing软件测试网"fJ vT&L;Q S
};51Testing软件测试网(r#o9xCA:x;^
}51Testing软件测试网g-k"E H1`LE G&A

Vu&]:S/D0我们只是关心最基础的以及一个标签。如果我们发现一个基本的元素,我们保存超连接,因此,我们可以解析相关连接。当我们发现一个连接,我们创建一个新的URI对象,把它加到连接的列表中。最后,我们找到一个片断,把它加到片断的哈希列表中。51Testing软件测试网!\z}*mLKQnjh8Z
我们有两个访问器:
"L/a)GU[0$parser->links()51Testing软件测试网/eX6j+P!bWH
如果$fragment存在于这个页面,它返回true.51Testing软件测试网 J'~]$G)t5I

#?t4\h9]]0Page51Testing软件测试网YpFU9abs
Page包得到和解析web页面。web页面是交互连接的。也许可能有很多相同连接都是指向同一个页面。然而,下载页面花费时间,因此,我们不想下载同一个页面多次。

2XuKI&b L#E2E:EJ0

p Op_)k4t g"b2vV,[0Page把web页面缓存在%Page::Content中。URL是哈希的键,页面的内容是它的值。当我们第一次请求页面的时候,Page下载它,并将它放在缓存中。任何以下的相同请求都是从缓存中读取。51Testing软件测试网h7k1Lj3``

G@5_!G(P-v0Z1_0Page包还解析web页面。解析一个web页面,并不需要网络的I/O,但是这仍然花费时间,如果我们对每个片断都检查解析的话,时间也许就会用得很多。
I(^N:mo~O5]0为了避免这个,Page包缓存了解析后的内容在%Page::Parse中。哈希的键是URL,值是一个HTML::Parser::Links对象。

-p,~.rfucWbvA051Testing软件测试网#n2j a;T6Jn8@

下面是一个外部的接口:
-hJd IF0$page = new Page $uri;
4N2FNO ~'c(Ezk:q+R0$uri = $page->uri;51Testing软件测试网h+CX:g.e"[3za-N
上一篇     目录     下一篇s = $page->links;
!z(j3k_;~@0$content = get $page;
D*BR)ge#GBXg0$parser = parse $page;

;J+Lpw QaTl/~0

4GF{;U}4Pp+^0Link51Testing软件测试网!k!k)W'z Y
Link包检查一个连接的有效性。51Testing软件测试网Gx:[e\
它的外部接口非常简单:51Testing软件测试网:N4T R ~ Vtm2dG8t
上一篇     目录     下一篇= new Link $uri;51Testing软件测试网1G)O!HiS_ ]`Gv:P
$ok =上一篇     目录     下一篇->check;51Testing软件测试网:W'p TJT%q!`
和Page包一样,Link有许多对不必要的操作的优化。
Eh'd1_\(L%k0检查连接分为两个部份。如果连接有碎片的话,
g!C7w1RJ#?7Yzln\"e0http://my.isp.com/page.html#section
#a.{ G;_&m+m7F-Z0D0那么我们就必须下整个的页面。事实上,我们甚至不必下载它。一个头部请求就可以告诉我们这个页面是否存在,而这个就是我们所关心的。51Testing软件测试网C]lXv
在 内部,check()方法分别调用check_fragment()或者check_base(),来处理这两个事件。check_fragment() 使用Page包来下载,解析包,然后,它检查看是否碎片存在于这个页面。check_base()发出一个头部请求,直接看是否存在这个页面。51Testing软件测试网5\3Ik6? K#g"~3z|
无论在哪个事件,check()缓存结果到%Link::Check。因此,我们可以不必对相同的连接检查两次。

:H5KD CA0

/D,Qk o*Ccx}u0Program
Ic i9h{!~|8^6x0由于所有的基础都由包和模块提供了,我们可以在100行代码内完成linkcheck这个程序。下面是主程序:51Testing软件测试网 UR,aW Yd;v[
package main;51Testing软件测试网 r8fw!jk5h.\^

+Z9B$p$N|5Cm}}p0my %Options;
4x7cA2m'F%DmmG0my %Checked;
nk[;R3Jm0my($Scheme, $Authority);
(ZX P7k4u0my($Pages, $Links, $Broken) = (0, 0, 0);

%n.c#O7~0L;F051Testing软件测试网t U(GY0i1Aq'{#V

getopt('vt', %Options);
Y#~L.s8fr0Help();
)z JzkO9hA1QZF0CheckPages(@ARGV);
/TX,M4`ua9z0Summary();51Testing软件测试网1wK-P A D2s

?3\(^(AD!GNT0Globals
~2l+\)I2f/s6M0我们声明我们的全局变量。这是我们的主程序。文档范围也许就属于这里。%Options保存了命令行的选项。% Checked 是一个已经检查过了的url的哈希结构。我们用它来避免由于循环连接而带来的无限的递归运算。$Authority报告当前的站点。我们用它来确定在站的 连接。$Pages, $Links 和 $Broken保存Progress()和Summary()的计数。51Testing软件测试网aIW2GV/}

51Testing软件测试网7Z%Ky"eR-ju O

CheckPages
S _OOE/WF U0当处理好了命令行的选项后,@ARGV就包含了要检查的网页的一个列表。
V+}uVF0CheckPages()产生为每个网页产生一个URI的对象,并调用 CheckPage()。
:d-W.v3{"\z#D[0sub CheckPages51Testing软件测试网2K};kXT*N
{
"n M6_!v)mC$z0my @pages = @_;
*j"nYmZ'iE4q0my @URIs = map { new URI $_ } @pages;

R_\_FC4z051Testing软件测试网 w,e}#k sU#M B

for my $uri (@URIs)
c nC rC*H-`?Y9x0{51Testing软件测试网q O6_;P)oGBzu2?7FC
$Scheme = $uri->scheme;51Testing软件测试网Y J y[ Z6B [
$Authority = $uri->authority;51Testing软件测试网.l8f+\N7T7M
CheckPage($uri);
f5ai6hZA0}51Testing软件测试网2T1a R K%[8C,b7n
}51Testing软件测试网G dH!d q5Mel

xBJ^%q3o0CheckPage
VO9|#Y9n0aK0CheckPage()检查一个网页。51Testing软件测试网 S5Ur9GPQt
sub CheckPage51Testing软件测试网u;lX+|\ z6iw
{
N)Zn?#]0my $uri = shift;51Testing软件测试网W.Wbp:`hFe

a i6F2Y1FO4}T c~.z0$Checked{$uri} and return;51Testing软件测试网4n9J*U^6bX ]/L%YKL
$Checked{$uri} = 1;
}+w)vU)C5V/r0$Pages++;51Testing软件测试网Q;`ROq
Twiddle();
'S j}._7C6xN:^%O"Z0print "PAGE $urin" if $Options{v} > 1;51Testing软件测试网;{ R hm*ru%{ a @

51Testing软件测试网p z)? w5muX!E!G

my $page = new Page $uri;
K0Y6s,GH*QZ0my上一篇     目录     下一篇s = $page->links;
HR\,^0K^x0defined上一篇     目录     下一篇s or51Testing软件测试网(k}h.]W)h*p5A
die "Can't get $urin";51Testing软件测试网D;R fo&?*C

V(Di9u+u0CheckLinks($page,上一篇     目录     下一篇s);51Testing软件测试网{-C E,H)@V5z'P0y3g.H
}51Testing软件测试网/K O P&I-`2n%{/P
51Testing软件测试网-t(|$Y np

} fJe:SzU P0经过一些内部管理后,它产生一个新的Page对象,得到在这个网页上的所有的连接,然后调用CheckLinks()。
ih5P S|!^Ioc0linkcheck检查坏的连接,但是用户所指定的那些必须存在。如果我们不能下载其中的一个,我们就停止。51Testing软件测试网 K Q'y7p6P6d ah

0t4Bt5T8V,af6x,x0CheckLinks
8~pU7^0U"T\7nD d0CheckLinks()检查在一个页面上的连接。
X4r zLmF2]0sub CheckLinks51Testing软件测试网 SR)h8r,x7u@.~}
{51Testing软件测试网Q+mt{Ob.V
my($page,上一篇     目录     下一篇s) = @_;
-m*?z,`~9d&Nv0my @links;51Testing软件测试网3?%G%b'dk*x

;`1j)y Bg0for my上一篇     目录     下一篇(@上一篇     目录     下一篇s)
%x%m*} k'w3FA3g[0{
{FK~ r"?Ep#m0上一篇     目录     下一篇->scheme eq 'http' or next;
5SKO,[i,M0my $on_site =上一篇     目录     下一篇->authority eq $Authority;51Testing软件测试网5L L/RdP'@kh ~
$on_site or $Options{o} or next;

d8fnSGg;?MG'b051Testing软件测试网`-WH.MA C i

$Links++;51Testing软件测试网 m l-?i H9nj#q
Twiddle();51Testing软件测试网(S m~~`0k Y
print "LINK上一篇     目录     下一篇n" if $Options{v} > 2;51Testing软件测试网#Y9~)Km0{DaM$UG5s2L
Link->new(上一篇     目录     下一篇)->check or do
}(p9q QwF0{
2A%M/o,RJm{0Report($page,上一篇     目录     下一篇);51Testing软件测试网x9R NB%o+Xm
next;
3Gi,C ~G W0};51Testing软件测试网G(a2U3~ y

L{4qD|5q%L'p0$on_site or next;51Testing软件测试网iD$bNS1x
上一篇     目录     下一篇->fragment(undef);51Testing软件测试网 Bt-P:Y4Q? OB
push @links,上一篇     目录     下一篇;51Testing软件测试网 ?C!wwanzg%}
}51Testing软件测试网@Q3j(P xh1Eg-Y%v

51Testing软件测试网.qV6qlZ%P3Zbp

$Options{r} or return;

SW7\}8jcVC0

&w kS bg0for my上一篇     目录     下一篇(@links)51Testing软件测试网6mfla$R$oc,}4?.G5n
{
z3T-hPI%F(cZ0CheckPage(上一篇     目录     下一篇);51Testing软件测试网~sO2TXo
}
%C'YH,r9A;g8Dqd(]0}51Testing软件测试网'Z2OJ lfxo.|+J;?

%Ef$^u1k0第一个循环检查连接。我们只检查http的连接。如果-o标志是指定的话,我们只检查站内的连接。目前的check是:51Testing软件测试网$fpZ/O f;|&`
Link->new(上一篇     目录     下一篇)->check
l{9h2tQX0如果检查失败,我们就调用report();

6},{%O%EO'`z:b4[0

&Le0VC&Ek*D d Zv k0如果检查通过,而且连接是在站点上的,我们把它加入@links数组。51Testing软件测试网 h2zW4P L
如果-r标志指定的话,我们进入第二个循环,然后我们对每个在站上的连接调用checkpage()。51Testing软件测试网tA6@$U^Q4x

51Testing软件测试网F'Q-t Y0Y5rJ:[Y

Output
xC*~$C6G/[0Report()根据-a,-v标志打印出坏的连接。51Testing软件测试网?%{!V'|.|!Y5t
Twiddle()根据-t标志打印出每个具体的进一步的报告。51Testing软件测试网_O"Q4OI5C
Summary()打印出一个最终的检查页面的报告。
WDp1R?G u051Testing软件测试网'l#T#ih9Cd

51Testing软件测试网'L)W vdRU6ec ZY

包的强大并不在于它们做任何常复杂和老练的事。尽管,一旦我们写好了它们,我们可以不必管它们怎样工作就可以使用他们。

it+eHu_C0

TAG: python

 

评分:0

我来说两句

Open Toolbar