您的位置:首页 >文章内容

网络爬虫封ip该怎么办?用万变ip搭建一个个人IP代理池

来源: 作者:admin 时间:2019-11-22 10:27:05
 ip代理

 网络爬虫封号该怎么办?用Node搭建一个个人IP代理池

 你是否还记得初学网络爬虫的那时候,选了一个美女网站来练习,高效率极高,见到全都想爬下来。爬得正开心呢,出現了一连串错误,查询后发觉由于抓取太过经常,被网址封了ip,那时候起总有了搭建代理ip池的想法。

 在网上搜索一下代理ip就会发觉有许多网址出示,可是平稳功能强大的必须收费标准,完全免费倒也是一堆,但大部分都不可以用。并且我写的一般全是小爬虫,非常少有抓取上白g统计数据的那时候,用收费标准的代理ip有点儿奢侈浪费。

 因此,写了这一代理ip池,从各大代理ip网址抓取搜集完全免费的代理ip,随后一一开展检测,从这当中挑选出髙速能用的ip。归功于Node的多线程构架,速率十分快,能够立即在自身的网络爬虫里启用,每一次抓取前获得最新消息的代理ip,之后母亲就再也不需要担忧我的网络爬虫封号了。

 接下去会分成三个一部分来解读,如何下载,如何使用和要怎么写,假如仅仅想要得话看前几篇就可以了。

 1.怎么下载

 有二种方式,一个是根据Github:Card007/Proxy-Pool;

 另一种是根据npm加上:npm install ip-proxy-pool;

 二种方法都能够,强烈推荐github,有一个使用说明书,中后期我都会开展升级,热烈欢迎start。

 2.怎么使用

 //导进当地控制模块 var proxy = require('./proxy_pool.js') //假如根据npm安裝 //var proxy = require('ip-proxy-pool') //子程序,抓取ip+查验ip var proxys = proxy.run //不抓取,只查验数据库查询里目前的ip var check = proxy.check //获取数据库查询里全部的ip var ips = proxy.ips //ips接受一个处理函数,随后向这一涵数传送2个主要参数,一个为错误,另一个为数据库查询里的全部ip ips((err,response)=>{ console.log(response) }) //假如期待抓取的ip多一点能够改动check涵数里的timeout

 3.如何手动式写一个代理ip池

 如今而言说自身要怎么写一个代理ip池,往西刺为例,采用的专用工具和方式 大部分和上一篇抓取豆瓣电影top250一样,起先抓取西刺网址前5页的全部完全免费ip,随后储存在sqlite数据库查询里,随后根据一一应用抓取好的代理ip浏览某一网站地址,回到200的则是能用,回到其他大数字的则删掉,看来编码:

 //导进相对的库 var request = require('request') var cheerio = require('cheerio') var sqlite3 = require('sqlite3') //转化成网站地址,西刺网站地址以尾数大数字做为分页查询连接 var ipUrl = function(resolve){ var url = 'http://www.xicidaili.com/nn/' var options = { url:'http://www.xicidaili.com/nn/', headers, } //用个简易的for循环系统即可领取全部必须的连接,随后将连接一一放进抓取互联网的requestProxy里 for (let i = 1; i <= 5; i++) { options.url = url + i requestProxy(options) } } //连接互联网 var requestProxy = function(options){ //这儿应用了Promise来操纵多线程 return new Promise((resolve, reject) => { request(options, function(err, response, body){ if(err === null && response.statusCode === 200){ //回到200表明抓取取得成功,loadHtml为解析函数,会将人们必须的信息内容爬取下来存有数据库查询里 loadHtml(body) resolve() } else { console.log('连接不成功') resolve() } }) }) }

 接下去应说到Node的深坑,多线程,因为多线程构架,必须采用Promise来操纵,例如在这一代理ip池中,会出現reqeust涵数还没爬完的那时候就刚开始实行认证涵数,非常容易错误,因此人们必须分成2组,一组为多线程抓取网址抓取,另一组为多线程认证代理ip,因此人们来更新改造一下上边的编码:

