分享一下我老師大神的人工智能教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
上一篇博客,介紹了Linux 抓取網頁的實例,其中在抓取google play國外網頁時,需要用到代理服務器
代理的用途
其實,除了抓取國外網頁需要用到IP代理外,還有很多場景會用到代理:
代理的原理
代理服務的原理是本地瀏覽器(Browser)發送請求的數據,不是直接發送給網站服務器(Web Server)
而是通過中間的代理服務器(Proxy)來代替完成,如下圖:
IP代理篩選系統
問題分析
分析解決一個實際問題時,將會遇到各種問題,有些問題甚至是方案設計之初都難以想到的(如代理IP抓取網頁速度過慢),我的體會是:動手實踐比純理論更重要!
方案設計
總體思路:尋找並縮小篩選的IP代理源——》檢測代理IP是否可用——》IP可用則記錄下來抓取網頁——》代理IP故障則重新篩選——》繼續抓取網頁——》完成
1、IP代理源
選擇有兩個原則:可用和免費,經過深入調研和搜索,最後確定兩個網站的IP代理比較靠譜:freeproxylists.net 和 xroxy.com
從國家數、IP代理數量、IP代理可用率、IP代理文本格式等多方面綜合考量,IP代理源主要選自前者,後者作爲補充,在後來的實踐測試表明這種初選方案基本滿足需求
2、文本預處理
從freeproxylists.net獲取的代理IP,有IP地址、端口、類型、匿名性、國家...等等參數,而我們需要的僅僅是IP+Port,因此需要對初選的IP代理源做文本預處理
文本空格處理命令:
sed -e "s/\s\{2,\}/:/g" $file_input > $file_split
sed -i "s/ /:/g" $file_split
合併代理IP(ip:port)命令:
proxy_ip=$(echo $line | cut -f 1 -d ":")
proxy_port=$(echo $line | cut -f 2 -d ":")
proxy=$proxy_ip":"$proxy_port
3、檢測IP代理
文本預處理代理IP爲標準格式(ip:port)後,需要進行代理IP篩選測試,看哪些可用哪些不可用(由於獲取的IP代理源有一些不能使用或下載過慢,需要過濾掉)
curl抓取網頁檢測IP代理是否可用命令:
cmd="curl -y 60 -Y 1 -m 300 -x $proxy -o $file_html$index $url_html"
$cmd
4、保存IP代理
檢測一個代理IP是否可用,如果可用,則保存下來。
判斷一個代理IP是否可用的標準,是通過判斷步驟3中下載的網頁($file_html$index)是否有內容,具體命令如下:
if [ -e ./$file_html$index ]; then
echo $proxy >> $2
break;
fi
5、IP代理抓取網頁
利用步驟4保存的代理IP抓取網頁,通過代理IP抓取12國排名網頁和遊戲網頁,具體命令如下:
proxy_cmd="curl -y 60 -Y 1 -m 300 -x $proxy -o $proxy_html $proxy_http"
$proxy_cmd
6、IP代理故障
IP代理故障有多種情況,在上面的問題分析中已經列出了幾條,下面將詳細分析如下:
a、代理IP在抓取的網頁過程中,突然失效,無法繼續完成網頁抓取
b、代理IP沒有失效,但是抓取網頁很慢,無法在一天24小時內完成網頁抓取,導致無法生成遊戲排名每日報表
c、代理IP全部失效,無論是輪詢檢測一遍或多遍後,都無法完成當天的網頁抓取任務
d、由於整個網絡路由擁塞,導致代理IP抓取網頁很慢或無法抓取,誤判爲代理IP全部失效,如何恢復和糾正
7、重新檢測IP代理
在網頁抓取過程中,面對步驟6的IP代理故障,設計一套合理、高效的代理IP抓取恢復機制,是整個IP代理篩選系統的核心和關鍵
其故障恢復的輪詢篩選流程如下:
上圖流程中,需要注意幾點:
a、首先檢測上次IP代理,這是因爲上次(昨天)的IP代理完成了所有網頁抓取任務,其可用概率相對比較高,所以優先考慮其今天是否也可用。如果不可用,則另選其它
b、如果上次代理IP今天不可用,則重新遍歷檢測代理IP源,一旦檢測到有可用,則不再循環下去,更新可用IP代理並保存其在IP源的位置,方便下次從此處開始遍歷
c、如果流程b新選的代理IP突然失效或網速過慢,則在b記錄的IP源位置繼續篩選後面的代理IP是否可用。如可用,則繼續抓取網頁;如不可用,則再次遍歷整個IP源
d、如果再次遍歷了整個代理IP源,仍然沒有代理IP可用,則反覆輪詢遍歷整個代理IP源,直到有代理IP可用或今天24時過去(即今日整天都找不到可用代理IP)
e、對流程d中全部代理IP失效且整日找不到可用代理IP,無法完成當日網頁抓取這一特殊情況,在次日凌晨重新啓動網頁抓取總控腳本前,需要先殺死流程d在後臺的循環進程,防止今日和次日的兩個後臺網頁抓取程序同時運行(相當於兩個異步的後臺抓取進程),造成抓取網頁排名數據陳舊或錯誤、佔用網速帶寬等。其實現殺死當日僵死的後臺抓取進程,請見上一篇博客 Linux 抓取網頁實例 ——》 自動化總控腳本 ——》kill_curl.sh腳本,其原理是kill -9 進程號,關鍵腳本代碼如下:
while [ ! -z $(ps -ef | grep curl | grep -v grep | cut -c 9-15) ]
do
ps -ef | grep curl | grep -v grep | cut -c 15-20 | xargs kill -9
ps -ef | grep curl | grep -v grep | cut -c 9-15 | xargs kill -9
done
8、完成網頁抓取
通過上述的IP代理篩選系統,篩選出12國可用的免費代理IP,完成每日12國網頁排名和遊戲網頁的抓取任務
之後,就是對網頁中游戲屬性信息的進行提取、處理,生成每日報表、郵件定時發送和趨勢圖查詢等,詳見我的上一篇博客:Linux 抓取網頁實例
腳本功能實現
IP代理篩選的基本過程比較簡單,其數據格式和實現步驟如下:
首先,到 freeproxylists.net 網站,收集可用的代理IP源(以美國爲例),其格式如下:
接着,清除上圖中的空格,具體實現命令請見上面【方案設計】——》【2、文本預處理】,文本預處理後的格式如下:
然後,測試上圖文本預處理後的代理IP是否可用具體命令請見上面【方案設計】——》【3、檢測IP代理】,檢測代理IP後的格式如下:
下面介紹shell腳本實現文本預處理和網頁篩選的詳細步驟
1、文本預處理
# file processlog='Top800proxy.log'dtime=$(date +%Y-%m-%d__%H:%M:%S)function select_proxy(){ if [ ! -d $dir_split ]; then mkdir $dir_split fi if [ ! -d $dir_output ]; then mkdir $dir_output fi if [ ! -e $log ]; then touch $log fi echo "================== Top800proxy $dtime ==================" >> $log for file in `ls $dir_input`; do echo $file >> $log file_input=$dir_input$file echo $file_input >> $log file_split=$dir_split$file"_split" echo $file_split >> $log rm -rf $file_split touch $file_split sed -e "s/\s\{2,\}/:/g" $file_input > $file_split sed -i "s/ /:/g" $file_split file_output=$dir_output$file"_out" echo $file_output >> $log proxy_output "$file_split" "$file_output" echo '' >> $log done echo '' >> $log}
腳本功能說明:
if語句,判斷並創建用於保存處理IP源中間結果的文件夾$dir_split 和 $dir_output ,前者保存【腳本功能實現】中文本預處理後的文本格式,後者保存檢測後可用的代理IP
sed -e語句,把輸入文本(腳本功能實現的圖1)中的多個空格,修改爲一個字符「:」
sed -i語句,進一步把文本中的多餘空格,轉換爲一個字符":"
轉換的中間結果,都保存到文件夾 $dir_split
後面的file_output三行,以文件參數的形式"$file_split",傳給代理IP檢測函數(proxy_output),篩選出可用的代理IP
2、代理IP篩選
index=1file_html=$dir_output"html_"cmd=''function proxy_output(){ rm -rf $2 touch $2 rm -rf $file_html* index=1 while read line do proxy_ip=$(echo $line | cut -f 1 -d ":") proxy_port=$(echo $line | cut -f 2 -d ":") proxy=$proxy_ip":"$proxy_port echo $proxy >> $log cmd="curl -y 60 -Y 1 -m 300 -x $proxy -o $file_html$index $url_html" echo $cmd >> $log $cmd if [ -e ./$file_html$index ]; then echo $proxy >> $2 break; fi index=`expr $index + 1` done < $1 rm -rf $file_html*}
腳本功能說明:
代理IP篩選函數proxy_output頭三行,清除先前篩選的結果,作用是初始化
while循環,主要是遍歷以參數形式傳入的文本預處理後的"$file_split",檢測代理IP是否可用,其步驟如下:
a、首先拼接出代理IP的(ip:port)格式,其實現是通過cut分割文本行,然後提取出第一個字段(ip)和第二個字段(port),拼接成(ip:port)
b、通過curl構造出抓取網頁的命令cmd,執行網頁下載命令$cmd
c、通過檢測網頁下載命令執行後,是否生成了網頁下載文件,來判斷拼接出的代理IP($proxy)是否有效。若有效,則保存此代理IP到"$file_output"中並退出遍歷(break)
d、如果當前代理IP無效,則讀取下一行代理IP,繼續檢測
代理IP抓取網頁實例:
利用上面的代理IP系統,篩選出來免費代理IP,抓取遊戲排名網頁的實例如下(腳本片段):
index=0 while [ $index -le $TOP_NUM ] do url=$url_start$index$url_end url_cmd='curl -y 60 -Y 1 -m 300 -x '$proxy' -o '$url_output$index' '$url echo $url_cmd date=$(date "+%Y-%m-%d___%H-%M-%S") echo $index >> $log echo $url"___________________$date" >> $log $url_cmd # done timeout file seconds=0 while [ ! -f $url_output$index ] do sleep 1 echo $url_output$index"________________no exist" >> $log $url_cmd seconds=`expr $seconds + 1` echo "seconds____________"$seconds >> $log if [ $seconds -ge 5 ]; then select_proxy url_cmd='curl -y 60 -Y 1 -m 300 -x '$proxy' -o '$url_output$index' '$url seconds=0 fi done index=`expr $index + 24` done
腳本功能說明:
上面shell腳本代碼片段,是用來抓取網頁的,其中最核心的一行是 select_proxy
其作用是上述介紹過的,當代理IP突然失效、抓取網頁過慢、全部代理IP都無效、或無法完成當天的網頁抓取工作,用來重新篩選代理IP,恢復網頁抓取的一段核心代碼
其設計實現流程,如上述的【方案設計】——》【7、重新檢測IP代理】,其實現原理可參照上述的【代理IP篩選】的腳本,在此不再貼出其源腳本代碼