perl登陸各類網站的原理與實現javascript
tkorays(tkorays@hotmail.com)html
小孩子才踐行大道理,大人只會講。java
寫腳本抓取某個頁面內容很簡單,可是每每事情沒那麼簡單。有些頁面必須是要登陸才能查看的,好比你想抓取選課系統中本身的成績?因此,下面介紹下使用perl登陸網站的原理,以及實現。c++
原理shell
若是你瞭解一些http原理的話,這就很好理解了。使用瀏覽器打開網頁無非就是:你發送請求,而後服務器響應,給你所須要的頁面內容。固然這些請求和相應都是有必定規律的。apache
先說瀏覽器發送請求。瀏覽器
請求經常使用有POST和GET兩種,撇去細節不談,二者有個很大的區別就是POST傳遞的參數是不顯示在url中,而GET方式傳遞的參數會在url中顯示。而咱們登陸有表單提交,常常要用POST和GET。好比我在開源中國搜索apache:服務器
這個表單是GET方式的,因此url中會有參數。cookie
那麼,是否瀏覽器就發送了這麼多數據給服務器了呢,答案固然是,否。如上圖中,點開頭消息,請求頭以下:併發
其實還發送了這些數據,因此若是你要本身用c/c++等實現,不要忘記發送必要的數據哦。(提示,每一個數據使用\r\n分割的)若是你使用perl,有現成的庫,你不須要關注太多細節的,只須要知道,可能須有cookie!
所以,請求你只須要關注,請求的參數以及可能須要的cookie。
接下來講相應。
一樣,瀏覽器返回的html網頁不止是你查看源代碼看到的那些,還包括響應頭。
相應頭和請求頭差很少,主要高速瀏覽器該怎麼處理這些相應。注意上面的Content-Type沒,後面的text/html表示返回的數據是html格式的。(返回javascript時,content-type是application/x-javascript
)。固然並非全部的相應都有響應頭,並且大多時候,你也不須要關注它。這裏我只是湊字數說說,徹底能夠忽略。返回的頁面,你徹底只須要獲取頭後面的東西(反正你也知道返回的是html仍是javascript,何須還判斷呢)。
cookies是保存在瀏覽器端的一些小數據,能夠用於保存一些信息。它其實就是一些鍵值對。不少時候,服務器會生成一些數據給瀏覽器,這些在以後的通訊過程當中是很重要的。所幸的是,perl有現成的庫供咱們管理cookies,若是你要一步步實現,就頭大了。
對了,還要注意的是url編碼問題,有時候會出現。
實現
說了原理固然要說實現了,否則我就是欺騙讀者的感情了。
perl中使用到的主要包有LWP,會用到它的UserAgent、Cookies、Response等類。這些類有不明白的地方能夠查看cpan。
這裏咱們須要模擬一個瀏覽器的行爲,因此要建立一個UserAgent對象。
my $ua = LWP::UserAgent->new; $ua->agent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0");
這樣,請求頭裏面的瀏覽器就變成了火狐,服務器會覺得咱們是使用火狐呢。
不能忘記cookies哦。
my $cookie_jar = HTTP::Cookies->new( file=>'lwp_cookies.txt', autosave=>1, ignore_discard=>1); $ua->cookie_jar($cookie_jar);
以後調用UserAgent的post和get方法,想幹什麼就幹甚麼。
若是你看的不是很明白,下面給出一個登陸人人併發狀態的例子,好好領悟吧。有註釋哦:
#!/usr/bin/perl # Copyright 2014 tkorays. All rights reserved. # author tkorays # email tkorays@hotmail.com use strict; use warnings; use LWP; use LWP::Simple; use LWP::UserAgent; use HTTP::Cookies; use HTTP::Headers; use HTTP::Response; use Encode; use URI::Escape; use URI::URL; my $email = '***@**.com'; my $password = '***'; my $domain = 'renren.com'; my $hostid=''; my $requestToken=''; my $rtk=''; my $channel='renren'; my $ua = LWP::UserAgent->new; $ua->agent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0"); my $cookie_jar = HTTP::Cookies->new( file=>'lwp_cookies.txt', autosave=>1, ignore_discard=>1); $ua->cookie_jar($cookie_jar); my $login_url = 'http://www.renren.com/PLogin.do'; # 這裏面沒有判斷是否須要驗證碼,聰明的你學完後確定知道怎麼搞定的 # 人人是post登錄的,第一個參數是登錄的地址,第二個參數是一個匿名hash my $res = $ua->post($login_url,{ 'email'=>$email, 'password'=>$password, 'domain'=>$domain}); my $homepage; # 判斷響應頭裏面的location,肯定是否登錄成功 if($res->header('Location') eq 'http://www.renren.com/Home.do'){ print 'login ok...',"\n"; $homepage = $ua->get('http://www.renren.com/home'); }else{ exit; } # 做爲福利,下面仍是貼上,髮狀態的吧,後面就不註釋了 ##################################### if($homepage->is_success){ my $pagect = $homepage->content; $pagect =~ /id\s:\s"(\d+)"/g; $hostid = $1; $pagect =~ /requestToken\s:\s'(.+)'/g; $requestToken = $1; $pagect =~ /_rtk\s:\s'(.+)'/; $rtk = $1; }else{ exit; } my $purl = 'http://shell.renren.com/'.$hostid.'/status'; my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime(); $year +=1900; $mon++; my $postret = $ua->post($purl,{ 'content'=>"renren test,by perl script,author:tkorays,date:$year-$mon-$day $hour:$min:$sec.", 'hostid'=>$hostid, 'requestToken'=>$requestToken, '_rtk'=>$rtk, 'channel'=>$channel}); if($postret->is_success){ print 'send ok...',"\n"; }else{ print 'fuck!'; }
有驗證碼怎麼辦?UserAgent的get、方法獲取啊。
給個簡單的例子吧:
my $res = $ua->get($url.'/GenImg'); if(!$res->is_success){ return 0; } open(FILE_HANDLE,'>img.jpg'); binmode FILE_HANDLE; print FILE_HANDLE $res->content; close FILE_HANDLE;
上面的代碼把驗證碼存爲圖片。因此驗證碼問題就解決了。
GO
問題都解決了,你就趕快行動?