javascript 如何用 puppet 师点击选择列表中的元素

ukxgm1gy  于 2023-02-21  发布在  Java
关注(0)|答案(3)|浏览(158)

我试图创建一个自动化的一些网站与 puppet 戏,我有一个麻烦,当我试图点击选择列表内的元素。
我在谷歌上搜索后发现,只有当列表在"select"元素中时,才能选择一个项目。我的问题是,我试图自动化的HTML在一个"div"中:

<div class="dropdown open dropdown--gray">
  <div class="dropdown__header">
     <div class="dropdown__field">other</div>
     <div class="dropdown__opener">
        <span class="icon icon-chevron-down"></span>
     </div>
  </div>
  <div class="dropdown__list">
    <div class="dropdown__list-item selected">other</div>
    <div class="dropdown__list-item">.org</div>
    <div class="dropdown__list-item">.co.uk</div>
    <div class="dropdown__list-item">.net</div>
    <div class="dropdown__list-item">.gov</div>
    <div class="dropdown__list-item">.de</div>
    <div class="dropdown__list-item">.fr</div>
    <div class="dropdown__list-item">.nl</div>
    <div class="dropdown__list-item">.com</div>
    <div class="dropdown__list-item">.be</div>
    <div class="dropdown__list-item">.jpg</div>
  </div>
</div>

我已经试过了:

await page.click('div.dropdown__field');
const elementHandle4=await page.$$("div.dropdown__list-item");
await elementHandle4[8].click();

但实际上它没有点击元素。当我在这段代码运行后手动打开列表时,我看到它向下滚动了列表的滚动条,但没有点击元素。
谢谢

kxkpmulp

kxkpmulp1#

试试这样的方法:

await page.click('.dropdown__field');
await page.click('.dropdown__list > div:nth-child(8)');

更新日期:

它看起来像是视口中的问题,因为它工作正常,并选择了'.nl'选项,而没有使用以下脚本进行任何滚动:

(async () =>  {
    const browser = await puppeteer.launch({ 
        headless: false,
        defaultViewport: null,
    });
    const page = await browser.newPage();
    await page.goto('https://userinyerface.com/game.html');
    await page.click('.dropdown__field');
    await page.click('.dropdown__list > div:nth-child(8)');
})();

但如果我删除defaultViewport: null属性,它将不起作用

w1e3prcc

w1e3prcc2#

我猜你需要看到那个元素才能触发点击事件。首先,你必须滚动到元素的位置才能看到元素,然后触发点击事件。
对我很有效

const ListItemIndex = 10, ListItem = document.querySelector(`.dropdown__list > div:nth-child(${ListItemIndex})`);
document.querySelector(".dropdown__list").scroll({ behavior: 'smooth', top: ListItem.offsetTop });
ListItem.click()
jchrr9hc

jchrr9hc3#

我有一个和你类似的问题。在我的例子中,HTML看起来像这样:

<select id="locationIdentifier" name="..." class="..." title="...." size="....">
    <option value="..." selected="selected">CITY NAME Station, CITY NAME</option>
    <option value="...">CITY NAME</option>
    <option value="...">CITY NAME City Centre</option>
    <option value="...">CITY NAME, City Of</option>
    <option value="...">CITY NAME Airport, CITY NAME</option>
    <option value="...">CITY NAME East, CITY NAME</option>
    <option value="...">CITY NAME North, CITY NAME</option>
    <option value="...">CITY NAME NorthWest, CITY NAME</option>
    <option value="...">CITY NAME South, CITY NAME</option>
    <option value="...">CITY NAME West, CITY NAME</option>
</select>

为了简洁起见,我删除了所有不相关的类名和属性,并将它们替换为...
这里我想从列表中选择第二个选项,即:

<option value="...">CITY NAME</option>

这是第二种选择,所以这是可行的,但并不理想:

await page.click('select#locationIdentifier > option:nth-child(2)');

如果在服务器端进行了一些更改,导致不同的排序,会发生什么?这可能很难用Puppeteer这样的自动化系统检测到,并可能导致不连续的数据-假设您这样做是为了抓取数据,然后您希望分析。
更好的方法是:

const index = await page.evaluate(() => {
    const elements = document.querySelectorAll('select#locationIdentifier > option');

    for(let index = 0; index < elements.length; ++ index) {
        const text = elements[index].innerText;

            if(text === 'CITY NAME') {
                return index + 1;
            }
        }

        return -1;
    });

    if(index === -1) {
        // Error
        console.log(`Error: Failed to find CITY NAME option`);
    }
    else {
        const tmpString = 'select#locationIdentifier > option:nth-child(' + index + ')';
        await page.click(tmpString);
    }

+ 1添加到索引是因为HTML从nth-child中的1开始索引,而通过从querySelectorAll获得的元素进行迭代显然是从0开始的。

相关问题