动态ip

>

代理ip软件

>

换ip软件

>

HTTP代理

>
Socks5代理
黑核动态ip代理
黑核动态ip为您提供更友好、更专业的服务。
您的位置:首页>新手教程>如何搭建自己的爬虫IP代理池
如何搭建自己的爬虫IP代理池
来源:黑核动态ip代理 时间:2019-04-18

分享到

  如今爬虫越来越多,一些网站网站加强反爬措施,其中最为常见的就是限制IP,对于爬虫爱好者来说,能有一个属于自己的IP代理池,在爬虫的道路上会减少很多麻烦。如何搭建自己的爬虫IP代理池?今天小编就来教教大家。

  环境参数

工具详情
服务器Ubuntu
编辑器Pycharm
第三方库requests、bs4、redis

搭建背景

之前用Scrapy写了个抓取新闻网站的项目,今天突然发现有一个网站的内容爬不下来了,通过查看日志发现是IP被封,于是就有了这篇文章。

思路

一般出售IP代理的都会提供一些免费代理,既然是免费的就不要浪费,我们只要把免费的代理爬下了,及时维护和更新就可以把免费的变成我们自己的代理池

编写爬虫

搜索免费代理会有很多结果,一般情况大部分都可以使用,这里以其中一家代理为例,打开代理网站以后,首先通过浏览器查看代码,然后分析代码开始编写爬虫

网站源代码

...    ....

通过上面一条数据可以看出,提供者为防止网站被爬取还是做了一些防范措施,但是我们可以使用正则表达式取出IP地址和端口号。
使用正则表达式的时候我们一般会有两种思路

  • 1.提取数字和点.

  • 2.过滤html标签,保留我们想要的数字和点

这里我们以第二种方法为例

soup = BeautifulSoup(html, 'html.parser')
data = soup.find('td', class_='ip')
res=re.compile('|',re.S)
proxy=re.sub(res, '', str(data))
print(proxy)# 59.108.125.241:8080

这个时候IP地址和端口号就提取出来了,当你把整个网页的代理地址都提取出来以后,你会发现没有一个可以使用的。

这是为什么呢?难道是代理商提供的免费代理都是垃圾,其实不然,细心的你可能会发现你匹配的端口和他们官网显示的端口号不一样,很显然他们的端口号是通过js动态加载的,遇到这种情况,我们一般也会想到2种解决方案

  • 使用selenium

  • 破解js
    如果加密方式复杂、js文件很多,无从下手时可以使用selenium,好在我们今天爬取的这个网站js文件不是很多,通过打断点,很容易定位到我们要解密的js文件,下面我就分享一下的我解决方法

破解js

  • 找到对应的js文件

可以给网站中的每个js文件打断点,一步步调试找出影响数据的js文件,通过调试我找到这样一个文件

eval(function(p,a,c,k,e,d){e=function(c){return(c35?Stri

  解密js文件

  很显然上面这个文件是加密压缩过的,通过在线解密工具,两次解密以后我们得到这样一个方法,有点js基础的同学应该能看的懂,但是还是不够直观,因为这个方法首先定义了一个数组,每个变量都是用数组切片的方式代替,所以一眼很难看出加密方式

var _$ = ['\x2e\x70\x6f\x72\x74', "\x65\x61\x63\x68", "\x68\x74\x6d\x6c", "\x69\x6e\x64\x65\x78\x4f\x66", '\x2a', "\x61\x74\x74\x72", '\x63\x6c\x61\x73\x73', "\x73\x70\x6c\x69\x74", "\x20", "", "\x6c\x65\x6e\x67\x74\x68", "\x70\x75\x73\x68", '\x41\x42\x43\x44\x45\x46\x47\x48\x49\x5a', "\x70\x61\x72\x73\x65\x49\x6e\x74", "\x6a\x6f\x69\x6e", ''];
$(function() {
    $(_$[0])[_$[1]](function() {
        var a = $(this)[_$[2]]();        if (a[_$[3]](_$[4]) != -0x1) {            return
        };
        var b = $(this)[_$[5]](_$[6]);
        try {
            b = (b[_$[7]](_$[8]))[0x1];
            var c = b[_$[7]](_$[9]);
            var d = c[_$[10]];
            var f = [];            for (var g = 0x0; g < d; g++) {
                f[_$[11]](_$[12][_$[3]](c[g]))
            };
            $(this)[_$[2]](window[_$[13]](f[_$[14]](_$[15])) >> 0x3)
        } catch (e) {}
    })
})

通过对数组的拆分,你会发现上面方法的核心内容可以简化成这样

    var f = []; 
    var c="GEGEA".split(""); 
    for (var g = 0; g < c.length; g++) {
        f.push('ABCDEFGHIZ'.indexOf(c[g]))
    };

我来解释一下这个代码片段,首先"GEGEA"这个值是怎么来的? 这个值不是固定的,而是网页源码中class='port GEGEA' port的同级class,获取到这个class以后,先把它转为数组,判断数组中的每个元素在'ABCDEFGHIZ'中的位置,会得到一个类似这样的数组[6, 4, 6, 4, 0],再把这个新数组转为字符串,然后位移,就可以得到真实的端口号,所以可以把解密函数简化成这样

    // 定义一个数组,用于记录class在'ABCDEFGHIZ'出现的位置
    var f = []; 
    // 把class转为一个数组
    var c="GEGEA".split(""); 
    // 根据数组的长度记录数组中每个元素在'ABCDEFGHIZ'出现的位置
    for (var g = 0; g < c.length; g++) {
        f.push('ABCDEFGHIZ'.indexOf(c[g]))
    };    // 把数组转为字符串,再进行运算
    var port=f.join('')>>0x3
    // 得到真实的端口号
    console.log(port)

如果上面的js解密步骤你已经理解,接下来用python重写一下这个解密步骤很会简单很多,具体代码如下所示

# port_class 是源代码port的同级classdef parse_port(self,port_class):
        string = 'ABCDEFGHIZ'
        arr = list(port_class)
        lists = []        for x in range(0, len(arr)):
            lists.append(string.find(arr[x]))

        ports = ''.join(str(x) for x in lists)        return int(ports) >> 3

这段python代码和上面的js代码逻辑一致,效果也一样,只不过是用python翻译了一遍。

到这里爬虫的难点我们都解决了,现在要做的是把爬取下来的代理存储到redis里面。
至于为什么用redis存储,有以下几点原因:

  1. redis相比mysql、文件写入速度更快

  2. 使用redis里的集合特性,不用担心有重复数据

  3. 项目中使用了分布式爬虫,存到redis中方便多台服务器调用

IP代理池添加和维护

下面分为4个步骤来分享一下IP代理池的维护

  • 安装redis
    不同系统redis的安装方法不同,本文以Ubuntu为空

apt-get install redis-server

redis 安装好以后会自动安装一个客户端redis-cli,我们可以通过redis-cli对数据的增删改查,比如:

# 进入客户端redis-cli# 添加一条数据set name 'hello world'# 获取name的值get name

但是我们总不能把IP代理地址一个个手动添加到redis里,所以我们还要安装一个python操作redis的模块

这个模块名刚好也叫redis

pip install redis

模块安装好我们就可以通过python管理redis里的数据了
redis有5种数据类型分别为:string(字符串),hash(哈希),list(列表),set(集合)及zset(有序集合),我们这里主要使用set(集合)

  • 添加IP代理地址到redis

# 导入模块import redis# 连接到Redis服务器conn = redis.Redis(host='127.0.0.1', port=6379)# 添加数据 key 可以更加自己的需求设置conn.sadd('proxy','119.179.0.1:8083')# 随机取出一条代理地址conn.redis.srandmember('proxy')
  • 验证IP代理是否有效
    可以在存入的时候可以验证,也可以在取的时候验证代理是否有效,但是如果存入的时候就验证,取得时候有可能已经不能使用

# 导入模块import redisimport requests# 连接到Redis服务器conn = redis.Redis(host='127.0.0.1', port=6379)# 随机取出一条代理数据ip=conn.redis.srandmember('proxy')
print(ip)

url='https://www.baidu.com'proxies = {            "http": "http://" + ip.decode("utf-8")
        }        
# 使用IP代理访问百度,测试代理地址是否有效try:
    data = requests.get(url=url, proxies=proxies, timeout=5)except:    # 代理地址无效
  • 删除无效的IP代理

验证IP代理是否无效,如果代理地址无效,可以使用以下命令删除代理,这样可以保证我们代理池中的地址都是有效的

conn.redis.srem('proxy', '无效的IP代理地址')

最后把获取代理的步骤封装成一个方法,在需要代理的地方调用即可

到这里我们的代理池就搭建好了,如果感觉只有一个网站的数据不能我们使用,只需要多爬取几个免费代理及时维护就可以啦。

对于大多数爬虫初学者来说,其实爬取一个没有反爬的网站不是什么难事,无非就是把网站的源代码获取下来,然后使用bs4或者正则表达式来提取数据,这里我专门找来一个有反爬的网站,就是想让大家感受一下反爬的流程,当然这也是很简单的一个。

对于代理池的搭建记住三点即可:

  1. 添加IP代理

  2. 验证IP代理是否有效

  3. 及时删除无效代理

总结:本文用一半的篇幅再和大家分享JS破解的步骤,对于没有JS基础的同学看起来会有点吃力,但是通过python的解密步骤,可能会让你对JS加密流程有个大致了解。reids的操作可以参考具体文档。

在线客服
大客户VIP渠道
点击这里给我发消息
讨论QQ群
客服电话
13318873961