Перво-наперво: поскольку Instagram является мощным приложением React на основе JavaScript, нужные вам селекторы могут быть недоступны сразу после загрузки страницы. Поэтому нам следует подождать, пока они появятся в DOM:
await page.waitForSelector('.v1Nh3.kIKUG._bz0w');
Теперь с page.evaluate мы получаем сообщения, но, поскольку вам нужны только ссылки внутри этих сообщений, давайте сразу же захватим их вquery:
const result = await page.evaluate(() => {
// Get elements into a NodeList
const elements = document.querySelectorAll('.v1Nh3.kIKUG._bz0w a');
...
}
Но мы не можем преобразовать элементы из Nodelist в Array и просто вернуть их, потому что они по-прежнему являются узлами DOM, сложными несериализуемыми объектами, и они должны быть serializable чтобы иметь возможность вернуться с page.evaluate
. Поэтому вместо того, чтобы возвращать полные узлы, мы просто получим то, что нам нужно: urls из атрибута href:
const result = await page.evaluate(() => {
// Get elements into a NodeList
const elements = document.querySelectorAll('.v1Nh3.kIKUG._bz0w a');
// Convert elements to an array,
// then for each item of that array only return the href attribute
const linksArr = Array.from(elements).map(link => link.href);
return linksArr;
});
Другие способы сделать это
В вашем вопросеВы упомянули page.$$
метод. Здесь действительно применимо получение ручек объектов, которые мы ищем. Но код для их перебора не очень приятен:
const results = await page.$$('.v1Nh3.kIKUG._bz0w a')
for (const i in results)
{
console.log(await(await(await results[i]).getProperty("href")).jsonValue());
}
Мой любимый способ получить эти ссылки - использовать метод page.$$eval
:
const results = await page.$$eval('.v1Nh3.kIKUG._bz0w a', links => links.map(link => link.href))
Это делает именното же самое, что мы сделали в page.evaluate
решении, но гораздо более кратким способом.