我正在创建一个使用puppeteer的机器人,需要能够从下拉菜单中 Select 一个动态选项. 但我也是新来的,所以我真的不知道这是不是可能的.

我想得到一个列表内的所有选项,然后能够 Select 任何选项使用索引像这样的page.click(optionsList[3]);然后page.click(optionsList[0]);

Html代码如下所示:

<div class="parentClass">
    <!-- Each one of this divs represent an option from the dropdown menu -->
    <div data-visualcompletion="ignore-dynamic">
        <!-- <Lot of code 1 ...></> -->
    </div>
    <div data-visualcompletion="ignore-dynamic">
        <!-- <Lot of code 0 ...></> -->
    </div>
    <div data-visualcompletion="ignore-dynamic">
        <!-- <Lot of code 0 ...></> -->
    </div>
    <div data-visualcompletion="ignore-dynamic">
        <!-- <Lot of code 1 ...></> -->
    </div>
    <div data-visualcompletion="ignore-dynamic">
        <!-- <Lot of code 0 ...></> -->
    </div>
    <div data-visualcompletion="ignore-dynamic">
        <!-- <Lot of code 0 ...></> -->
    </div>
    <!-- ...and so on -->
</div>

正如您所看到的,"parentClass"内的div中的代码可能会有所不同,只有两种类型(代码1和代码0)我没有包括完整的代码,因为很多,但如果您需要的话,我可以添加它.

是否有可能捕获列表中的所有选项(具有data-visualcompletion属性的选项),并能够使用索引:page.click(optionsList[3]); Select 任何选项?

我还想从另一个列表中的每个选项中获取文本,因为我假设optionsList将存储某种类型的 puppeteer 操纵者对象,代表下拉菜单中的每个选项或类似的东西.所以我想我需要另一个列表optionsText来存储每个选项的文本.

我try 过(成功):

  // Fetch the parent where all categories live (must be called after click on dropdown menu)
  let parentDomCategories = await page.$(constants.cssMpCreateItemCategoryContainer);
  // Fetch all categories in a list
  let domCategories = await parentDomCategories.$$(constants.cssMpCreateItemCategoryAttr);

  // Web categories = 33 & totalCats = 33. We good to go.
  let totalCats = await page.evaluate(el => el.length, domCategories);
  console.log(`Total number of categories: ${totalCats}`);

但我不知道我还能用domCategories美元做什么 我已经在网上搜索,这应该打印的类别:

  let categoriesText = await page.evaluate(el => el.textContent, domCategories);
  console.log(`Text?: ${categoriesText}`);

我得到了undefined.

当我运行时,domCategories是什么类型的:

  console.log(`typeof domCategories: ${typeof domCategories}`);

我得到的回报是反对.

通向domCategories指甲的唯一方法是通过page.evaluate

domCategories是ElementHandle吗?

