кукловод, идентифицирующий содержимое элемента после события клика - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь извлечь определенный элемент со страницы после ввода запроса и нажатия кнопки.Страница не переходит на новый URL-адрес: она просто возвращает новый HTML-контент, который мне нужно извлечь.

Это описывает, как далеко я продвинулся:

const puppeteer = require('puppeteer');

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
};

const input_val = 'some query text';

(async() => {
    const browser = await puppeteer.launch()
    const page = await browser.newPage()
    await page.goto('http://target.com', { waitUntil: 'networkidle2' })
    await page.waitFor('input[name=query]')

    await page.evaluate((input_val) => {
      document.querySelector('input[name=query]').value = input_val;
      document.querySelector('.Button').click();
    }, input_val)

    // Now I want to console.log the <strong> tag fields 
    // innerText (will be 0-3 matching elements).
    // The lines below describe in non-puppeteer what 
    // I need to do. But this has no effect.

    const strongs = await page.$$('strong')
    for(var i=0; i<strongs.length; i++) {
      console.log(strongs[i].innerText);
    }

    await timeout(2000)
    await page.screenshot({path: 'example.png'}) // this renders results page ok

    browser.close();
})();

Таким образом, вводимый запрос вводится правильно, нажатие кнопки срабатывает, и на скриншоте показано, что веб-страница отреагировала так, как ожидалось.Я просто не могу понять, как извлечь и сообщить соответствующие биты.

Я пытался разобраться во всей парадигме асинхронности / ожидания, но я все еще довольно новичок в этом.Помощь очень ценится.


Правка - Ошибка метода Vaviloff:

(node:67405) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Cannot find context with specified id undefined
    at Promise (/Users/user/node_modules/puppeteer/lib/Connection.js:200:56)
    at new Promise (<anonymous>)
    at CDPSession.send (/Users/user/node_modules/puppeteer/lib/Connection.js:199:12)
    at ExecutionContext.evaluateHandle (/Users/user/node_modules/puppeteer/lib/ExecutionContext.js:79:75)
    at ExecutionContext.evaluate (/Users/user/node_modules/puppeteer/lib/ExecutionContext.js:46:31)
    at Frame.evaluate (/Users/user/node_modules/puppeteer/lib/FrameManager.js:326:20)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:160:7)
(node:67405) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:67405) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

1 Ответ

0 голосов
/ 07 июня 2018

Существует полезная вспомогательная утилита page. $$ eval :

Этот метод запускает Array.from(document.querySelectorAll(selector)) на странице и передает его в качестве первого аргумента функции pageFunction.

Поскольку он передает массив в вычисляемую функцию, мы можем использовать .map() для извлечения необходимого атрибута:

const strongs = await page.$$eval('strong', items => items.map( item => item.innerText));

Обновление Вот полныйрабочий скрипт для тестирования:

const puppeteer = require('puppeteer');

const input_val = '[puppeteer]';
const items_selector = '.question-hyperlink';

(async() => {

    const browser = await puppeteer.launch({
        headless: false,
    })
    const page = await browser.newPage()

    await page.goto('https://stackoverflow.com/', { waitUntil: 'networkidle2' })
    await page.waitFor('input[name=q]')
    await page.type('input[name=q]', input_val + '\r');
    await page.waitForNavigation();

    const items = await page.$$eval(items_selector, items => items.map( item => item.innerText));

    console.log(items);

    await browser.close();
})();

Обновление 2
Модифицированная версия скрипта для песочницы по адресу https://diplodata.shinyapps.io/puppeteer-test/

const puppeteer = require('puppeteer');
const input_val = 'puppeteer';
const timeout = (ms => new Promise( resolve => setTimeout(resolve, ms) ));

(async() => {

    const browser = await puppeteer.launch({
        headless: false,
    })
    const page = await browser.newPage()

    await page.goto('https://diplodata.shinyapps.io/puppeteer-test/', { waitUntil: 'networkidle2' })
    await page.waitFor('#query')
    await page.type('#query', input_val);
    await page.click('#go');
    await timeout(500);
    const items = await page.$$eval('strong', items => items.map( item => item.innerText));

    console.log(items);

    await browser.close();
})();

Производит следующеерезультат:

['При нажатии ниже должно читаться:', '', 'puppeteer']

...