Perl 是 Practical Extraction and Report Language 的缩写,可翻译为 "实用报表提取语言"。

Perl 是高级、通用、直译式、动态的程序语言。

Perl 所有的字母都是小写的。一般“Perl”有大写的 P,是指语言本身,而“perl”小写的 p,是指程序运行的解释器。

Perl是一种功能丰富的计算机程序语言,运行在超过100种计算机平台上,适用广泛,从大型机到便携设备,从快速原型创建到大规模可扩展开发。

Perl最初的设计者为拉里·沃尔(Larry Wall),于1987年12月18日发表。

Perl借取了C、sed、awk、shell scripting以及很多其他程序语言的特性。其中最重要的特性是它内部集成了正则表达式的功能,以及巨大的第三方代码库CPAN。简而言之,Perl像C一样强大,像awk、sed等脚本描述语言一样方便,被称之为“一种拥有各种语言功能的梦幻脚本语言”、“Unix 中的王牌工具”。

 

perl 官网: https://www.perl.org

perl 源码: http://www.cpan.org/src/

cpan官网: http://www.cpan.org

perlbrewhttp://perlbrew.pl

 

Perl 特点

Perl是一门解释型程序,开放源码,免费软件

Perl能在绝大多数操作系统运行,可以方便地向不同操作系统迁移,支持Windows、Linux、Mac OS X

Perl 是一种能完成任务的语言。从一开始,Perl 就设计成可以把简单工作简单化,同时又不失去处理困难问题能力的语言。它可以很容易操作数字、文本、文件、目录,计算机和网络,特别是程序的语言。这种语言应该很容易运行外部的程序并且扫描这些程序的输出获取感兴趣的东西。而且它还应该很容易能把这些你感兴趣的东西交给其它程序做特殊的处理。当然,这种语言还应该很容易在任何现代的操作系统上可以移植地编译和运行。

Perl 优点

  • 相比C、Pascal这样的"高级"语言而言,Perl语言直接提供泛型变量、动态数组、Hash表等更加便捷的编程元素。
  • Perl具有动态语言的强大灵活的特性,并且还从C/C++、Basic、Pascal等语言中分别借鉴了语法规则,从而提供了许多冗余语法。
  • 在统一变量类型和掩盖运算细节方面,Perl做得比其他高级语言(如:Python)更为出色。
  • 由于从其他语言大量借鉴了语法,使得从其他编程语言转到Perl语言的程序员可以迅速上手写程序并完成任务,这使得Perl语言是一门容易用的语言。
  • Perl 是可扩展的,我们可以通过CPAN("the Comprehensive Perl Archive Network"全面的 Perl 存档网络)中心仓库找到很多我们需要的模块。
  • Perl 的 mod_perl 的模块允许 Apache web 服务器使用 Perl 解释器。

Perl 运行平台

  • Unix (Solaris, Linux, FreeBSD, AIX, HP/UX, SunOS, IRIX etc.)
  • Win 9x/NT/2000/
  • WinCE
  • Macintosh (PPC, 68K)
  • Solaris (x86, SPARC)
  • OpenVMS
  • Alpha (7.2 and later)
  • Symbian
  • Debian GNU/kFreeBSD
  • MirOS BSD
  • ...

 

Perl 安装

1)命令安装

sudo apt-get -y install perl                         // Debian and Ubuntu

sudo yum -y install perl                           // RedHat、CentOS
sudo yum -y install perl-CPAN  
sudo yum -y install cpan

curl -L http://xrl.us/installperlosx | bash   // Mac OS X(原理是通过perlbrew安装)

 

2)源码安装推荐

wget http://www.cpan.org/src/5.0/perl-5.26.0.tar.gz
tar -xzf perl-5.26.0.tar.gz
cd perl-5.26.0
./Configure -des -Dprefix=$HOME/localperl
sudo make
sudo make test
sudo make install

 

Perl 语法

变量定义,以$号开头,如:$num = 1;

数组定义,以@开头,如:@array = (1, 2, 3);

数组元素调用 $array[index],其中index表示数组下标,如上例,$array[0]的值是1

字典(哈希)定义,以%开头,如:%hash=("a", 1, "b", 2);

散列调用 %hash,其中keys表示键值,多用字符串表示,注意hash的key必须具有唯一性,但value可以不唯一,为此hash的key经常被用来做唯一化处理,如上例中的"a", "b", values是keys对应的值,如1,2。$hash{"b"}的值是2。

Perl 更多语法请参见:http://www.runoob.com/perl/

 

Perl 使用

1. hello.pl 示例

a)perl 命令行

$ perl -e 'print "hello mimvp.com\n"'           
hello mimvp.com

 

b)perl 文件

vim hello.pl 

#!/usr/bin/env perl 
print "hello mimvp.com\n";

执行命令:

$ perl mimvp-proxy-perl.pl 
hello mimvp.com

 

2. 变量、数组、字典(哈希)

#!/usr/bin/env perl 
# 
# mimvp.com
# 2017-03-28


## 普通变量
$num = 2066;             	# 整型
$name = "mimvp.com";      	# 字符串
$salary = 1000000.52;     	# 浮点数

