##写在前面
做爬虫的小伙伴一般都绕不过代理IP这个问题.
PS:如果还没遇到被封IP的场景,要不就是你量太小人家懒得理你,要不就是人家压根不在乎…
爬虫用户自己是没有能力维护一系列的代理服务器和代理IP的,这个成本实在有点高了。 所以公用代理服务器应运而生,现在几大云服务商家都提供代理IP服务,一般论个买…
同时网上也有很多代理IP共享网站,会把一些免费的代理IP放出来给大家用。 大家都是做爬虫的,那么,是不是可以先把代理IP网站的数据爬一遍? 所以可以看到不少的爬代理IP的爬虫,如突破反爬虫的利器——开源IP代理池之类的项目。 这些项目都能达到抓取代理IP数据的目的,很多时候也够用了。
然而在使用过程中我们发现了一些问题:
出于以上种种的原因,按耐不住的dalao(@virjar)开始自己动手撸了。
于是,proxyipcenter出来了。
这个项目做了什么东西呢? dalao是这样写的:
DungProxy是一个代理IP服务,他包括一个代理IP资源server端和一系列适配中心IP资源得客户端。 server负责代理IP资源的收集维护。 client则是一系列方便用户使用得API,他屏蔽了代理IP下载、代理IP选取、IP绑定、IP切换等比较复杂逻辑。用户只需要引入client即可方便使用代理IP服务
简单来说:
server是一个代理IP爬虫,同时负责简单的数据清洗。
client本质是一个代理IP池,获取数据源之后,基于需要代理访问的网站在本地维护一个代理IP池供爬虫使用。
以下内容转载自http://git.oschina.net/virjar/proxyipcenter, 并已获得相关授权。(PS:dalao写的太好了,我都懒得重新写一遍了…问过dalao之后直接转载过来算了。)
DrungProxy的代理IP都是从互联网收集,他是架设在一个高度不可用的资源上面的服务。server会负责对这些资源进行清洗、校验、打分,最终输出可以被客户端使用的IP资源。IP资源从入库到最终判定可用生命流程如下
再IP验证的时候,我们设计了一个模型用来确定哪些IP应该优先验证。模型描述如下:长期可用IP检测频率低,长期不可用IP检测评率低。不稳定IP和刚加入的IP检测频率高。我们使用优先队列来实现这个逻辑,所有IP根据分值放在不同优先队列中,每次校验的时候再不同优先队列中拿出一定资源进行校验(不同优先级拿出的资源数目不一样,高优先级的对象拿出更多资源),对于同一个优先队列,我们根据最后验证时间排序。使上次更新时间最久的资源被优先选择。
分发资源的时候,设计去重问题,也就是根据相同条件,每次分发得到的IP很大可能会重复。为了规避这个问题,每次分发都会相应的下发一个资源签名,他会记录分发过的IP。在下次请求的时候,客户端需要带上这个签名,服务器会根据签名过滤,同时会重新对新分发的IP资源做再次签名.
server端使用java编写,使用maven管理项目,使用mysql作为数据库。相关技术包括springMVC,spring,tomcat,mybatis,guava,fastjson,httpclient等。 运行server的方式很简单
直接运行项目使用的是我们的默认数据库,同时使用的是默认配置。实际上server存在一些配置用来设置运行参数。合理的运行参数能够合理使用机器资源以及达到更好的运行效果。 项目主要有两个配置文件需要配置:
其他的应该没有了把,哦对了,项目存在多个profile,也就是resources.local,resources.beta,resources.prod等。他们叫做profile,是maven里面的概念,默认是resources.local生效的。如果想使用其他profile下面的配置,则增加 -Pprofile参数,如运行server
-Pskyee clean tomcat7:run```
### server接口事例
[http://115.159.40.202:8080/proxyipcenter/av?usedSign=&checkUrl=http%3A%2F%2Ffree-proxy-list.net%2F&domain=free-proxy-list.net&num=10](http://115.159.40.202:8080/proxyipcenter/av?usedSign=&checkUrl=http%3A%2F%2Ffree-proxy-list.net%2F&domain=free-proxy-list.net&num=10)
{ “data”: { “data”: [ { “id”: 257, “ip”: “203.192.12.148”, “proxyIp”: “203.192.12.149”, “port”: 80, “ipValue”: 3418360980, “country”: “中国”, “area”: “华北”, “region”: “北京市”, “city”: “北京市”, “isp”: “”, “countryId”: “CN”, “areaId”: “100000”, “regionId”: “110000”, “cityId”: “110100”, “ispId”: “-1”, “transperent”: 2, “speed”: 104, “type”: 1, “connectionScore”: 1310, “availbelScore”: 8, “connectionScoreDate”: 1475641264000, “availbelScoreDate”: 1475646860000, “createtime”: 1473840886000, “lostheader”: false }, { “id”: 654, “ip”: “120.55.245.47”, “proxyIp”: “112.124.119.21”, “port”: 80, “ipValue”: 2016933167, “country”: “中国”, “area”: “华东”, “region”: “浙江省”, “city”: “杭州市”, “isp”: “阿里云”, “countryId”: “CN”, “areaId”: “300000”, “regionId”: “330000”, “cityId”: “330100”, “ispId”: “1000323”, “transperent”: 2, “speed”: 83, “type”: 1, “connectionScore”: 1429, “availbelScore”: 2, “connectionScoreDate”: 1475659905000, “availbelScoreDate”: 1475630273000, “createtime”: 1473840884000, “lostheader”: false }, { “id”: 2489, “ip”: “124.193.33.233”, “proxyIp”: “124.193.33.233”, “port”: 3128, “ipValue”: 2093031913, “country”: “中国”, “area”: “华北”, “region”: “北京市”, “city”: “北京市”, “isp”: “鹏博士”, “countryId”: “CN”, “areaId”: “100000”, “regionId”: “110000”, “cityId”: “110100”, “ispId”: “1000143”, “transperent”: 2, “speed”: 3390, “type”: 1, “connectionScore”: 310, “availbelScore”: 2, “connectionScoreDate”: 1475657685000, “availbelScoreDate”: 1475661878000, “createtime”: 1473839334000, “lostheader”: false }, { “id”: 5004, “ip”: “203.192.12.146”, “proxyIp”: “203.192.12.149”, “port”: 80, “ipValue”: 3418360978, “country”: “中国”, “area”: “华北”, “region”: “北京市”, “city”: “北京市”, “isp”: “”, “countryId”: “CN”, “areaId”: “100000”, “regionId”: “110000”, “cityId”: “110100”, “ispId”: “-1”, “transperent”: 2, “speed”: 161, “type”: 1, “connectionScore”: 1291, “availbelScore”: 10, “connectionScoreDate”: 1475638336000, “availbelScoreDate”: 1475636727000, “createtime”: 1473840882000, “lostheader”: false }, { “id”: 5421, “ip”: “221.237.155.64”, “proxyIp”: “221.237.155.64”, “port”: 9797, “ipValue”: 3723336512, “country”: “中国”, “area”: “西南”, “region”: “四川省”, “city”: “成都市”, “isp”: “电信”, “countryId”: “CN”, “areaId”: “500000”, “regionId”: “510000”, “cityId”: “510100”, “ispId”: “100017”, “transperent”: 2, “speed”: 3238, “type”: 1, “connectionScore”: 119, “availbelScore”: -1, “connectionScoreDate”: 1475611973000, “availbelScoreDate”: 1475629954000, “createtime”: 1473840773000, “lostheader”: false }, { “id”: 8722, “ip”: “58.243.0.162”, “proxyIp”: “58.243.0.162”, “port”: 9999, “ipValue”: 989003938, “country”: “中国”, “area”: “华东”, “region”: “安徽省”, “city”: “安庆市”, “isp”: “联通”, “countryId”: “CN”, “areaId”: “300000”, “regionId”: “340000”, “cityId”: “340800”, “ispId”: “100026”, “transperent”: 2, “speed”: 5143, “type”: 1, “connectionScore”: 154, “availbelScore”: -3, “connectionScoreDate”: 1475665673000, “availbelScoreDate”: 1475614147000, “createtime”: 1473839836000, “lostheader”: false }, { “id”: 11698, “ip”: “218.7.170.190”, “proxyIp”: “218.7.170.190”, “port”: 3128, “ipValue”: 3657935550, “country”: “中国”, “area”: “东北”, “region”: “黑龙江省”, “city”: “绥化市”, “isp”: “联通”, “countryId”: “CN”, “areaId”: “200000”, “regionId”: “230000”, “cityId”: “231200”, “ispId”: “100026”, “transperent”: 2, “speed”: 3145, “type”: 1, “connectionScore”: 317, “availbelScore”: -1, “connectionScoreDate”: 1475642001000, “availbelScoreDate”: 1475524810000, “createtime”: 1473839128000, “lostheader”: false }, { “id”: 13318, “ip”: “220.249.185.178”, “proxyIp”: “220.249.185.178”, “port”: 9999, “ipValue”: 3707353522, “country”: “中国”, “area”: “华东”, “region”: “福建省”, “city”: “福州市”, “isp”: “联通”, “countryId”: “CN”, “areaId”: “300000”, “regionId”: “350000”, “cityId”: “350100”, “ispId”: “100026”, “transperent”: 2, “speed”: 5094, “type”: 1, “connectionScore”: 129, “availbelScore”: -1, “connectionScoreDate”: 1475615670000, “availbelScoreDate”: 1475585178000, “createtime”: 1473840539000, “lostheader”: false }, { “id”: 57033, “ip”: “210.245.25.228”, “proxyIp”: “210.245.25.228”, “port”: 3128, “ipValue”: 3539278308, “country”: “越南”, “area”: “”, “region”: “”, “city”: “”, “isp”: “”, “countryId”: “VN”, “areaId”: “”, “regionId”: “”, “cityId”: “”, “ispId”: “”, “transperent”: 2, “speed”: 1024, “type”: 1, “connectionScore”: 488, “availbelScore”: 36, “connectionScoreDate”: 1475635386000, “availbelScoreDate”: 1475630473000, “createtime”: 1473836572000, “lostheader”: false }, { “id”: 124334, “ip”: “60.194.72.253”, “proxyIp”: “60.194.72.253”, “port”: 3128, “ipValue”: 1019365629, “country”: “中国”, “area”: “华北”, “region”: “北京市”, “city”: “北京市”, “isp”: “鹏博士”, “countryId”: “CN”, “areaId”: “100000”, “regionId”: “110000”, “cityId”: “110100”, “ispId”: “1000143”, “transperent”: 2, “speed”: 2366, “type”: 1, “connectionScore”: 610, “availbelScore”: 16, “connectionScoreDate”: 1475643516000, “availbelScoreDate”: 1475631080000, “createtime”: 1473839561000, “lostheader”: false } ], “num”: 10, “sign”: “9999#C99+999#9B99B99999##Y9999+9999999999999999999999t9999s99999999s9999999999999999999999999999#99999999999999GB999999999G9999s9s99999#9999999999Y9+999##99999999+99999999999999+999999999999B999+Y9999G9+99999999999YB99999999999999999999999+99Y999999999B9999G999s99G999999999#99999#9Y999s999999999#B99999999999999999999+999999Y9999999Y9999999999999Y9999Y999999999999999” }, “status”: true }
client运行原理 这里讲述IP池的设计相关,如果您仅仅是为了使用dunproxy-client,则不必关心本文内容
client就是一个代理IP池的实现,IP池的设计基于两个点:
获取一个IP的方式是这样的 IpPool.getInstance().bind(domain, accessUrl);
曾经有一个绑定用户的功能,使得同一个账户每次获取的IP相同,后来觉得是过度设计,因为对于抓取场景,切换IP是很普通的需求,而且貌似没有多少server会检查常用IP。就算有也是小众需求,本框架不必支持
每当使用IP的时候,需要记录一次IP使用,也就是将IP实例的使用次数加一,用于打分机制计算IP的使用分值,评估IP可用性
方式如下:com.virjar.dungproxy.client.model.AvProxy.recordUsage
每当IP使用失败的时候,需要记录IP使用失败,也就是将IP实例的失败次数加一,用于打分机制计算IP的使用分值,评估IP可用性
方式如下:com.virjar.dungproxy.client.model.AvProxy.recordFailed()
IP下线很简单,拿到IP实例,这样调用com.virjar.dungproxy.client.model.AvProxy.offline()
。
一般情况不建议这么做,因为IP池会自动检查IP是否应该下线,IP池可以定制各种策略。当时,有些时候IP池的检查机制比较缓慢,而上层业务可以明确知道本IP不可用,这个时候可以使用本API强制下线
IP池是单例的,同时里面维护了两个任务线程,在业务完成的时候,需要销毁IP池才能终止内部线程。同时也会执行一些收尾工作,如将可用IP dump。
销毁方式是:com.virjar.dungproxy.client.ippool.IpPool.destroy
IP池有其他很多扩展点,但是目前接口没有开发完成,待后续完善