递归调用基于诺言的javascript函数,以供网络抓取工具检查下一页

时间:2019-01-21 09:13:18

标签: javascript node.js asynchronous recursion promise

我正在构建一个Ebay网页抓取器作为辅助项目,我需要知道如何多次调用基于promise的功能,才能将卖方的所有商品放在多个页面上,直到到达商品的结尾为止。

基本上,使用Javascript和Node.js,如果卖方只有一页商品,我将其刮掉,一切都很好。

当他有多个页面时,事情变得复杂了,我需要多次调用promise函数并将链接返回到每个页面。我尝试了promise循环,尝试了递归,并且尝试了async / await。似乎没有任何作用。

我将为您提供一个代码段:

const request = require('request-promise');
const cheerio = require('cheerio');

const options = {
    url : 'https://www.ebay.com/sch/i.html?_nkw=&_in_kw=1&_ex_kw=&_sacat=0&_udlo=&_udhi=&_ftrt=901&_ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_sadis=15&_stpos=29582&_sargn=-1%26saslc%3D1&_salic=1&_fss=1&_fsradio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=brickearth&_sop=12&_dmd=1&_ipg=50&_fosrp=1',
    //url : 'https://www.ebay.com/sch/i.html?_nkw=&_in_kw=1&_ex_kw=&_sacat=0&_udlo=&_udhi=&_ftrt=901&_ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_sadis=15&_stpos=29582&_sargn=-1%26saslc%3D1&_salic=1&_fss=1&_fsradio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=supersavingsdeals&_sop=12&_dmd=1&_ipg=200&_fosrp=1',
    method : 'GET',
    headers : {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
    }
}

const pageLinks = [];

async function getPagesRecursive(link) {
    await request(link, (error, response, html) => {
        if(!error && response.statusCode === 200) {
            const $ = cheerio.load(html);
            const nextPage = $('td.pagn-next > a').attr('href');
            pageLinks.push(link)
            if(nextPage) {
                return getPagesRecursive(nextPage);
            }
            console.log(pageLinks);
        }
    })
}

我很确定Java和Node.js专家对您而言一无是处;)我已经使用async / await将其发布给您,但是我想在请求模块中使用promises,因为我感觉我知道他们更好,更个人而言,我尝试了其他所有方法均未成功:)

我为你们提供了两个URL,供您尝试请求模块的options对象。第一个是指向具有多个项目的卖方的链接,它应该获取所有页面链接。第二个链接是一个只有一页的卖方,它应该只获得该卖方的一页链接。

提前谢谢;)

1 个答案:

答案 0 :(得分:1)

由于request返回承诺,因此您无需使用回调,也无需使用async await语法-仅返回承诺。

此外,如果您基于promise满足的值构建链接数组,那么最好不要填充全局的pageLinks数组。

function getPagesRecursive(link) {
    return request(link).then(html => {
        const $ = cheerio.load(html);
        const nextPage = $('td.pagn-next > a').attr('href');
        return nextPage ? getPagesRecursive(nextPage).then(links => [link, ...links])
                        : [link];
    });
}

// Use:
getPagesRecursive(firstPage).then(links => console.log(links))
                            .catch(err => console.log("request failed", err));