print "num = $num\n";			# 2066
print "name = $name\n";			# mimvp.com
print "salary = $salary\n";		# 1000000.52


## 数组变量
@num_array = (20, 30, 40);             
@name_array = ("proxy.mimvp.com", "domain.mimvp.com", "money.mimvp.com");

print "\$num_array : @num_array\n";					# 20 30 40
print "\$num_array[0] = $num_array[0]\n";			# 20
print "\$num_array[2] = $num_array[2]\n";			# 40
print "\$num_array[-1] = $num_array[-1]\n";			# 40
print "\$name_array[1] = $name_array[1]\n";			# domain.mimvp.com
print "\$name_array[-1] = $name_array[-1]\n";		# money.mimvp.com


## 哈希变量
%data_dict = ('proxy', 20, 'domain', 30, 'money', 40);

print "\$data_dict{'proxy'} = $data_dict{'proxy'}\n";		# 20
print "\$data_dict{'domain'} = $data_dict{'domain'}\n";		# 30
print "\$data_dict{'money'} = $data_dict{'money'}\n";		# 40


## 
@name_array = ('taobao', 'tencent', 'baidu', 'mimvp');

@copy_array = @name_array; 		# 复制数组
$array_size = @copy_array;   	# 返回数组元素个数

print "copy_array : @copy_array\n";		# taobao tencent baidu mimvp
print "array_size : $array_size\n";		# 4

 

3. 局部变量 my

perl 像C、Java等语言一样,变量有作用域的概念,比如一个在函数中定义的变量,属于局部变量,在函数外是无效的。

perl 定义的变量默认是全局变量,当在定义变量时使用 my $mimvp,那么 $mimvp 的作用域就限定在当前函数体或当前for循环中,属于局部变量。

vim test-my.pl

#!/usr/bin/env perl 
# 
# mimvp.com
# 2017-03-28


my $mimvp = "mimvp.com";
print "$mimvp\n";				# mimvp.com

myFunction();
print "$mimvp\n";				# mimvp.com

sub myFunction {
	print "$mimvp\n";			# mimvp.com
	
	my $mimvp = "mimvp.com in myFunction";
	print "$mimvp\n";			# mimvp.com in myFunction
	mySub();
}

sub mySub {
	print "$mimvp\n";			# mimvp.com
	
	my $mimvp = "mimvp.com in mySub";
	print "$mimvp\n";			# mimvp.com in mySub
}

运行命令:

$ perl test-my.pl           
mimvp.com
mimvp.com
mimvp.com in myFunction
mimvp.com
mimvp.com in mySub
mimvp.com

 

4. 爬取网页

Perl 爬取网页,涉及到CGI,简单介绍如下

CGI(Common Gateway Interface,通用网关接口),它是一段程序,运行在服务器上,如Tomcat、Apache httpd、tornado等HTTP服务器,处理客户端请求,并返回数据给客户端HTML页面的接口。CGI程序可以是Python、Perl、Python、Shell脚本,也可以是C、C++、Java等程序。

CGI是如何工作的,我们可以从在网页上点击一个链接或URL的流程:

  • 1、使用你的浏览器访问URL并连接到HTTP web 服务器。
  • 2、Web服务器接收到请求信息后会解析URL,并查找访问的文件在服务器上是否存在,如果存在返回文件的内容,否则返回错误信息。
  • 3、浏览器从服务器上接收信息,并显示接收的文件或者错误信息。

CGI架构图

perl-an-zhuang-yu-kai-fa-01

 

爬取网页示例

vim  mimvp-spider.pl

#!/usr/bin/env perl 
# 
# mimvp.com
# 2017-03-28


use CGI;
use strict;
use LWP::UserAgent;
use LWP::ConnCache;

my $browser = LWP::UserAgent->new();
$browser->env_proxy();
$browser->timeout(30);

my $browser_agent = $browser->agent();				# libwww-perl/6.05
print "$browser_agent\n";

$browser->agent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36');
$browser_agent = $browser->agent();					# Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
print "$browser_agent\n";

my $url = "http://proxy.mimvp.com/exist.php";		# 爬取的网址
my $response = $browser->get($url);  				# HTTP::Response=HASH(0x7f8c9b9bd948)
print "$response\n";

my $is_success = $response->is_success();			# 1
my $content_type = $response->content_type();		# text/html
my $content = $response->content();					# 网页正文
my $content_length = length($content);				# 网页正文长度

print "$is_success\n";
print "$content_type\n";
print "$content_length\n";
# print "$content\n";



if($content =~ m/proxy.mimvp.com/i) {
      print "I love mimv.com\n",
} 
elsif($content =~ m/mimvp.com/i) {
      print "I love proxy.mimv.com\n",
} 
else {
      print "I love the whole world.\n";
}

执行命令:

perl mimvp-spider.pl 

运行结果:

libwww-perl/6.05
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
HTTP::Response=HASH(0x7f8f272074e8)
1
text/html
77593
I love proxy.mimv.com

 

Perl 代理设置

