在 运行 结束时导出为 CSV

export to CSV at the end of the run

抓取第一页数据的原始代码有效,但后来我创建了一个循环,点击“加载更多”按钮,然后抓取数据,直到不再有“加载更多”按钮。在我的 运行 结束时,它没有导出任何内容。我导出到 CSV 的代码不正确吗?我哪里出错了?

const puppeteer = require('puppeteer');
const jsonexport = require('jsonexport');

(async () => {
  const browser = await puppeteer.launch({ headless: false }); // default is true
  const page = await browser.newPage();
  await page.goto('https://www.Website.com/exercises/finder', {
    waitUntil: 'domcontentloaded',
  });

  //load more CSS to be targeted
  const LoadMoreButton =
    '#js-ex-content > #js-ex-category-body > .ExCategory-results > .ExLoadMore > .bb-flat-btn';

  do {
// clicking load more button and waiting 1sec
    await page.click(LoadMoreButton);
    await page.waitFor(1000);

    const loadMore = true;


    const rowsCounts = await page.$eval(
      '.ExCategory-results > .ExResult-row',
      (rows) => rows.length
    );

    //scraping the data
    const exerciseNames = [];
    for (let i = 2; i < rowsCounts + 1; i++) {
      const exerciseName = await page.$eval(
        `.ExCategory-results > .ExResult-row:nth-child(${i}) > .ExResult-cell > .ExHeading > a`,
        (el) => el.innerText
      );
      exerciseNames.push(exerciseName);
    }

    console.log({exerciseNames});
  } while (10000);

  const allData = [
    {
      exercise: exerciseNames,
    },
  ];
// exporting data to CSV
  const options = [exercise];
  //json export error part
  jsonexport(allData, options, function (err, csv) {
    if (err) return console.error(err);
    console.log(csv);
  });

  await browser.close();
})().catch((e) => {
  console.error(e);
});

编辑: 这就是我目前用于导出和写入 CSV 文件的内容。我得到 3 headers 但只有练习正在编写,然后没有其他内容。 Console.log 显示锻炼、肌肉目标组和正在导出的设备。我试图将它放在 3 headers(名称、设备和目标肌肉)所在的位置,然后每一行都被填充在其中。例如:深蹲、杠铃、腿,这些将排成一排,但每个都在自己的单元格中。

当前导出代码:

 const allData = [
    {
      exercise: exerciseNames,
      muscleGroup: muscleTargets,
      equipment: equipmentTypes,
    },
  ];

  var ws = fs.createWriteStream('test1.csv');


  csv.write(allData, { headers: true, delimiter: ',' }).pipe(ws);

  //json export error part
  jsonexport(allData, function (err, csv) {
    if (err) return console.error(err);
    console.log(csv);
  });

编辑 2 这是我目前的全部代码。它正在输出 allData pre-filled 信息但没有更多新数据

 const puppeteer = require('puppeteer');
const jsonexport = require('jsonexport');
const fs = require('fs');

(async () => {
  const browser = await puppeteer.launch({ headless: false }); // default is true
  const page = await browser.newPage();
  await page.goto('https://www.website.com/exercises/finder', {
    waitUntil: 'domcontentloaded',
  });

  const loadMore = true;

  const rowsCounts = await page.$$eval(
    '.ExCategory-results > .ExResult-row',
    (rows) => rows.length
  );
  let allData = [];
  for (let i = 2; i < rowsCounts + 1; i++) {
    const exerciseName = await page.$eval(
      `.ExCategory-results > .ExResult-row:nth-child(${i}) > .ExResult-cell > .ExHeading > a`,
      (el) => el.innerText
    );
    const muscleGroupName = await page.$eval(
      `.ExCategory-results > .ExResult-row:nth-child(${i}) > .ExResult-cell > .ExResult-muscleTargeted > a`,
      (el) => el.innerHTML
    );
    const equipmentName = await page.$eval(
      `.ExCategory-results > .ExResult-row:nth-child(${i}) > .ExResult-cell > .ExResult-equipmentType > a`,
      (el) => el.innerHTML
    );

    let obj = {
      exercise: exerciseName,
      muscleGroup: muscleGroupName,
      equipment: equipmentName,
    };
    allData.push(obj);
  }
  console.log(allData);

  async function fn() {
    const allData = [
      {
        exercise: 'Rickshaw Carry',
        muscleGroup: 'Forearms',
        equipment: 'Other',
      },
      {
        exercise: 'Single-Leg Press',
        muscleGroup: 'Quadriceps',
        equipment: 'Machine',
      },
      {
        exercise: 'Landmine twist',
        muscleGroup: 'Forearms',
        equipment: 'Other',
      },
      {
        exercise: 'Weighted pull-up',
        muscleGroup: 'Forearms',
        equipment: 'Other',
      },
    ];

    // json export error part
    jsonexport(allData, function (err, csv) {
      if (err) return console.error(err);
      console.log(csv);
      fs.writeFileSync('output.csv', csv);
    });
  }
  fn();

  await browser.close();
})().catch((e) => {
  console.error(e);
});

我在这里看到两个问题。

I.) 其中之一是 options 声明:

const options = [exercise]; // ❌

您试图访问 allData 对象的 exercise 属性,但没有正确的表示法。如果你真的需要将它提取到一个新数组中,你可以使用索引 [0] 进入 allData 数组的第一个元素,然后使用 dot-notation 访问 exercise 属性.

const options = [allData[0].exercise]; // ✅

注意: 我建议只保留选项 allData[0].exercise (没有包装数组)因为你的 allData 对象已经是一个数组,我明白了使结构更深没有任何好处。


II.) 第二个问题是 jsonexport npm 包的使用。我想你不小心把 allData 留在了这一行:

jsonexport(allData, options, function (err, csv) // ❌

这里你只需要options(根据docs你只能给一个对象作为输入):

jsonexport(options, function (err, csv) // ✅

编辑

根据您更新的答案,如果您对 allData 对象进行一些重构,您的问题就可以解决,因此 jsonexport 将正确识别每一列和每一行。

const jsonexport = require('jsonexport')
const fs = require('fs')

async function fn() {
  const allData = [
    {
      exercise: 'Rickshaw Carry',
      muscleGroup: 'Forearms',
      equipment: 'Other'
    },
    {
      exercise: 'Single-Leg Press',
      muscleGroup: 'Quadriceps',
      equipment: 'Machine'
    },
    {
      exercise: 'Landmine twist',
      muscleGroup: 'Forearms',
      equipment: 'Other'
    },
    {
      exercise: 'Weighted pull-up',
      muscleGroup: 'Forearms',
      equipment: 'Other'
    }
  ]

  // json export error part
  jsonexport(allData, function (err, csv) {
    if (err) return console.error(err)
    console.log(csv)
    fs.writeFileSync('output.csv', csv)
  })
}
fn()

要实现这样的结构,您应该像这样在每次迭代中扩展 allData

let allData = []
for (let i = 2; i < rowsCounts; i++) {
  const exerciseName = await page.$eval(`...row:nth-child(${i})...`,
    el => el.textContent.trim())
  const muscleGroupName = await page.$eval(`...row:nth-child(${i})...`,
    el => el.textContent.trim())
  const equipmentName = await page.$eval(`...row:nth-child(${i})...`,
    el => el.textContent.trim())

  let obj = {
    exercise: exerciseName,
    muscleGroup: muscleGroupName,
    equipment: equipmentName
  }
  allData.push(obj)
}
console.log(allData)