Perl爬蟲的簡單實現

來源:互聯網
上載者:User

標籤:

由於工作中有個項目需要爬取第三方網站的內容,所以在Linux下使用Perl寫了個簡單的爬蟲。

相關工具

1. HttpWatch/瀏覽器開發人員工具

一般情況下這個工具是用不到的,但是如果你發現要爬取的內容在頁面的HTML源碼裡找不到,如有的頁面是通過AJAX非同步請求資料的,這時候就需要HttpWatch之類的工具來找到實際的HTTP請求的URL了,當然現在很多瀏覽器都有開發人員工具(如Chrome, Firefox等),這樣可以更方便查看所有請求的URL了。

2. curl/wget

這是爬蟲中最重要的工具了,作用就是類比瀏覽器的HTTP請求,從而擷取資料。一般來說就是請求一個URL來擷取相應的Web頁面的HTML源碼,還可以下載檔案。使用curl和wget都可以很方便完成這個任務。

3. Perl

把頁面爬下來後,就要從HTML中提取所需要的資訊,這時候就要用到Regex了。我用的是Perl來編寫爬蟲指令碼。之所以不使用Shell,是因為Shell的正則匹配功能還是太弱了。當然有很多指令碼語言在正則匹配方面都很強大,如Python,如果你對這些指令碼語言都不熟悉,相對而言,Perl會更容易上手一些。

4. Regex

Regex的文法大部分都是通用的,但是不用的語言又會有些小的差別,下面列舉Perl中Regex的一些重要的文法:

元字元 .

錨位 ^ $ \b

字元集  \d \w \s

量詞 * ? + {m,n}

分組 () (abc)*

擇一匹配  |  (ab|bc)

捕獲變數 ()

修飾符  /i /s /g

爬取步驟

下面以爬取某網站的手機App為例,說明一下爬取的步驟。

1. 爬取目錄

假設我需要爬取的目錄頁是http://www.anzhi.com/sort_39_1_new.html,首先找到頁索引和URL的規律,這個是很簡單的,只需要把http://www.anzhi.com/sort_39_[i]_new.html中的[i]替換為頁索引即可。接下來,需要知道一共有多少頁,才能知道爬取目錄頁什麼時候時候完成。一般頁面上會顯示共多少頁,但這裡要爬的頁面是沒有的,那怎麼辦呢?可以通過人工的方式去看一共有多少頁,還有一個方法是,爬取到某一頁發現沒有匹配的目錄項了,就說明所有目錄頁已經爬完了。

把目錄頁爬取下來後,把二級頁面的ULR通過正則匹配提取出來,寫到資料庫中,URL可以標識一個頁面的唯一性,所以要保證寫入資料的URL不重複。需要注意的是在HTML中的URL可能是相對路徑,需要把URL補全。

 

 

大部分情況是需要增量爬取的,如每天只爬取新增的目錄項,為了防止重複無效的爬取,選擇的目錄頁最好是按更新時間排序的,這樣只需要爬取有更新的前幾頁就可以了。那怎麼知道哪些目錄頁是有更新的呢?如果目錄項有更新時間的話,可以通過比較這個時間來確定。還有一種更簡單的方法是,如果某一頁所有的URL在資料庫都存在了,說明這一頁沒有新的目錄項了,可以停止爬取了。

2. 爬取詳細資料

在第一步中已經把二級頁面的URL爬取下來了,接下來就是要爬取詳細資料了,如手機App的各種資訊,和安裝包的URL。對於文字資訊是很容易在HTML中提取的,但對於安裝包URL就不是一眼能找到的,這裡的隱藏在JS中,如,在頁面裡提取到id後,就能拼出安裝包URL。對於爬取完成的URL,在資料庫中應該用狀態欄位標示其爬取完成,避免重複爬取。

 

 

 

 

3. 檔案下載

有時候我們不僅要爬取文字資訊,還需要下載圖片或檔案,比如這裡我們還需要下載和安裝包,在前一步中已經爬取了和安裝包的URL,使用curl或wget可以很方便地進行檔案下載。同樣也需要狀態欄位來標示檔案的下載狀態。

通用和擴充

1. 通用爬取介面

