首页>比特动态>如何维护一个1000IP的免费代理池
如何维护一个1000IP的免费代理池

  好友李博士要买房了, 前几天应邀帮他抓链家的数据分析下房价, 爬到一半遇到了验证码.

  李博士的想法是每天把链家在售的二手房数据都抓一遍, 然后按照时间序列分析. 链家线上在交易的二手房数据大概有30000余套, 而一天只有86400秒, 也就是最慢3s也要访问一个页面. 测试按照这种频率, 大概访问100个页面就会被封了, 而且封锁的时间还不短, 至少在12小时左右. 如果想要每天快速的爬一些数据, 必须得搞定验证码.

  链家封锁是按照IP封禁的, 简单的添加上cookies并没有什么效果. 要破解IP封禁, 自然地想法是加上代理就好了. 在公司里代码各种工具都很成熟, 有现成的代理池可用, 自己要爬些数据的时候发现原来什么都需要自己做. 那就自己做个代理池吧.

  方案

  三种方法:

  需要付费的方法

  自己买IP地址,自己做代理池. 可以利用各种云可以换IP的api(弹性IP),采用几台实例做出口,如果被封了就换IP, 大概看一下IP的价格的话, 就知道这个实在不太现实, 太贵了理论上这个比上一个便宜, 但是还是很贵.

  阿里云上最便宜的主机(内网主机, 没有公网IP)大概价格在60元左右, 如果自己做代理池的话, 想要多少并发出口就需要多少台主机. 假如我们需要同时有10个IP出口是可用的, 那么主机的费用就是 600元. 另外一个1Mbps的IP的价格大概是30元左右, IP的价格是300元. 每个月搭建一个代理池就要花费近1000元, 实在是用不起.

  而且云主机厂商的IP地址往往是连续的, 很可能换来换去都在一个C段, 这时候对于直接封禁IP段的网站就无解了.

  直接购买代理,这些代理往往是通过一些接近黑产的方式扫描端口得来的,需要验证才能使用.

  购买的代理的价格大概是每天几块到几十块不等, 不同厂商之家大同小异, 一个月最少也都需要几百元左右. 不过之前听同事说这些代理的可用性一般, 拿到的代理还需要自己验证是否可用, 也就是花了钱还不能爽, 自然没有了买的欲望.

  穷人的方法

  这些卖代理的网站往往都提供了一些免费代理在首页来吸引流量, 少则几十, 多则几百, 初步测试了几个还算能用. 既然直接买来代理也还需要验证, 那还不如直接抓取他们网站上提供的免费代理了. 验证后入库, 用的时候直接选取一个用就好了. 如果代理库里有1000个左右的可用IP, 那还是能解决不少问题的.

  代理的一些基础知识

  某网站的代理列表:

  

如何维护一个1000 IP的免费代理池


  一般来说, http/https代理用的比较多, socks代理似乎很少使用. 其中好多代理服务器只支持http代理. 比如 https://www.baidu.com 就只能使用https代理访问, 而不能使用http代理. 上图中给出了这些代理的类型, 然而实际测试发现, 这些类型好多都是不准的. 还有响应时间等数据也和服务器有关, 并不能直接使用上面的数据. 所以我们的思路是只要地址和端口, 其他的数据都自己验证.

  架构设计

  存储

  我们把抓到的代理存到mysql中, 具体的表设计如下:

  CREATE TABLE `proxy` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `ip` varchar(15) NOT NULL,

  `port` int(10) unsigned NOT NULL DEFAULT '3128',

  `type` smallint(5) unsigned NOT NULL DEFAULT '0',

  `country` varchar(2) DEFAULT NULL,

  `state` varchar(15) DEFAULT NULL,

  `enqueue_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  `last_check_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  `used_times` int(11) NOT NULL DEFAULT '0',

  `from_url` varchar(1024) NOT NULL DEFAULT '',

  PRIMARY KEY (`id`),

  KEY `idx_ip_port` (`ip`,`port`)

  ) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4

  抓取和验证

  代理的获取分为两个线程, 一个线程使用爬虫不断扫描已知的代理的网站, 获得代理的地址, 验证后入库. 另一个线程扫描库里的代理, 验证是否依然可用.

  接口

  代理服务对外主要提供一个接口, get_proxy. 需要使用代理的程序每次调用这个接口获得一个可用代理使用. 每次尽量选取使用次数最少但是存活时间最长的代理.

  实现

  之前写过一个简单的按照配置文件抓取网页的小爬虫(https://github.com/yifeikong/minicrawler). 这下终于派上用场了. 把每个网页抽取代理的xpath配好, 之后就等着在数据库看数据就好了 ^_^

  使用 django 简单实现了一个后台, 大概是这样的:

  

如何维护一个1000 IP的免费代理池


  经过测试, 一般代理的存活时间往往在十几分钟左右, 但是这些代理网站的更新时间一般也在十几分钟, 而且由于找到了大概几十个网站, 扫一遍并验证花费的时间可能在几个小时左右. 所以维持一个可用代理在1k左右的代理库是不成问题的.

  get_proxy 的接口如下:

  

如何维护一个1000 IP的免费代理池


  后记

  经过测试发现, 国外的代理网站往往量很大, 而且可用率也比较高. 然而由于防火墙的原因, 这些网站以及甚至他们提供的代理在国内是不能访问的, 不过我的主机在阿里云香港, 所以也就没有问题了.

  有不少网站显然是发现了我们这种抓代理的行为, 他们页面的IP或者端口是加密的, 而在浏览器中js执行过后则是有正确结果的. 也就是简单地通过抽取是得不到正确结果的. 比如这样:

  

如何维护一个1000 IP的免费代理池


  比如这里在原始网页中是没有代理的IP的, 而是通过js动态生成的.

  对于这种网页怎么操作的, 且听下回分解: 使用headless chrome抓取动态网页.