首页 > 解决方案 > 如何在 Node.js 中按顺序发送多个 http 请求?

问题描述

我正在使用 Node.js 创建一个爬虫。

在目标网页中,有 10+ 个类别。

我可以使用我的爬虫获取它们。

我对每个类别提出要求。(10+ 个请求)

然后,每个类别页面都有 100 多个项目。

我对每个项目提出要求。(超过 100 个请求)

所以我需要 10+ * 100+ 个请求!

我的代码在这里。

const axios = require("axios")
const cheerio = require("cheerio");

async function request(url) {
    return await axios.get(url);
}

function main() {
    request(url).then(html => {
        const $ = cheerio.load(html.data);
        const categoryArray = $('table.table tbody').children('tr').toArray()

        categoryArray.map(category => {
            console.log("category: " + category.name)

            request(category.url).then( html => {
                const $ = cheerio.load(html.data);
                const items = $('table.table tbody').children('tr').toArray()

                console.log("item.length: " + items.length)

                items.map(item => {
                    request(item).then(html => {
                        const $ = cheerio.load(html.data);
                        const itemDetails = $('table.table tbody').children('tr').toArray()

                        console.log("item.name: " + itemDetails.name)
                    })
                })
            })
        })
    })
}

但它不起作用...

console.log 看起来像:

category: A
category: B
category: C
category: D
category: E
category: F
category: G
category: H
category: I
category: J
category: K
category: L
category: M
category: N
item.length: 0
item.length: 100
item.length: 100
item.length: 0
item.length: 100
item.length: 0
item.length: 0
item.length: 100
item.length: 0
item.length: 0
item.length: 0
item.length: 0
item.length: 0
item.length: 0
item.name: item1
(node:5409) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:5409) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

第一次,它看起来工作正常,但几秒钟后,它不起作用。

我认为“categoryArray.map”不会等待孩子的请求。

所以 HTTP 连接线程数达到最大值。

我不知道如何解决它...

标签: javascriptnode.jsweb-crawler

解决方案


你的问题是Array.prototype.map不知道Promise,所以它不能等待你的请求。

而不是使用map,只需使用async/await并使用迭代数组for ... of

async function main() {
    const categoryArray = await request(categoryUrl)
    for (const category of categoryArray) {
        console.log("category: " + category.name)

        const items = await request(category.url)
        console.log("item.length: " + items.length)

        for (const item of items) {
            const itemDetails = await request(item)
            console.log("item.name: " + itemDetails.name)
        }
    }
}

推荐阅读