Я написал небольшой скрипт в Node.js, чтобы очистить веб-страницу и получить некоторые ссылки. Часть скрапа выполняется с помощью Cheerio. Мой код здесь (упрощено для пространства):JSON document mysteriously "empties"
var request = require('request');
var cheerio = require('cheerio');
var base_url = 'http://www.naftemporiki.gr/finance/';
var mutuals = {};
mutuals.date = new Date();
mutuals.companies = [];
var company = {};
request(base_url + 'mtfCompanies', function (error, response, html) {
if (!error && response.statusCode == 200) {
var $ = cheerio.load(html);
$('.blueRow.texttd.name a').each(function (i, element) {
var a = $(this);
company = {};
company.name = a.text();
company.link = a.attr('href');
mutuals.companies.push(company);
});
}
//console.log(mutuals); // 1st place
});
console.log(mutuals); // 2nd place
Здесь начинается самое интересное: Когда я пытаюсь вывести документ в формате JSON с «1-е место», внутри блока «запроса», то выходит красиво и правда. Примером здесь:
{ date: Wed Nov 26 2014 10:35:09 GMT+0200 (EET),
companies:
[ { name: ' J.P. MORGAN ASSET MANAGEMENT',
link: 'mtfCompany?id=J.P.+MORGAN+ASSET+MANAGEMENT' },
{ name: ' BNP PARIBAS INVESTMENT PARTNERS',
link: 'mtfCompany?id=BNP+PARIBAS+INVESTMENT+PARTNERS' },
{ name: ' PICTET', link: 'mtfCompany?id=PICTET' },
{ name: ' ALLIANZ ΑΕΔΑΚ',
link: 'mtfCompany?id=ALLIANZ+%ce%91%ce%95%ce%94%ce%91%ce%9a' },
{ name: ' ALLIANZ ΑΕΔΑΚ (ΑΝΤΙΠΡ.)',
link: 'mtfCompany?id=ALLIANZ+%ce%91%ce%95%ce%94%ce%91%ce%9a+(%ce%91%ce%9d%ce%a4%ce%99%ce%a0%ce%a1.)' },
{ name: ' ALLIANZ ΕΛΛΑΣ Α.Ε.',
link: 'mtfCompany?id=ALLIANZ+%ce%95%ce%9b%ce%9b%ce%91%ce%a3+%ce%91.%ce%95.' }]}
При попытке вывода документа в формате JSON с «2-е место», вне любого блока и в конце исполнения, это то, что я получаю:
{ date: Wed Nov 26 2014 10:35:09 GMT+0200 (EET), companies: [] }
Похоже, что массив «компаний» внутри документа JSON становится опустошенным. У меня есть подозрение, что «mutuals.companies = [];» по какой-то причине линия снова выполняется.
Может ли кто-нибудь помочь в этом?
UPDATE 1:
изменил код, как предложил использовать 'async.series ...'. Это обновленная версия:
var request = require('request'),
async = require('async'),
cheerio = require('cheerio');
var base_url = 'http://www.naftemporiki.gr/finance/';
var mutuals = {};
mutuals.date = new Date();
mutuals.companies = [];
var company = {};
async.series([
function(callback) {
request(base_url + 'mtfCompanies', function (error, response, html) {
if (!error && response.statusCode == 200) {
var $ = cheerio.load(html);
$('.blueRow.texttd.name a').each(function (i, element) {
var a = $(this);
company = {};
company.name = a.text();
company.link = a.attr('href');
mutuals.companies.push(company);
});
}
});
callback(null, 'one');
},
function (callback) {
console.log(mutuals);
callback(null, 'two');
}
]);
Все еще не работает. Тем не менее, выдается JSON:
{ date: Wed Nov 26 2014 10:35:09 GMT+0200 (EET), companies: [] }
Это из-за асинхронного характера node.js? Если да, как я могу это исправить? Я хотел бы иметь возможность выводить вне цикла, потому что я считаю, что он более «правилен» программно. – dsljanus
Лучший способ управлять потоком асинхронного кода в настоящее время является модулем 'async'. Это определенно сложнее, чем синхронный код, однако взамен есть дополнительные возможности. Например, с node.js вы можете запросить несколько ресурсов параллельно и объединить их в ответ при завершении последнего. В синхронном коде вам необходимо каждый запрос каждого ресурса. Следующая версия node.js будет иметь функцию, называемую генераторами, которая сделает ваш асинхронный код более синхронным, но вам все равно нужно понять, что происходит под капотом. – Daniel
Вы предлагаете использовать «async.series» для своей цели? – dsljanus