(async () => {

  // Launch the browser and open a new blank page
  // Configuration when using StealthPlugin 
  const browser = await puppeteer.launch({
    headless: false,
    // ignoreDefaultArgs: ["--enable-automation"],
  });
  // Disable Facebook notifications
  const context = await browser.defaultBrowserContext();
  await context.overridePermissions('https://www.facebook.com', ['geolocation', 'notifications']);

  const page = await browser.newPage();

  await page.goto('https://www.facebook.com/', {waitUntil: ['domcontentloaded', 'networkidle2']});

  await page.waitForSelector('input[id="email"]', {visible: true});
  await page.type(
    'input[id="email"]', "email",
  );
  await page.type(
    'input[id="pass"]', "pass",
  );

  let nav = page.waitForNavigation();
  await page.click( 'button[name="login"]' );
  await nav;

  await page.goto(
    'https://www.facebook.com/marketplace/create/item/' , {waitUntil: ['domcontentloaded', 'networkidle2']}
  );
  // click dropdown menu
  await page.click( 'div[class="xamitd3 x1pi30zi"]' );

  // Fetch the parent where all categories live (must be called after click on dropdown menu)
  let parentDomCategories = await page.$( 'div[class="x1iz1s3 x1rife3k x2ewi1q"]' );

  // Fetch all categories in a list
  let domCategories = await parentDomCategories.$$('div[data-visualcompletion="ignore-dynamic"]');


  // Facebook categories = 33 & totalCats = 33. We good to go.
  let totalCats = await page.evaluate(el => el.length, domCategories);
  console.log(`Total number of categories: ${totalCats}`);

  // Doesn't return anything
  let categoriesText = await page.evaluate(el => el.textContent, domCategories);
  console.log(`Text?: ${categoriesText}`);

  // object
  console.log(`typeof domCategories: ${typeof domCategories}`);


  console.log('Trying loop');
  try {
    // doesn't even enter loop
    for (let index=0; index < domCategories.lengthl; index++)
    {
      const element = domCategories[index];
      const text_ = await page.evaluate(element => element.textContent, element);
      console.log(text_);
    }
    console.log('\t\tSuccessed');
  }
  catch (error){
    console.log('Error in loop');
    console.log(error.message);
  }
  console.log('Finish loop');

  /* try {
    await page.evaluate(el => el.click(), domCategories);
  }
  catch (error){
    console.log('Error in clicking categories')
    console.log(error.message);
  }

  try {
    console.log('Error in indexing domCategories')
    console.log(domCategories[0]);
  }
  catch (error){
    console.log(error.message);
  } */


  await browser.close();


})();

推荐答案

我认为您正在try 按文本内容单击某个元素.您可以try 使用属性 Select 器来调整this answer以匹配您的用例:

const puppeteer = require("puppeteer"); // ^21.6.0

const html = `<!DOCTYPE html><html><body>
<div class="parentClass">
  <div data-visualcompletion="ignore-dynamic">foo</div>
  <div data-visualcompletion="ignore-dynamic">bar</div>
  <div data-visualcompletion="ignore-dynamic">baz</div>
</div>
<script>
document.querySelectorAll(".parentClass").forEach(e => {
  e.addEventListener("click", e => e.target.textContent = "clicked!");
});
</script></body></html>`;

let browser;
(async () => {
  browser = await puppeteer.launch({headless: "new"});
  const [page] = await browser.pages();
  await page.setContent(html);
  const sel = '[data-visualcompletion="ignore-dynamic"]::-p-text(bar)';
  const el = await page.waitForSelector(sel);
  await el.click();

  // or try an untrusted click if the Puppeteer click doesn't work:
  // await el.evaluate(el => el.click());

  const text = await page.$eval("::-p-text(clicked)", el => el.textContent);
  console.log(text); // => clicked!
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

如果这在您的实际网站上不起作用,可能会有一些特定于站点的行为,比如可见性、元素位于阴影DOM或IFRAME中、异步加载、服务器在无头模式下阻止您,或者许多其他边缘情况之一.如果是这样的话,请分享实际页面.

Javascript相关问答推荐

序列查找器功能应用默认值而不是读取响应

禁用从vue.js 2中的循环创建的表的最后td的按钮

vanillajs-datepicker未设置输入值,日期单击时未触发更改事件

React:未调用useState变量在调试器的事件处理程序中不可用

如何修复循环HTML元素附加函数中的问题?

没有输出到带有chrome.Devtools扩展的控制台

将2D数组转换为图形

当运行d3示例代码时,没有显示任何内容

函数返回与输入对象具有相同键的对象

MathJax可以导入本地HTML文档使用的JS文件吗?

WebGL 2.0无符号整数输入变量

可更改语言的搜索栏

React.Development.js和未捕获的ReferenceError:未定义useState

将Node.js包发布到GitHub包-错误ENEEDAUTH

如何使用基于promise (非事件emits 器)的方法来传输数据?

与svg相反;S getPointAtLength(D)-我想要getLengthAtPoint(x,y)

在ChartJS中使用spanGaps时,是否获取空值的坐标?

使用props 将VUE 3组件导入JS文件

更改管线时不渲染组件的react

每隔一行文本段落进行镜像(Boustrophedon)