Perl 支持 http、https 代理,其中 https 代理利用 connect 实现,详见代码

#!/usr/bin/env perl 
#
# Perl 支持 http、https
#
# 米扑代理示例:
# http://proxy.mimvp.com/demo2.php
# 
# 米扑代理购买:
# http://proxy.mimvp.com
# 
# mimvp.com
# 2017-03-28


use CGI;
use strict;
use LWP::UserAgent;


our %proxy_http = ("http", "http://138.68.165.154:3128");
our %proxy_https = ("https", "https://113.106.94.213:80");
our %proxy_connect = ("https", "connect://173.233.55.118:443");

our $mimvp_url = "http://proxy.mimvp.com/exist.php";
our $mimvp_url2 = "https://proxy.mimvp.com/exist.php";



## http 
sub test_http {
	my ($url, %proxy) = @_;
	
	print "proxy  : $proxy{'http'}\n";
	print "https  : $proxy{'https'}\n";
	print "url : $url\n";
	
	my $browser = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
	$browser->env_proxy();
	
# 	# 设置的代理格式
# 	$browser->proxy('http', 'http://138.68.165.154:3128');  
# 	$browser->proxy(['http','ftp'], 'http://138.68.165.154:3128');  
	$browser->proxy(%proxy);
	$browser->timeout(30);
	$browser->agent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36');
	
	my $response = $browser->get($url);  				# 爬取的网址
	my $is_success = $response->is_success();			# 1
	my $content_type = $response->content_type();		# text/html
	my $content = $response->content();					# 网页正文
	my $content_length = length($content);				# 网页正文长度
	
	print "$is_success\n";
	print "$content_type\n";
	print "$content_length\n";
	print "$content\n";
}



## https (NO Success)
## error info : LWP::Protocol::https::Socket: SSL connect attempt failed because of handshake problems SSL wants a read first at /System/Library/Perl/Extras/5.18/LWP/Protocol/http.pm line 51.
sub test_https {
	my ($url, %proxy) = @_;
	
	print "proxy  : $proxy{'http'}\n";
	print "https  : $proxy{'https'}\n";
	print "url : $url\n";
	
	BEGIN {
		$ENV{HTTPS_PROXY} = 'https://173.233.55.118:443'; 
# 		$ENV{HTTPS_PROXY_USERNAME} = ; 
# 		$ENV{HTTPS_PROXY_PASSWORD} = ; 
		$ENV{HTTPS_DEBUG} = 1;
		$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
	}
	
	my $browser = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
	$browser->env_proxy();
	
# 	# 设置的代理格式
# 	$browser->proxy(%proxy);	# NO USE
	$browser->timeout(30);
	$browser->agent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36');
	
	my $req = new HTTP::Request('GET', $url);			# 爬取的网址
	my $response = $browser->request($req);
	
	my $is_success = $response->is_success();			# 1
	my $content_type = $response->content_type();		# text/html
	my $content = $response->content();					# 网页正文
	my $content_length = length($content);				# 网页正文长度
	
	print "$is_success\n";
	print "$content_type\n";
	print "$content_length\n";
	print "$content\n";
}



## https (connect)
## 1. download LWP-Protocol-connect (wget http://search.cpan.org/CPAN/authors/id/B/BE/BENNING/LWP-Protocol-connect-6.09.tar.gz)
## 2. tar zxvf LWP-Protocol-connect-6.09.tar.gz 
##    cd LWP-Protocol-connect-6.09
##    perl Makefile.PL
##    make
##    sudo make install
sub test_connect {
	my ($url, %proxy) = @_;
	
	print "proxy  : $proxy{'http'}\n";
	print "https  : $proxy{'https'}\n";
	print "url : $url\n";
	
	my $browser = LWP::UserAgent->new();
	$browser->env_proxy();
	
# 	# 设置的代理格式
# 	$browser->proxy('https', 'connect://173.233.55.118:443'); 
	$browser->proxy(%proxy);
	$browser->timeout(30);
	$browser->agent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36');
	
# 	my $req = new HTTP::Request('GET', $url);
# 	my $response = $browser->request($req);
	my $response = $browser->get($url);  				# 爬取的网址
	my $is_success = $response->is_success();			# 1
	my $content_type = $response->content_type();		# text/html
	my $content = $response->content();					# 网页正文
	my $content_length = length($content);				# 网页正文长度
	
	print "$is_success\n";
	print "$content_type\n";
	print "$content_length\n";
	print "$content\n";
}


test_http($mimvp_url, %proxy_http);			# http
test_https($mimvp_url2, %proxy_https);		# https (NO Success)
test_connect($mimvp_url2, %proxy_connect);	# https (connect)



## 执行命令
## perl -d mimvp-proxy-perl.pl
	  

 

 

参考推荐:

HTTPS Proxy and LWP::UserAgent (StackOverflow)

CentOS 安装 perl

Ruby 安装与开发

Python scrapy 安装与开发

Python requests 安装与开发

Python pyspider 安装与开发

Python3 urllib 用法详解

PhantomJS 安装与开发

Node.js 安装与开发