首页 > 解决方案 > Javascript Web Scraping 几个 url

问题描述

我想从几个 url 中获取一些数据并写入 csv 文件。但是结果对我来说并不满意,因为我没有得到所有数据(在这种情况下应该是 10)并且获取的数据的顺序不正确。应该是 1、2、3 等等,但我是随机得到的,6、10、5、1.... 从这段代码中,我有时会得到六个 h3 值,有时是五个,它是随机发生的。我的网址是 100% 好的。我正在使用异步等待语法,但它没有帮助。我是初学者。这是我的代码:

const request = require('request');
const cheerio = require('cheerio');
const fs = require('fs');
const writeSteam = fs.createWriteStream('data.csv');

let data= '';
const numOfFetchData = 10;
const numbers = Array.from(Array(numOfFetchData + 1).keys());

async function getData() {
    for await (const number of numbers) {
        request('randomURL/' + (number+1), (err, res, html) => {
            if(!err && res.statusCode == 200 && (number+1) <= numOfFetchData) {
                const $ = cheerio.load(html);
                const h3Tag = $("h3")[0].children[0].data;
                data += (number + 1) + ' ' + h3Tag + '\n'   
            } else {
                writeSteam.write(`${data}`); 
            }
        });
    };
};

getData();

我应该在我的代码中改进什么?

谢谢和最好的问候!

标签: javascriptweb-scrapingrequestcheerio

解决方案


在再次查看您的代码之后,请求库似乎没有返回承诺,但可以使用回调(使 async/await 不可用)。如果您真的希望按顺序获取代码,则可以

  1. 使用递归仅在第一个请求完成后触发下一个请求:
async function getData(numbers) {
    request('randomURL/' + (numbers[numbers.length - 1] + 1), (err, res, html) => {
        numbers.pop()
        if(!err && res.statusCode == 200 && (number+1) <= numOfFetchData) {
                const $ = cheerio.load(html);
                const h3Tag = $("h3")[0].children[0].data;
                data += (number + 1) + ' ' + h3Tag + '\n'   
        } else {
                writeSteam.write(`${data}`); 
        }
        if (numbers.length > 0) getData(numbers);
    });
};

getData(numbers);
  1. 如果您获取数据的顺序不只要结果与初始数字数组的顺序相同,我建议使用 fetch (一个承诺库)而不是请求:
async function getData() {
    let fetchPromises = numbers.map(number => fetch('randomURL/' + (number+1)));
    const results = await Promise.all(fetchPromises); // results in order
    // Handle results
};

推荐阅读