簡體   English   中英

在Node / Express中使用Request.js和Cheerio.js返回空數組

[英]Using Request.js and Cheerio.js in Node/Express return empty array

我正在Express中使用Request.js和Cheerio.js構建一個簡單的刮板。 現在,我只在尋找網站的標題。 而不是一個一個地抓取網站,而是將列表放在一個數組中。 我解析它們,然后使用Cheerio.js查找網站的標題。 當我用控制台記錄標題時,它們很好用,但是我想最終在HTML頁面上顯示它們。 請注意,我是編程的新手,所以如果您能提供詳細的反饋,那將非常有用(下面是我一直在研究的代碼)。 提前致謝!

function parseSites(urls) {
var parsedSites = [];
urls.forEach(function(site) {
        request(site, function(err, res, body) {
            if(err) {
                console.log(err);
            } else {
                var $ = cheerio.load(body);
                parsedSites.push($('title').text());
                }
            }    
        });             
    });
    return parsedSites;
}

請參考以下代碼,了解有效的實現方式

var request = require('request-promise')
    var cheerio = require("cheerio")

    function parseSites(urls, callback) {
        var parsedSites = [];
        var promiseList = urls.map(getPage)

        Promise.all(promiseList).then(function (data) {
            callback(data.map(parse))
        })

        return parsedSites;
    }

    function getPage(url) {

        return request.get(url)
    }

    function parse(body) {
        console.log("parsing body")
        var $ = cheerio.load(body);
        return $('title').text()
    }

    parseSites(['https://www.google.com','https://www.facebook.com'],function(data) {
        console.log(data)
    })

首先,您需要了解異步和同步代碼之間的區別。 讓我們來看一個例子:

function testFor() {
    for(let i=0;i<5;++i){
        console.log(i);
    }
}

-

console.log('start:');
testFor();
console.log('end:');

// Here you get the expected output because this code is synchronous.
//output:
    start:
    0
    1
    2
    3
    4
    end:

-

console.log('start:');
setTimeout(testFor,1000);
console.log('end:');

// Here you don't get your expected output because setTimeout is asynchronous .
//output:
    start:
    end:
    0
    1
    2
    3
    4
  1. 首先是console.log('start:'); 叫做。
  2. 然后setTimeout(testFor,1000); (但它是異步的,調用將在1秒內執行)。
  3. 在console.log('end:');之后; 叫做。
  4. 最后1秒后,執行testFor()並輸出0 1 2 3 4

接下來的一點是,您的代碼中有錯誤!

function parseSites(urls) {
    var parsedSites = [];
    urls.forEach(function(site) {
        request(site, function(err, res, body) {
            if(err) {
                console.log(err);
            } else {
                var $ = cheerio.load(body);
                parsedSites.push($('title').text());
            }
        //} ! THIS bracket should be removed
        });
    });
    return parsedSites;
}

因此,您的問題是,forEach循環中的“請求”是一個異步函數,一旦網頁有響應,該函數就會調用回調函數“(function(err,res,body))”。

我對此的解決方案:

'use strict'

const cheerio = require('cheerio');
const request = require('request');
const async = require('async');

const urls = ['http://stackoverflow.com/','http://hackaday.com/','https://www.raspberrypi.org/','https://cheerio.js.org/'];

//SOLUTION 1: do what you need to do when all calls are done using recursion
let i=0;
let parsedSites = [];
parseSites(urls[i],parsedSites);
function finalCall(sites) {
    console.log(sites);
}
function parseSites(site,parsedSites) {
    ++i;
    request(site, function(err, res, body) {
        if(err) {
            console.log(err);
        } else {
            let $ = cheerio.load(body);
            let title = $('title').text();
            console.log(title);
            parsedSites.push(title);
        }
        if(i<urls.length){
            parseSites(urls[i],parsedSites);// recursive call;
        }
        else{
            finalCall(parsedSites);// when all sites are done.
        }
    });
    //return parsedSites;// cant return! we are in async calls!
}


//SOLUTION 2: do what you need to do when all calls are done using 'async'
parseSites(urls);
function finalCall(sites) {
    console.log(sites);
}
function parseSites(urls) {
    let parsedSites = [];
    async.each(urls,function parseSite(site, callback) {
        request(site, function (err, res, body) {
            if (err) {
                callback(err);
            } else {
                let $ = cheerio.load(body);
                parsedSites.push($('title').text());
                callback();
            }
        })
    },function (err) {
        if(err) console.log(err);
        else finalCall(parsedSites);
    });
}

異步github頁面

異步示例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM