Linux IP代理筛选系统(shell+proxy)

上一篇博客,介绍了Linux 抓取网页的实例,其中在抓取google play国外网页时,需要用到代理服务器


代理的用途

其实,除了抓取国外网页需要用到IP代理外,还有很多场景会用到代理:

  • 通过代理访问一些国外网站,绕过被某国防火墙过滤掉的网站
  • 使用教育网的代理服务器,可以访问到大学或科研院所的内部网站资源
  • 利用设置代理,把请求通过代理服务器下载缓存后,再传回本地,提高访问速度
  • 黑客发动攻击时,可以通过使用多重代理来隐藏本机的IP地址,避免被跟踪(当然,魔高一尺,道高一丈,终究会被traced)


代理的原理

代理服务的原理是本地浏览器(Browser)发送请求的数据,不是直接发送给网站服务器(Web Server)

而是通过中间的代理服务器(Proxy)来代替完成,如下图:

Linux IP代理筛选系统(shell+proxy)_第1张图片



IP代理筛选系统

问题分析

  • 因为不可能每天都遍历测试全球2^32数量级的IP地址,来看哪个IP可用,因此首要工作就是寻找待选的代理IP源?
  • 初步确定了待选代理IP源,如何确定这里面的每一个IP是真的可用?
  • 寻找到的待选代理IP源,是以什么格式保存的?需要进行文本预处理吗?
  • 选择并确定了某个代理IP可用,但在下载网页过程中可能会又突然失效了,如何继续抓取剩下的网页?
  • 如果重新选择了一个可用的代理IP完成了剩下的网页抓取,为了方便下次使用,需要将它更新到12国抓取脚本中,该如何实现呢?
  • 上篇博客中提到过,在抓取游戏排名网页和游戏网页的过程中,都需要使用代理IP来下载网页,如果遇到上面的代理IP突然失效,该如何解决?
  • 如果一个代理IP并没有失效,但是它抓取网页的速度很慢或极慢,24小时内无法完成对应国家的网页抓取任务,该怎么办?需要重新筛选一个更快的吗?
  • 如果把所有代理IP源筛选一遍后,仍然没有一个可用的代理IP,该怎么办?是继续循环再筛选一次或多次,还是寻找新的代理IP源?

分析解决一个实际问题时,将会遇到各种问题,有些问题甚至是方案设计之初都难以想到的(如代理IP抓取网页速度过慢),我的体会是:动手实践比纯理论更重要!



方案设计

总体思路:寻找并缩小筛选的IP代理源——》检测代理IP是否可用——》IP可用则记录下来抓取网页——》代理IP故障则重新筛选——》继续抓取网页——》完成


Linux IP代理筛选系统(shell+proxy)_第2张图片


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代理筛选系统的核心和关键

其故障恢复的轮询筛选流程如下:


Linux IP代理筛选系统(shell+proxy)_第3张图片


上图流程中,需要注意几点:

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源(以美国为例),其格式如下:

Linux IP代理筛选系统(shell+proxy)_第4张图片


接着,清除上图中的空格,具体实现命令请见上面【方案设计】——》【2、文本预处理】,文本预处理后的格式如下:

Linux IP代理筛选系统(shell+proxy)_第5张图片


然后,测试上图文本预处理后的代理IP是否可用具体命令请见上面【方案设计】——》【3、检测IP代理】,检测代理IP后的格式如下:



下面介绍shell脚本实现文本预处理和网页筛选的详细步骤

1、文本预处理

[php]  view plain copy
  1. # file process  
  2. log='Top800proxy.log'  
  3. dtime=$(date +%Y-%m-%d__%H:%M:%S)  
  4.   
  5. function select_proxy(){  
  6.     if [ ! -d $dir_split ]; then  
  7.         mkdir $dir_split  
  8.     fi  
  9.   
  10.     if [ ! -d $dir_output ]; then  
  11.         mkdir $dir_output  
  12.     fi  
  13.   
  14.     if [ ! -e $log ]; then  
  15.         touch $log  
  16.     fi  
  17.   
  18.     echo "================== Top800proxy $dtime ==================" >> $log   
  19.   
  20.     for file in `ls $dir_input`; do  
  21.         echo $file >> $log  
  22.   
  23.         file_input=$dir_input$file  
  24.         echo $file_input >> $log  
  25.         file_split=$dir_split$file"_split"  
  26.         echo $file_split >> $log  
  27.   
  28.         rm -rf $file_split  
  29.         touch $file_split  
  30.   
  31.         sed -e "s/\s\{2,\}/:/g" $file_input > $file_split  
  32.         sed -i "s/ /:/g" $file_split  
  33.   
  34.   
  35.         file_output=$dir_output$file"_out"  
  36.         echo $file_output >> $log  
  37.         proxy_output "$file_split" "$file_output"  
  38.   
  39.         echo '' >> $log  
  40.     done  
  41.   
  42.     echo '' >> $log  
  43. }  
脚本功能说明:

if语句,判断并创建用于保存处理IP源中间结果的文件夹$dir_split 和 $dir_output ,前者保存【脚本功能实现】中文本预处理后的文本格式,后者保存检测后可用的代理IP

sed -e语句,把输入文本(脚本功能实现的图1)中的多个空格,修改为一个字符“:”

sed -i语句,进一步把文本中的多余空格,转换为一个字符":"

转换的中间结果,都保存到文件夹 $dir_split 

后面的file_output三行,以文件参数的形式"$file_split",传给代理IP检测函数(proxy_output),筛选出可用的代理IP


2、代理IP筛选

[php]  view plain copy
  1. index=1  
  2. file_html=$dir_output"html_"  
  3. cmd=''  
  4. function proxy_output(){  
  5.     rm -rf $2  
  6.     touch $2  
  7.     rm -rf $file_html*  
  8.   
  9.     index=1  
  10.     while read line  
  11.     do  
  12.         proxy_ip=$(echo $line | cut -f 1 -d ":")  
  13.         proxy_port=$(echo $line | cut -f 2 -d ":")  
  14.         proxy=$proxy_ip":"$proxy_port  
  15.         echo $proxy >> $log  
  16.   
  17.         cmd="curl -y 60 -Y 1 -m 300 -x $proxy -o $file_html$index $url_html"  
  18.         echo $cmd >> $log  
  19.         $cmd  
  20.   
  21.         if [ -e ./$file_html$index ]; then  
  22.             echo $proxy >> $2  
  23.             break;  
  24.         fi  
  25.   
  26.         index=`expr $index + 1`  
  27.     done < $1  
  28.   
  29.     rm -rf $file_html*  
  30. }  
脚本功能说明:

代理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,抓取游戏排名网页的实例如下(脚本片段):

[php]  view plain copy
  1. index=0  
  2.     while [ $index -le $TOP_NUM ]  
  3.     do  
  4.         url=$url_start$index$url_end  
  5.         url_cmd='curl -y 60 -Y 1 -m 300 -x '$proxy' -o '$url_output$index' '$url  
  6.         echo $url_cmd  
  7.   
  8.         date=$(date "+%Y-%m-%d___%H-%M-%S")  
  9.         echo $index >> $log  
  10.         echo $url"___________________$date" >> $log  
  11.   
  12.         $url_cmd  
  13.   
  14.         # done timeout file  
  15.         seconds=0  
  16.         while [ ! -f $url_output$index ]  
  17.         do  
  18.             sleep 1  
  19.             echo $url_output$index"________________no exist" >> $log  
  20.             $url_cmd  
  21.             seconds=`expr $seconds + 1`  
  22.             echo "seconds____________"$seconds >> $log  
  23.             if [ $seconds -ge 5 ]; then  
  24.                 select_proxy  
  25.                 url_cmd='curl -y 60 -Y 1 -m 300 -x '$proxy' -o '$url_output$index' '$url  
  26.                 seconds=0  
  27.             fi  
  28.         done  
  29.   
  30.         index=`expr $index + 24`  
  31.     done  
脚本功能说明:

上面shell脚本代码片段,是用来抓取网页的,其中最核心的一行是 select_proxy 

其作用是上述介绍过的,当代理IP突然失效、抓取网页过慢、全部代理IP都无效、或无法完成当天的网页抓取工作,用来重新筛选代理IP,恢复网页抓取的一段核心代码

其设计实现流程,如上述的【方案设计】——》【7、重新检测IP代理】,其实现原理可参照上述的【代理IP筛选】的脚本,在此不再贴出其源脚本代码

转至:http://blog.csdn.net/sunboy_2050?viewmode=contents

你可能感兴趣的:(Linux IP代理筛选系统(shell+proxy))