Я до сих пор помню, что когда я только училась ползать, я выбрала бьюти-сайт для тренировки рук, он был очень эффективным, и мне хотелось слезть, когда я что-то видел. Я с удовольствием полез, и появилась серия сообщений об ошибках.Проверив его, я обнаружил, что 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