Что делать, если гад заблокировался? Создание частного пула IP-прокси с узлом

Node.js
Что делать, если гад заблокировался? Создание частного пула IP-прокси с узлом

Я до сих пор помню, что когда я только училась ползать, я выбрала бьюти-сайт для тренировки рук, он был очень эффективным, и мне хотелось слезть, когда я что-то видел. Я с удовольствием полез, и появилась серия сообщений об ошибках.Проверив его, я обнаружил, что ip был заблокирован сайтом, потому что сканирование было слишком частым.С тех пор у меня возникла идея построить прокси IP пул.

Поиск прокси ip в Интернете обнаружит, что есть много веб-сайтов, которые предоставляют его, но те, которые стабильны и просты в использовании, платные, и есть много бесплатных, но большинство из них нельзя использовать. А то что я пишу это вообще мелкий краулер.Немножко расточительно использовать платный прокси ip при сканировании белых г данных.

Поэтому я написал этот пул IP-адресов прокси, сканирует и собирает бесплатные IP-адреса прокси-серверов с основных веб-сайтов IP-прокси, а затем тестирует их один за другим, чтобы отфильтровать доступные высокоскоростные IP-адреса. Благодаря асинхронной архитектуре Node, скорость очень высокая, и его можно вызывать прямо в собственном краулере.Перед каждым краулированием будет получен последний прокси-айпи.В будущем маме больше не придется беспокоиться о моем краулере быть заблокированным.

Далее он будет разделен на три части, чтобы объяснить, как скачать, как использовать и как писать.Если вы просто хотите использовать его, достаточно прочитать первые две статьи.

1. Как скачать

Есть два способа, один проходит через GitHub: Card007 / прокси-бассейн;

Другой — добавить через npm: npm install ip-proxy-pool;

Оба метода доступны, рекомендуется github, есть инструкция по использованию, я обновлю ее позже, добро пожаловать на старт.

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接收一个处理函数,然后向这个函数传递两个参数,一个为错误信息,另一个为数据库里的所有ip
ips((err,response)=>{
    console.log(response)
})

//如果希望爬取的ip多一点可以修改check函数里的timeout

3. Как вручную написать пул прокси ip

Теперь давайте поговорим о том, как написать пул прокси-ip.В качестве примера возьмем Xithorn.Используемые инструменты и методы в основном такие же, как и в предыдущей статье для сканирования Douban top250.Сначала мы сканируем все свободные IP-адреса на первых 5 страницах веб-сайт Xithorn, а затем сохраните его в базе данных 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 функция проверки будет выполнена до того, как функция запроса закончит сканирование , в котором легко ошибиться. , поэтому нам нужно разделить его на две группы, одна группа — это асинхронное сканирование веб-сайта, а другая — асинхронная проверка 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] === '\n'){
        }else{
            var ips = l[i].replace('\n','')
            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('\n\n可用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