//生成网址 var ipUrl = function(resolve){ var url = 'http://www.xicidaili.com/nn/' var options = { url:'http://www.xicidaili.com/nn/', headers, } var arr = [] for (let i = 1; i <= 5; i++) { options.url = url + i arr.push(requestProxy(options)) } //Promise.all接收一个数组,直到数组里所有的函数执行完毕才执行后面then里的内容 //实际上放这里有点多余,后期会改过来,先将就 Promise.all(arr).then(function(){ resolve() }) } //链接网络 var requestProxy = function(options){ return new Promise((resolve, reject) => { request(options, function(err, response, body){ if(err === null && response.statusCode === 200){ loadHtml(body) resolve() } else { console.log('链接失败') resolve() } }) }) }

接下来分析一下网页内容,这里我们只需要ip,端口,和类型即可:

//分析网页内容 var loadHtml = function(data){ var l = [] var e = cheerio.load(data) e('tr').each(function(i, elem){ l[i] = e(this).text() }) for (let i = 1; i < l.length; i ++){ //在提取到想要的内容后发现太乱,需要额外的函数进行处理优化 clearN(l[i].split(' ')) } } //提取优化文件数据, var clearN = function(l){ var index = 0 for (let i = 0; i < l.length; i++) { if(l[i] === '' || l[i] === ' '){ }elsevar ips = l[i].replace(' ','') if (index === 0){ var ip = ips console.log('爬取ip:' + ip) } else if(index === 1){ var port = ips } else if(index === 4){ var type = ips } index += 1 } } //存入数据库 insertDb(ip, port, type) }

接着来实现数据库的存储删除功能:

//打开数据库 var db = new sqlite3.Database('Proxy.db', (err) => { if(!err){ console.log('打开成功') } else { console.log(err) } }) db.run('CREATE TABLE proxy(ip char(15), port char(15), type char(15))',(err) => {}) //添加数据文件 var insertDb = function(ip, port, type){ db.run(\"INSERT INTO proxy VALUES(?, ?, ?)\",[ip,port,type]) } //删除数据库文件 var removeIp = function(ip){ db.run(`DELETE FROM proxy WHERE ip = '${ ip }'`, function(err){ if(err){ console.log(err) }else { console.log('成功删除:'+ip) } }) } //从数据库提取所有ip var allIp = function(callback){ return db.all('select * from proxy', callback) }

接着将数据库里的ip提取出来,进行测速筛选:

//从数据库提取出来的ip会通过这个类创建一个对象 var Proxys = function(ip,port,type){ this.ip = ip this.port = port this.type = type } //提取所有ip,通过check函数检查 var runIp = function(resolve){ var arr = [] allIp((err,response) => { for (let i = 0; i < response.length; i++) { var ip = response[i] var proxy = new Proxys(ip.ip, ip.port, ip.type) arr.push(check(proxy, headers)) } Promise.all(arr).then(function(){ allIp((err, response)=>{ console.log(' 可用ip为:') console.log(response) }) }) }) } //检测ip var check = function(proxy, headers){ return new Promise((resolve, reject) => { request({ //检测网址为百度的某个js文件,速度快,文件小,非常适合作为检测方式 url:'http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js', proxy: `${proxy.type.toLowerCase()}://${proxy.ip}:${proxy.port}`, method:'GET', //这里延迟使用了2000,如果希望通过检测的ip多一些,可以适当延长 timeout: 2000, headers,} ,function(err, response,body){ if(!err && response.statusCode == 200){ console.log(proxy.ip+' 链接成功:') resolve() } else { console.log(proxy.ip+' 链接失败') removeIp(proxy.ip) resolve() } } ) }) }

最后,来写几个运行函数:

var run = function(){ new Promise(ipUrl).then(runIp) } var rcheck= function(){ runIp() } var ips = function(callback){ allIp(callback) }

大功告成:




 详细编码能够根据Github查询:Proxy-Pool

 还可以浏览站长统计,获得大量文章内容:Nothlu