А так же о всякой фигне
Тут проблем меньше, чем со сканированием всего интернета, нужно лишь скравлить несколько разных сайтов и слить списки проксей в 1 итоговый файл.
Нам нужен скриптик, который обойдёт все странички таблицы со списком проксей, вытащит данные и сохранит в цсв.
Для первой тренировки возьмём всем известный hidemy.name.
Сперва опишем стартовые константы: с какого урла начинать, css селекторы для таблички и ссылки на следующую страницу итд:
const cheerio = require('cheerio'); const getHTML = require('./libs/getHTML'); const writeCSV = require('./libs/writeCSV'); const startUrl = 'https://hidemy.name/ru/proxy-list/?type=h#list'; const baseUrl = 'https://hidemy.name'; const tableRowSelector = '.inner .table_block tr'; const nextPageLinkSelector = '.pagination .next_array a'; const addrColIndex = 0; const portColIndex = 1; const proxyType = 'http'; const dstFile = './result.csv'; const headers = { 'Cookie': '__cfduid=df0f27963f74bedac8295bbbf4bf616cd1578833620; t=152631734; jv_visits_count_PeHzjrJoSL=3; cf_clearance=6be6588940ec85d25a629574413d8d1d798c5f42-1579771170-0-150; jv_enter_ts_PeHzjrJoSL=1579771172995; jv_pages_count_PeHzjrJoSL=6' }
Нам потребуются несколько вспомогательных функций, для красоты вынесем их в отдельные либы:
const axios = require('axios'); const defaultHeaders = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', 'Referer': 'https://www.google.com/', 'DNT': '1', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache', 'TE': 'Trailers' } function getHTML(url, headers={}) { let _headers = Object.assign({}, defaultHeaders); for(let hName in headers) _headers[ hName ] = headers[ hName ]; return axios({ method: 'get', url: url, timeout: 15000, headers: _headers }); } module.exports = getHTML;
На большинстве сайтов будет стоять какая-то защита от ботов, и нам нужно прикинуться нормальным браузерм. По этому у нас описаны всевозможные хэдеры, а ещё добавлена возможность изменить дефолтные хэдеры, если это понадобится(а нам это понадобится).
const fs = require('fs'); const outHeaders = [ 'addr', 'port', 'type' ]; function writeCSV(outFile, data) { let str = outHeaders.join(',') + ' '; for(let line of data) { let outCol = []; for(let h of outHeaders) if( line[ h ] ) outCol.push(line[ h ]); else outCol.push(''); str += outCol.join(',') + ' '; } fs.writeFileSync(outFile, str, { encoding: 'utf8' }); } module.exports = writeCSV;
Алгоритм простой:
async function main() { let result = []; let eof = false; let raund = 0; let url = startUrl; while( !eof ) { console.log('Raund:', raund, 'url:', url); let webResponse = await getHTML(url, headers); let webData = webResponse.data; let $ = cheerio.load(webData); let targetTable = $(tableRowSelector); for(let i=1; i<targetTable.length; i++) { let tdList = cheerio('td', targetTable[ i ]); let addr = cheerio(tdList[ addrColIndex ]).html(); let port = cheerio(tdList[ portColIndex ]).html(); result.push({ addr: addr, port: port, type: proxyType }); } let nextPageUrl = $(nextPageLinkSelector); if( nextPageUrl.length ==0 ) { eof = true; } else { raund ++; url = baseUrl + nextPageUrl[ 0 ].attribs.href; } } writeCSV(dstFile, result); }
Проверяем что получилось:
Всё скравлилось корректно, результаты в цсвшке сохранены.
Переходим на следующий сайт: free-proxy-list.net
На нём ситуация ещё более простая, вся таблица загружается целиком. Меняем константы:
const startUrl = 'https://free-proxy-list.net/'; const baseUrl = 'https://free-proxy-list.net/'; const tableRowSelector = '#proxylisttable tr'; const nextPageLinkSelector = '.any_random_class'; const addrColIndex = 0; const portColIndex = 1; const proxyType = 'http'; const dstFile = './free-proxy-list.net.csv';
В nextPageLinkSelector нужно поставить в любой несуществующий селектор, чтобы кравлер сразу остановился. Ну и пробуем, запускаем:
Всё отработало без ошибок, результаты в цсв сохранились.
Алгоритм одинаковый для любого сайта где есть табличка:
Если клаудфлера не будет пропускать наш запрос, то заходим на сам сайт, открываем инструменты разработки, и копипастим курл запрос:
Из этого запроса нужно вытащить куки и вставить в эту константу::
const headers = { 'Cookie': '__cfduid=df0f27963f74bedac8295bbbf4bf616cd1578833620; t=152631734; jv_visits_count_PeHzjrJoSL=3; cf_clearance=6be6588940ec85d25a629574413d8d1d798c5f42-1579771170-0-150; jv_enter_ts_PeHzjrJoSL=1579771172995; jv_pages_count_PeHzjrJoSL=6' };
После чего клаудфлера подумает, что это наш браузер и пропустит нас.
После того, как мы перекравлели пачку сайтов, нужно все результаты слить в 1 файл, да ещё и убрать дубликаты, наверняка большая часть проксей кочует с одного сайта на другой. Для этого напишем отдельный специализированный скриптик:
'use strict'; const fs = require('fs'); const writeCSV = require('./libs/writeCSV'); function parseCsv(srcString) { let result = []; let headers = []; let lines = srcString.split(' '); for (let name of lines[ 0 ].split(',')) { headers.push(name.trim()); } for (let lineIndex = 1; lineIndex<lines.length; lineIndex++) { let cols = lines[ lineIndex ].split(','); let resLine = {}; for (let colIndex = 0; colIndex<headers.length; colIndex++) { if ( cols[ colIndex ] ) { resLine[ headers[ colIndex ] ] = cols[ colIndex ].trim(); } } result.push(resLine); } return result; } function main() { if( !process.argv[ 2 ] || !process.argv[ 3 ] ) { console.error('Not enough arguments'); console.error('usage: node merge_scv.js src_dir dst_scv_file'); } let dirFiles = fs.readdirSync(process.argv[ 2 ], { encoding: 'utf8' }); let result = {}; for(let fileName of dirFiles) if( /.csv$/gi.test(fileName) ) { console.log('File:', fileName); let curSCV = parseCsv(fs.readFileSync(`${process.argv[ 2 ]}/${fileName}`, { encoding: 'utf8' })); for(let line of curSCV) result[ line.addr + ':' + line.port ] = line; } // Then save results let resArray = []; for(let key in result) resArray.push(result[ key ]); writeCSV(process.argv[ 3 ], resArray); } main();
Запускаем и сливаем всё в 1 итоговый файлик:
Парсить научились, сливать цсв научилисю, весь проект на гитлабе: https://gitlab.com/hololoev/proxy_crawler
Где взять бесплатные прокси? Часть 1: Сканируем интернет с помощью nodejs
Проверяем список прокси серверов на доступность, с помощью nodejs
Где взять бесплатные прокси? Часть 1: Сканируем интернет с помощью nodejs
Давайте за пару минут напишем приложуньку на nodejs, которая будет сканировать интернеты в поисках открытых прокси серверов.
Сейчас из каждого утюга призывают вкатываться в ИТ. Куча тренеров, на курсах рисуют радужные картины о 300к/сек и розовых понях. Но на самом деле всё на много сложнее.