gpt4 book ai didi

javascript - 循环内的“page.evaluate()”(在 Puppeteer 中)返回相同的值

转载 作者:行者123 更新时间:2023-12-04 08:58:03 28 4
gpt4 key购买 nike

概览:
这不是实际问题,但我已经简化了问题并将其转换为更容易理解的问题。我从 page.evaluate() 返回相同的数据放置在 for...of 内在循环的每次迭代中循环。估计是关闭的原因,很久没用JS编程了,没能实现IIFEasync职能。另外,我认为我们无法实现 forEach而不是 for...ifasync职能。如果发布的问题太长,我提前道歉,但我想说清楚。
enter image description here
说明:
我正在尝试抓取一个包含杂货数据的网页。杂货种类 (如蔬菜、水果、乳制品、面包店)可以从选择元素(下拉菜单)中选择。选择选项时,购物 list 将根据类型显示。

  • grocery-choice是让我们选择选项的 select 标签的 id
    (即 select#grocery-choice)
  • grocery-item是包含杂货店每件商品数据的 div 类。(即 div.grocery-item )例如:杂货类 水果它包含有关 的数据香蕉、苹果等每个 div 都有一个 <h4>和两个 <p>分别用于名称、价格和可用性的元素。

  • 我正在遍历数组中的项目( [ 'fruit', 'vegetable', 'bakery'] ),然后将每个项目作为 JSON 添加到数组 grocery_info 中并返回 grocery_inf来自 page.evaluate() . grocery_all是分配返回值的变量。
    这是我有问题的代码部分。
    async function scrape_and_display(item) {
    await page.select("select#grocery-choice", item);
    await page.waitForSelector("div.grocery-item");
    const grocery_all = await page.evaluate((x) => {
    let grocery_info = [];
    let grocery_list = document.querySelectorAll("div.grocery-item");
    grocery_list.forEach((item) => {
    grocery_info.push({
    name: item.getElementsByTagName("h4")[0].innerText,
    price: item.getElementsByTagName("p")[0].innerText,
    availability: item.getElementsByTagName("p")[1].innerText,
    });
    });
    return grocery_info;
    });
    console.log(grocery_all);
    }

    for (item of ["fruit", "vegetable", "bakery"]) {
    await scrape_and_display(item);
    }
    所需输出:
    [
    { name: 'Banana', price: '$10 / kg', availability: 'In Stock' },
    { name: 'Apple', price: '$20 / kg', availability: 'In Stock' },
    { name: 'Grape', price: '$45 / kg', availability: 'Out of Stock' },
    { name: 'Orange', price: '$10 / kg', availability: 'In Stock' }
    ]
    [
    { name: 'Brocli', price: '$10 / kg', availability: 'In Stock' },
    { name: 'Pumpkin', price: '$15 / kg', availability: 'In Stock' },
    { name: 'Lettuce', price: '$7 / kg', availability: 'In Stock' }
    ]
    [
    { name: 'Bread', price: '$15 / piece', availability: 'In Stock' },
    { name: 'Apple Pie', price: '$20 / piece', availability: 'In Stock' }
    ]
    当前输出:
    [
    { name: 'Bread', price: '$15 / piece', availability: 'In Stock' },
    { name: 'Apple Pie', price: '$20 / piece', availability: 'In Stock' }
    ]
    [
    { name: 'Bread', price: '$15 / piece', availability: 'In Stock' },
    { name: 'Apple Pie', price: '$20 / piece', availability: 'In Stock' }
    ]
    [
    { name: 'Bread', price: '$15 / piece', availability: 'In Stock' },
    { name: 'Apple Pie', price: '$20 / piece', availability: 'In Stock' }
    ]
    这是实际问题 , 而不是杂货类别,我有尼泊尔州,而不是杂货,我需要学校;我没有登录到控制台,而是将其导出为 CSV 文件。
    如果您检查 CSV 文件,您会发现所有相同的数据,即下拉列表的最后一项,即最后一个选项。
    这是工作代码:
    const puppeteer = require("puppeteer");
    const createCsvWriter = require("csv-writer").createObjectCsvWriter;

    (async () => {
    const browser = await puppeteer.launch({
    headless: false,
    IgnoreHTTPSErrors: true,
    });
    const page = await browser.newPage();
    await page.setViewport({ width: 1366, height: 820 });

    await page.goto("https://www.pabson.org/#!/School-locator");
    const selectOptions = await page.$$eval(
    "select#ddlState > option",
    (options) => {
    return options.map(function (option) {
    return { option: option.innerHTML, value: option.value };
    });
    }
    );
    async function scrape_and_save(item) {
    // let item = obj;
    await page.select("#ddlState", item.value);
    try {
    await page.waitForSelector("div.count-box-info");
    const school_array = await page.evaluate((x) => {
    let school = [];
    let school_list = document.querySelectorAll("div.count-box-info");
    school_list.forEach((item) => {
    school.push({
    name: item.getElementsByTagName("h4")[0].innerText,
    phone: item.getElementsByTagName("p")[0].innerText,
    email: item.getElementsByTagName("p")[1].innerText,
    });
    });
    return school;
    });

    let csvWriter = createCsvWriter({
    path: "school_" + item.option + ".csv",
    header: [
    { id: "name", title: "NAME" },
    { id: "phone", title: "PHONE" },
    { id: "email", title: "EMAIL" },
    ],
    });

    csvWriter
    .writeRecords(school_array) // returns a promise
    .then(() => {
    console.log("...Done");
    });
    } catch (e) {
    console.log(e);
    }
    }
    for (item of selectOptions) {
    await scrape_and_save(item);
    }
    await browser.close();
    })();
    任何帮助将不胜感激。提前致谢。

    最佳答案

    似乎重新渲染学校列表需要一些时间,而您不会等待这个时间,因此您的代码只是太快地抓取了相同的数据。您可以等待一些更改,例如更改列表上方的主要信息文本:

      async function scrape_and_save(item) {
    const previousData = await page.evaluate(
    () => document.querySelector('#divschoolData').innerText
    );

    await page.select("#ddlState", item.value);
    await page.waitForFunction(
    data => { return data !== document.querySelector('#divschoolData').innerText; },
    {},
    previousData,
    );

    try {
    // ...
    顺便说一句,尝试始终为循环变量添加 const/let 以防止范围问题:
      for (const item of selectOptions) {
    并使用严格模式不要忘记这一点)

    关于javascript - 循环内的“page.evaluate()”(在 Puppeteer 中)返回相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63704842/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com