最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to click on element from select list with puppeteer - Stack Overflow

programmeradmin5浏览0评论

I'm trying to create a automation on some website with puppeteer and I have a trouble with that when I try to click on element inside select list.

All I found about that after some google search is to select an item but only when the list is inside "select" element. My problem is that the HTML I try to automate is inside a '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"></div>
    <div class="dropdown__list-item">.co.uk</div>
    <div class="dropdown__list-item"></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"></div>
    <div class="dropdown__list-item">.be</div>
    <div class="dropdown__list-item">.jpg</div>
  </div>
</div>

I have tried this:

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

but actually its not click on the element. When I open manually the list after this code ran, I see that its scrolled down the scroller of the list but not clicked on the element.

Thanks

I'm trying to create a automation on some website with puppeteer and I have a trouble with that when I try to click on element inside select list.

All I found about that after some google search is to select an item but only when the list is inside "select" element. My problem is that the HTML I try to automate is inside a '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"></div>
    <div class="dropdown__list-item">.co.uk</div>
    <div class="dropdown__list-item"></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">.</div>
    <div class="dropdown__list-item">.be</div>
    <div class="dropdown__list-item">.jpg</div>
  </div>
</div>

I have tried this:

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

but actually its not click on the element. When I open manually the list after this code ran, I see that its scrolled down the scroller of the list but not clicked on the element.

Thanks

Share Improve this question asked Jul 5, 2019 at 10:49 Guy CohenGuy Cohen 1941 gold badge1 silver badge13 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

Try something like this:

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

UPDATE:

It looks like the problem in the viewport because it works correctly and selects the '.nl' option without any scrolling with the following script:

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

But it will not work if I remove the defaultViewport: null property

I guess you need to see that element to trigger click event. First, you must scroll to the position of the element to see the element then trigger the click event.


It works for me

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

I had a similar question to yours. In my case the HTML looked like this:

<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>

I have removed all the irrelevant class names and attributes, replacing them with ... for brevity.

What I wanted here was to select the second option from the list, which is:

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

It is the second option, so this will work, but it isn't ideal:

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

What happens if some change is made on the server side resulting in a different ordering? This could be hard to detect with an automated system like Puppeteer, and might lead to discontinuous data - assuming you are doing this to scrape data, which you then wish to analize.

A better approach is this:

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);
    }

The addition of + 1 to the index is because the HTML indexes from 1 in nth-child, whereas iterating through the elements obtained from querySelectorAll obviously starts from 0.

发布评论

评论列表(0)

  1. 暂无评论