【问题标题】:Node JS Puppteer Infinite scroll loopNode JS Puppeteer 无限滚动循环
【发布时间】:2019-03-10 16:04:15
【问题描述】:

我正在学习 Puppeteer 并试图抓取一个实现了无限滚动的网站。通过延迟 1 秒后向下滚动,我可以从列表中获取所有价格。 Here is the URL

我想要做的是,从列表中打开一个项目,获取产品名称,返回列表,选择第二个产品并对所有产品执行此操作。

const fs = require('fs');
const puppeteer = require('puppeteer');
function extractItems() {
  const extractedElements = document.querySelectorAll('.price');
  const items = [];
  for (let element of extractedElements) {
    items.push(element.innerText);
  }
  return items;
}
async function scrapeInfiniteScrollItems(
  page,
  extractItems,
  itemTargetCount,
  scrollDelay = 1000,
) {
  let items = [];
  try {
    let previousHeight;
    while (items.length < itemTargetCount) {
      items = await page.evaluate(extractItems);
      previousHeight = await page.evaluate('document.body.scrollHeight');
      await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
      await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`);
      await page.waitFor(scrollDelay);
    }
  } catch(e) { }
  return items;
}
(async () => {
  // Set up browser and page.
  const browser = await puppeteer.launch({
    headless: false,
    args: ['--no-sandbox', '--disable-setuid-sandbox'],
  });
  const page = await browser.newPage();
  page.setViewport({ width: 1280, height: 926 });
  // Navigate to the demo page.
  await page.goto('https://www.clubfactory.com/views/product.html?categoryId=53&subId=53&filter=%7B%22Price%22%3A%5B%7B%22beg%22%3A1.32%2C%22end%22%3A0%7D%5D%7D');
  // Scroll and extract items from the page.
  const items = await scrapeInfiniteScrollItems(page, extractItems, 4000);
  // Save extracted items to a file.
  fs.writeFileSync('./prices3.txt', items.join('\n') + '\n');
  // Close the browser.
  await browser.close();
})(); 

感谢任何帮助

【问题讨论】:

    标签: node.js web-scraping puppeteer google-chrome-headless


    【解决方案1】:

    编辑:我为问题中列出的特定网站添加了一个有效的 sn-p。

    如果您喜欢抓取,有时您必须将用户体验分解为小块,以模仿真实用户来获取用户将获得的实际数据。

    处理无限滚动的一种简单方法是删除所有当前元素,然后每次滚动直到有另外 10 或 100 个新元素,或者甚至尝试一次刮掉所有元素。

    不过你也可以换个思路,

    1. 获取第一个元素,
    2. 点击在新标签页中打开,
    3. 解析数据,
    4. 关闭标签,
    5. 删除元素,
    6. 并移至下一个元素。滚动并等待新元素出现。

    这个概念的问题是,你永远不会知道滚动和点击是如何被触发的。可以有多个事件绑定到滚动以在不同的站点中处理它。而且,提供的站点在 vueJS 中。

    代码片段

    每个产品的选择器是#__layout &gt; section &gt; main &gt; section &gt; section &gt; div.products &gt; div &gt; div。

    我们将滚动选择器,处理它,然后删除它。之后我们会触发一个滚动事件,让浏览器知道发生了什么变化。

    window.scrollTo(0, 0);
    const selector = `#__layout > section > main > section > section > div.products > div > div`;
    const element = document.querySelector(selector)
    element.scrollIntoView()
    element.remove()
    

    结果:(gif动画)

    很酷的是,我们不需要滚动到页面底部来触发更改。看看滚动条在移除过程中是如何变化的。

    这也适用于 producthunt 等网站。 Video Link 以获得更好的视图质量。

    const delay = d=>new Promise(r=>setTimeout(r,d))
    
    const scrollAndRemove = async () => {
        // scroll to top to trigger the scroll events
        window.scrollTo(0, 0);
        const selector = `.title_9ddaf`;
        const element = document.querySelector(selector);
    
        // stop if there are no elements left
        if(element){
          element.scrollIntoView();
    
          // do my action
          // wait for a moment to reduce load or lazy loading image
          await delay(1000);
          console.log(element.innerText);
          // end of my action
    
          // remove the element to trigger some scroll event somewhere
          element.remove();
    
          // return another promise
          return scrollAndRemove()
        }
    }
    
    scrollAndRemove();
    

    【讨论】:

      猜你喜欢
      • 2016-04-05
      • 2014-04-26
      • 2017-01-17
      • 1970-01-01
      • 2021-09-06
      • 2014-12-04
      • 1970-01-01
      • 2018-07-03
      • 1970-01-01
      相关资源
      最近更新 更多