為了減少一些爬取的重複代碼,這裡提取了一些公用代碼,寫了一個比較通用的爬取介面,需要注意的是,由於頁面的編碼和資料編碼可能不一致,所以需要把頁面的編碼轉化成資料庫編碼,否則寫入資料就可能出現亂碼。介面說明和代碼如下:

調用方式:@results=&CrawlUrl($url, $page_charset, $expect_charset, \@regexs, \$crawl_result)

參數:URL,頁面編碼,期望編碼,Regex數組,爬取是否成功(0成功,否則失敗)

傳回值:匹配結果二維數組(一個Regex可以匹配一組資料)

 

 1 #!/usr/bin/perl 2  3 sub ParseUrl 4 { 5     my $url=$_[0]; 6     $url=~s/\[/\\\[/g; 7     $url=~s/\]/\\\]/g; 8     return $url; 9 }10 11 sub CrawlUrl12 {13     my $url=$_[0];14     my $page_charset=$_[1];15     my $expect_charset=$_[2];16     my $regex_ref=$_[3];17     my $crawl_result_ref=$_[4];18     my @regexs[email protected]$regex_ref;19     my @results;20    21     my $file=`echo -n "$url" | md5sum | awk ‘{print \$1".htm"}‘`;22     chomp($file);23     $url=&ParseUrl($url);24     `curl -o "$file" "$url"`;25     my $curl_result=`echo $?`;26     chomp($curl_result);27     if($curl_result!=0)28     {29         $$crawl_result_ref=1;30         return @results;31 }32 33     my $html="";34     if($page_charset ne "" && $expect_charset ne "" && $page_charset ne $expect_charset)35     {36         $html=`iconv -f $page_charset -t $expect_charset "$file"`;37     }38     else39     {40         $html=`cat "$file"`;41     }42     `rm -f $file`;43 44     for(my $i=0;$i<=$#regexs;$i++)45     {46         my $reg=@regexs[$i];47         my @matches=($html=~/$reg/sg);48         $results[$i]=\@matches;49     }50 51     $$crawl_result_ref=0;52     return @results;53 }

 

2. 爬蟲通用性

我們可能需要爬去同一個類型的多個網站,比如我需要爬取數十個來源的手機App,如果每個網站都寫一個特定的爬蟲,會帶來大量的編碼工作,這時候就要考慮爬蟲的通用性,如何讓一套代碼能夠適應一類網站。這裡採用的方法是把各個網站的差異化資訊作為配置儲存在資料庫,如目錄頁URL、網站編碼、各欄位Regex等,這樣爬蟲通過讀取這些配置就可以去適配不同的網站,達到一定的通用性。如果要新增一個網站的爬取,只需要增加相應的配置,而不需要修改任何代碼。

3. 多進程爬取

如果要爬取的頁面或要下載的檔案數量比較大,會比較耗時,這時候可以考慮多個進程同時進行爬取。寫一個進程式控制制模組,通過查詢資料庫中未爬取的URL和檢測當前啟用爬取的進程數,來確定是否啟用新的進程,達到對多進程爬取的控制。

4. 代理

有些網站可能會限制IP的訪問頻率,如果對網站的爬取頻率比較高,可能就會導致IP被封了,可以通過在多個Proxy 伺服器隨機切換的方式來規避這個問題。為了避免代碼重複,寫了一個使用代理的wget封裝的Shell工具。

 1 #!/bin/bash 2  3 PROXY_HOST=(Proxy 伺服器列表) 4  5 function GetProxyStr() 6 { 7     rand=$(($RANDOM%(${#PROXY_HOST[*]}+1))) 8     if [ $rand -lt ${#PROXY_HOST[*]} ] 9     then10         PROXY_STR="-e http_proxy=${PROXY_HOST[$rand]}"11     fi12 }13 14 PROXY_STR=""15 PATH_TYPE="$1"16 FILE_PATH="$2"17 URL="$3"18 19 GetProxyStr20 GetPath21 22 wget --user-agent="Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092416 Firefox/3.0.3" $PROXY_STR $PATH_TYPE "$FILE_PATH" "$URL"

 

5. 監控

還有一個問題就是,如果爬蟲是每天定時啟動並執行,在網站目錄頁URL發生變化或頁面改版了,爬取就會失敗。這就要求對這些失敗進行監控,在爬取頁面失敗或者正則匹配失敗時,通過簡訊、郵件等方式進行警示。

Perl爬蟲的簡單實現

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.