javascript - 如何选择一个 DOM 元素在 Puppeteer 中滚动

标签 javascript scroll async-await instagram puppeteer

我对 Puppeteer 和 await/async 语法还很陌生。我正在尝试构建一个机器人来尝试从 Instagram 获取数据。具体来说,我想获得给定个人资料的关注者。一切正常,直到弹出关注者窗口。我想选择 DOM 元素在其上滚动并在每次迭代时将关注者推送到数组中。我在论坛中搜索并尝试了不同的方法,但它总是返回未定义的。我能够获得 ElementHandle (scrollBox3) 并获得 scrollHeight 之类的属性,但不能获得实际的 DOM 元素。 下面的代码对文件的不同部分进行了描述。

任何帮助将不胜感激:)

下一部分选择 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 中的最后一个元素,这会触发滚动到 View 中。这样我就可以获得定义为参数的关注者数量。这样很方便,功能也更短。但是仍然无法选择 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;
}

关于javascript - 如何选择一个 DOM 元素在 Puppeteer 中滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53299883/

相关文章:

javascript - 设置一个等于当前选定链接的数据属性的变量

javascript - 如何,可以说,在每次 Protractor 规范测试后重新启动或关闭浏览器

swift - 在 WKWebView 上禁用双击滚动

Android GestureDetector 无法使用 FrameLayout 检测到 onScroll 事件

c# - 如何使用默认覆盖处理异步和等待

javascript - 如何使用 pickadate.js 创建时间段?

javascript - 根据 mimetype 按类型对文件进行排序的最佳方法

python - PyGTK 2 : TreeView is extending out of my window even with scroll bar enabled

c# - 异步 TCP 服务器持有套接字但停止监听

javascript - 了解 testcafe 装置中的执行顺序