欲哭无泪啊,写了一下午的 Day 4, 最后生成 html 的时候直接按 tab 做了这么个操作:
cnhacktnt@Apollo:proxy$ pod2advent ae_proxy.pod > ae_proxy.pod 愣了一下,直接就悲剧了啊,还没 ci 到 git 里, 写的东西都没了。。。vim也退出了,连临时文件都没了。。。555,我敲了好几个小时啊。。。! 原文是《使用 AnyEvent::HTTP 的告诉代理验证程序》,现在只剩下代码了,算了,附上代码吧(见附件). 使用方式是,收集一部分待验证的 HTTP 代理地址,按如下格式存成 proxy.txt 文件: 201.75.96.153:3128 76.111.254.51:1111 211.139.10.183:80 78.154.146.173:80 200.52.133.188:8080 85.26.197.206:3128 86.110.154.82:3128 122.72.12.90:80 203.114.146.116:3128 190.201.126.171:8080 202.108.5.114:80 209.115.188.53:80 90.182.144.34:3128 204.188.215.51:3128 69.247.158.186:1586 202.154.4.23:8080 190.5.199.18:3128 123.127.98.170:80 109.75.64.30:3128 64.37.51.144:3128 然后使用如下命令: cat proxy.txt | perl ae_proxy.pl | tee ,result 就可以看到结果了,验证8000多个代理,耗时28秒。(如果待验证代理数量不足最大并发数,至少也要5秒,因为超时时间为5秒) 哭死!哭死!哭死! 血泪的教训,同学们打命令别太快了。。。。。 -- 您收到此邮件是因为您订阅了 Google 网上论坛的“PerlChina Mongers 讨论组”论坛。 要向此网上论坛发帖,请发送电子邮件至 [email protected]。 要取消订阅此网上论坛,请发送电子邮件至 [email protected]。 若有更多问题,请通过 http://groups.google.com/group/perlchina?hl=zh-CN 访问此网上论坛。
#!/usr/bin/env perl # ae_checkproxy.pl # cnhacktnt for 2011 perlchina advent use strict; use AnyEvent::HTTP; my $MAXCONN = 1000; $AnyEvent::HTTP::MAX_RECURSE = 0; # 置0,意思是如果有URL转向发生,直接忽略 $AnyEvent::HTTP::MAX_PER_HOST = $MAXCONN; # 默认 AnyEvent::HTTP 对同一个主机同时最多只会发起4个连接 # 而我们每次都是访问 www.google.co.jp, 但是是通过大量的代理去访问的,所以为了 # 让我们可以同时测试大量的代理,就把这个值设为和最大并发连接数一样的值就好了 my $target = "http://www.google.co.jp"; my $start = time; my $cv = AnyEvent->condvar; # 创建事件的条件变量,你可以把它当成是事件监督员,当我们通过 checkproxy() 创建 # 了大量 HTTP 连接去访问 www.google.co.jp 时,监督员的作用就是确保这些连接在干活 # 的时候,我们的主程序不会提早退出,另外,当所有访问都结束(或超时)后,这个监督员 # 能收到信号,告诉主程序今天的事儿已经全都干完了,可以下班收工了。 checkproxy(*STDIN); # 从标准输入读取代理服务器地址,开始发起大量 HTTP 请求,这里的请求是非阻塞的,我们 # 可以当这些请求是并发的 $cv->recv; # 监督员站岗,等待有信号告诉他,所有的请求都结束了(或超时),事儿干完了,可以收工。 # 当执行 $cv->recv 后,主程序就阻塞在这里,等待发出去的 HTTP 请求结束(或超时)。 my $end = time; print "time: ".($end - $start)."\n"; # 用来通过 HTTP 代理服务器发起 HTTP 请求的子程序 sub checkproxy { my $fh = shift; # 取得 STDIN 标准输入句柄 while($AnyEvent::HTTP::ACTIVE < $MAXCONN) { # 如果当前活动连接数小于我们设置的最大并发连接数,我们就继续 # 从 STDIN 里取出待验证的代理服务器地址,并增加 HTTP 请求。 my $proxy = <$fh>; defined $proxy or last; $proxy =~ s/\s//g; next unless $proxy =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}$/; http_request( # 通过 http_request 发出具体的 HTTP 请求 GET => $target, # 请求类型为 GET,目标URL就是 $target headers => { "user-agent" => "Mozilla/5.0" }, timeout => 5, # 5秒超时,超过5秒的代理太慢了:-P proxy => [split(/:/, $proxy)], # 设置要检测的代理服务器地址及端口 on_header => sub { # 当读到目标服务器返回的头信息时,会触发 on_header 事件 # 这里的 on_header 事件是一个匿名子程序,它的第一个参数 # 就是根据目标服务器返回的头信息所构造的一个哈希表 if ($_[0]{'server'} eq "gws") { # 如果头信息中 Server 字段是 gws,则当前代理是可用的,否则不行 print "$proxy ok!\n"; } else { print "$proxy failed!\n"; } return 0; # 返回0的意思就是立即终止该连接,我们只需要头信息就够了 }, sub { checkproxy($fh) } # 每个 http_request 结束后都会调用这个子程序 # 这样当一个请求结束(或超时)后,我们可以递归地调用 checkproxy() 来 # 立即发起新的请求。 ); } $cv->send if ($AnyEvent::HTTP::ACTIVE == 0 && eof($fh)); # 如果当前没有活动连接,且没有额外的代理服务器需要验证了,就通过 $cv->send 发送 # 信号,告诉监督员事儿都干完了,可以收工了。 }
