Как реализовать многопоточный парсинг node.js
Доброго времени суток, пишу парсер инстаграма на node.js с использованием приватного апи, работаю второй день с node.js , поэтому есть вопросы. На данный момент есть рабочая однопоточная версия с прокси:
'use strict'; var InstagramPrivateAPI = {}; InstagramPrivateAPI = {}; InstagramPrivateAPI.V1 = require(__dirname + '/client/v1'); InstagramPrivateAPI.Helpers = require(__dirname + '/helpers'); var acc = require(__dirname + "/client/v1/account"); var med = require(__dirname + "/client/v1/media") var Promise = require('../bluebird'); var _ = require('../lodash/'); module.exports = InstagramPrivateAPI; var Client = require('instagram-private-api').V1; var device = new Client.Device('maksgmn'); var storage = new Client.CookieFileStorage(__dirname + '/cookies/maksgmn.json'); var session = new Client.Session(device, storage); function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min)) + min; } var fs = require('fs'); var proxyArray = fs.readFileSync('proxy.txt').toString().split("\n"); var usernamesArray = fs.readFileSync('usernames.txt').toString().split("\n"); var proxy = "http://" + proxyArray[getRandomInt(0,proxyArray.length)] var username = usernamesArray[getRandomInt(0,usernamesArray.length)] console.log(proxy) console.log(username) Client.Request.setProxy(proxy); acc.searchForUser(session, username) //поиск id пользователя .then(function(profile) { return profile.id }) .then(function(someId) { //получение промиса lenta var feed = new Client.Feed.UserMedia(session, someId); var lenta = Promise.mapSeries(_.range(0, 1), function() { return feed.get(); }).then(function(lenta) { return {id: someId, fd : lenta} }) return lenta }) .then(function(results) { //обработка промиса и получение ленты пользователя // result should be Media[][] var media1 = _.flatten(results.fd); var urls1 = _.map(media1, function(medium) { //var arr1 = medium.params.images[0].url; var arr1 = [] try { arr1 = medium.params.images[0].url } catch (err) { //console.log("lala") } return arr1; //console.log(medium.params.carouselMedia.images[0].url) }) //console.log(urls1) return {id : results.id, linksNoCarousel : urls1, med : media1} }) .then(function(res){ var urls2 = _.map(res.med, function(medium) { var arr2 = [] try { arr2 = medium.params.images[0][0].url //console.log(arr2) } catch (err) { } return arr2 }) for (var i = 0; i < 5; i++) { if (typeof res.linksNoCarousel[i] == "undefined") res.linksNoCarousel[i] = urls2[i]; } var arr3 = [] for (var i = 0; i < 5; i++) { arr3[i] = res.linksNoCarousel[i] } return {id : res.id, links : arr3} }) .then(function(mediaAndId) { acc = acc.getById(session, mediaAndId.id) .then(function(account) { //console.log(account.params) let avatar = account.params.profilePicUrl; let fullName = account.params.fullName; let bio = account.params.biography; let media0 = mediaAndId.links[0]; let media1 = mediaAndId.links[1]; let media2 = mediaAndId.links[2]; let media3 = mediaAndId.links[3]; let media4 = mediaAndId.links[4]; console.log(avatar); console.log(fullName); console.log(bio); console.log(media0); console.log(media1); console.log(media2); console.log(media3); console.log(media4); }) }) Хотелось бы, чтобы все это работало в многопотоке, иначе скорость парсинга будет очень низкая. Как это можно реализовать? |
Цитата:
https://nodejs.org/dist/latest-v10.x...r_threads.html ну и подумать о том, как оптимизировать. Там реально большие объемы данных обсчитываются? |
Да в целом хорошая скорость, я не работал до этого с асинхронными функциями запустил в цикле и он профилей 100 за 5 секунд обработал, упирается в лимит запросов апи. Хотел уточнить еще: у меня конечный код выглядит примерно так:
'use strict'; var InstagramPrivateAPI = {}; InstagramPrivateAPI = {}; InstagramPrivateAPI.V1 = require(__dirname + '/client/v1'); InstagramPrivateAPI.Helpers = require(__dirname + '/helpers'); var acc = require(__dirname + "/client/v1/account"); var med = require(__dirname + "/client/v1/media") var Promise = require('../bluebird'); var _ = require('../lodash/'); module.exports = InstagramPrivateAPI; var Client = require('instagram-private-api').V1; var device = new Client.Device('maksgmn'); var storage = new Client.CookieFileStorage(__dirname + '/cookies/maksgmn.json'); var session = new Client.Session(device, storage); function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min)) + min; } var fs = require('fs'); var proxyArray = fs.readFileSync('proxy.txt').toString().split("\n"); var usernamesArray = fs.readFileSync('usernames.txt').toString().split("\n"); var proxy = "http://" + proxyArray[getRandomInt(0,proxyArray.length)] var username = usernamesArray[getRandomInt(0,usernamesArray.length)] console.log(proxy) console.log(username) //Client.Request.setProxy(proxy); for (var i = 0; i < usernamesArray.length; i++) { proxy = "http://" + proxyArray[getRandomInt(0,proxyArray.length)]; Client.Request.setProxy(proxy); acc.searchForUser(session, usernamesArray[i]) //поиск id пользователя .then(function(profile) { return profile.id }) .then(function(someId) { //получение промиса lenta var feed = new Client.Feed.UserMedia(session, someId); var lenta = Promise.mapSeries(_.range(0, 1), function() { return feed.get(); }).then(function(lenta) { return {id: someId, fd : lenta} }) return lenta }) .then(function(results) { //обработка промиса и получение ленты пользователя // result should be Media[][] var media1 = _.flatten(results.fd); var urls1 = _.map(media1, function(medium) { //var arr1 = medium.params.images[0].url; var arr1 = [] try { arr1 = medium.params.images[0].url } catch (err) { //console.log("lala") } return arr1; //console.log(medium.params.carouselMedia.images[0].url) }) //console.log(urls1) return {id : results.id, linksNoCarousel : urls1, med : media1} }) .then(function(res){ var urls2 = _.map(res.med, function(medium) { var arr2 = [] try { arr2 = medium.params.images[0][0].url //console.log(arr2) } catch (err) { } return arr2 }) for (var i = 0; i < 5; i++) { if (typeof res.linksNoCarousel[i] == "undefined") res.linksNoCarousel[i] = urls2[i]; } var arr3 = [] for (var i = 0; i < 5; i++) { arr3[i] = res.linksNoCarousel[i] } return {id : res.id, links : arr3} }) .then(function(mediaAndId) { acc.getById(session, mediaAndId.id) .then(function(account) { //console.log(account.params) let avatar = account.params.profilePicUrl; let username = account.params.username; let fullName = account.params.fullName; let bio = account.params.biography; let media0 = mediaAndId.links[0]; let media1 = mediaAndId.links[1]; let media2 = mediaAndId.links[2]; let media3 = mediaAndId.links[3]; let media4 = mediaAndId.links[4]; console.log(avatar) /*console.log(fullName); console.log(bio); console.log(media0); console.log(media1); console.log(media2); console.log(media3); console.log(media4);*/ }) }) } Функции парсинга тут асинхронны и так далее, а вот с циклами и асинхронностью я не уверен что у меня все верно. Стоит ли оставить так или как-то переделать можно? |
Часовой пояс GMT +3, время: 04:49. |