[英]How to select a DOM Element to scroll on it in Puppeteer
我對Puppeteer和await / async語法很陌生。 我正在嘗試構建一個機器人來嘗試從Instagram獲取數據。 具體來說,我想獲得給定個人資料的關注者。 一切正常,直到彈出關注者窗口。 我想選擇DOM元素來滾動它,並在每次迭代時將跟隨者推入數組中。 我在論壇上進行了搜索,並嘗試了不同的方法,但始終返回未定義狀態。 我可以獲取ElementHandle(scrollBox3)並獲取諸如scrollHeight的屬性,但不能獲取實際的DOM Element。 以下代碼包含文件不同部分的說明。
任何幫助,將不勝感激 :)
下一部分選擇DOM元素。 CRED文件是我的用戶名和密碼所在的位置。
const puppeteer = require('puppeteer');
const CREDS = require('./creds');
// Dom Elements
const loginPage = 'https://www.instagram.com/accounts/login/';
const usernameInput = 'input[name="username"]';
const passwordInput = 'input[name="password"]';
const submitButton = 'button[type="submit"]';
const userToSearch = 'nicolekidman';
const searchUser = `https://www.instagram.com/${userToSearch}`;
const followers = `a[href='/${userToSearch}/followers/']`;
此部分記錄在數組的scrollBox中可見的關注者。
// Extract followers from a user profile
const extractFollowers = () => {
let followers = [];
let elements = document.getElementsByClassName('FPmhX notranslate _0imsa ');
for (let element of elements)
followers.push(element.textContent);
return followers;
}
這是代碼中斷的滾動功能。 基本上,我想循環並在此scrollBox上滾動,但是我無法獲取DOM元素。
// Scrolling Function
async function scrapeInfiniteScrollItems(
page,
extractFollowers,
followersTargetCount,
scrollDelay = 1000,
) {
let items = [];
// Next 2 lines return undefined
// .isgrP and .PZuss are classes inside this div, PZuss is the one we want to scroll on
let scrollBox1 = await page.$eval('.isgrP', el => el.querySelector('body > div:nth-child(15) > div > div > div.isgrP > ul > div'));
let scrollBox2 = await page.$eval('body > div:nth-child(15) > div > div > div.isgrP > ul > div', el => el);
// Next line returns an ElementHandle
let scrollBox3 = await page.$('.PZuss');
console.log(scrollBox3);
let scrollBoxHeight = await page.$eval('.PZuss', el => el.scrollHeight);
console.log(scrollBoxHeight);
try {
while (items.length < followersTargetCount) {
items = await page.evaluate(extractFollowers);
console.log(extractFollowers());
// await page.evaluate('scrollBox.scrollTo(0, scrollable_popup.scrollHeight)');
// await page.waitForFunction(`scrollBox.scrollHeight > ${previousHeight}`);
// await page.waitFor(scrollDelay);
}
} catch(e) { }
return items;
}
這是實際的異步功能,我將在其中進行所有工作以訪問Instagram並調用滾動功能以記錄給定配置文件的關注者。
(async() => {
// headless false for visual debugging in browser
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.goto(loginPage, {waitUntil: 'networkidle2'});
// Type username
await page.click(usernameInput);
await page.keyboard.type(CREDS.username);
// Type password and submit
await page.click(passwordInput);
await page.keyboard.type(CREDS.password);
await page.click(submitButton);
await page.waitFor(2000);
// Search User with URL
await page.goto(searchUser);
await page.click(followers);
await page.waitFor(2000);
const findFollowers = await scrapeInfiniteScrollItems(page, extractFollowers, 100);
console.log(findFollowers);
await page.screenshot({ path: '../screenshots/insta.png' });
// await browser.close();
})();
我使用.hover()方法解決了這個問題。 我在每次迭代中選擇div中的最后一個元素,這會觸發滾動到視圖。 這樣,我就能獲得定義為參數的關注者數量。 這樣很方便,功能也更短。 雖然仍然無法選擇DOM元素本身。
async function scrapeInfiniteScrollItems(
page,
extractFollowers,
followersTargetCount
) {
let items = [];
// Next line returns undefined
let x;
try {
while (items.length < followersTargetCount) {
items = await page.evaluate(extractFollowers);
childToSelect = items.length;
await page.hover(`div.isgrP > ul > div > li:nth-child(${childToSelect})`);
}
} catch(e) { }
items.length = followersTargetCount;
return items;
}
是的,我對Instagram不熟悉,但是我將逐步與您合作。 您的代碼一目了然(在我沒有與Instagram簽約的情況下,我無法測試此代碼很不幸),但其中有些地方很突出。
scrapeInfiniteScrollItems
函數:
let scrollBox1 = await page.$eval('.isgrP', el => el.querySelector('body > div:nth-child(15) > div > div > div.isgrP > ul > div'));
let scrollBox2 = await page.$eval('body > div:nth-child(15) > div > div > div.isgrP > ul > div', el => el);
您指出,這兩行都返回undefined。 這是因為您沒有正確使用$eval
方法。 $eval
方法允許您執行的操作是執行querySelector
指令來定位特定的DOM元素(該元素與您聲明的CSS選擇器匹配),然后內部函數在該DOM元素上實時執行JavaScript指令。
因此,讓我們看一下第一行:您要它對isgrP
類的元素執行querySelector
,然后在該元素上運行進一步的querySelector
,該元素使用以body
開頭的CSS選擇器? 這沒有道理。
我還從那個奇怪的選擇器中看到,它以div.isgrP > ul > div
結尾,巧合的是,該div
的類名與您最初使用$eval
方法查詢的那個類名相同。 那么,您是否一直打算在div.isgrP > ul > div
上找到該元素?
您可以通過按如下所示重新編寫代碼來直接使用puppeteer
訪問DOM元素:
const scrollBox = await page.$eval('div.isgrP > ul > div.PZuss', (uiElement) => {
return uiElement;
});
這將為您一直在搜索的可滾動框返回DOM元素(不是ElementHandle
實例)。
請告訴我是否有幫助,是什么導致您的下一個問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.