Playwright脚本因懒加载无法抓取全部红米手机产品问题求助
解决Playwright爬取懒加载页面数据不全的问题
问题说明
使用Playwright爬取https://mistore.pk/collections/redmi-phones时,仅能获取20个红米手机产品名称,剩余11个因页面懒加载未触发加载,导致数据抓取不全。原脚本代码如下:
import { test, expect } from '@playwright/test'; test('Extract Mobile Product Names', async ({ page }) => { // Navigate to the target website await page.goto('https://mistore.pk/collections/redmi-phones'); // Wait for the '.product-title' selector to be visible for all products await page.waitForSelector('.product-title'); // Locate all anchor elements with the class 'product-title' const productTitleElements = await page.$$('.product-title'); // Initialize a counter let productCount = 0; // Extract and print the text content of each product title element for (const element of productTitleElements) { const productName = await element.textContent(); console.log(productName.trim()); // Trim to remove leading/trailing spaces productCount++; // Increment the counter } // Print the total number of products console.log(`Total products: ${productCount}`); });
解决思路
页面采用滚动触发懒加载的机制,需通过循环滚动页面到底部,触发新内容加载,直到产品数量不再增长,确保所有产品都被加载完成。
修改后的完整代码
import { test, expect } from '@playwright/test'; test('Extract All Mobile Product Names', async ({ page }) => { await page.goto('https://mistore.pk/collections/redmi-phones'); let previousProductCount = 0; let currentProductCount = 0; do { // 获取当前已加载的产品数量 currentProductCount = await page.locator('.product-title').count(); // 数量无变化则停止循环,说明所有产品已加载 if (currentProductCount === previousProductCount) break; previousProductCount = currentProductCount; // 滚动到页面底部,触发懒加载 await page.evaluate(() => { window.scrollTo(0, document.body.scrollHeight); }); // 等待新元素加载,可根据页面实际加载速度调整时长 await page.waitForTimeout(2000); } while (true); // 提取所有产品名称 const allProductNames = await page.locator('.product-title').allTextContents(); // 打印产品名称并统计总数 let total = 0; for (const name of allProductNames) { console.log(name.trim()); total++; } console.log(`Total products: ${total}`); });
可选优化方案
- 替换固定等待时长为动态等待,避免不必要的等待或加载不充分:
// 替换原waitForTimeout代码 await page.waitForFunction( (prevCount) => document.querySelectorAll('.product-title').length > prevCount, previousProductCount ); - 若页面存在“加载更多”按钮,可通过点击按钮替代滚动,稳定性更高:
// 替换滚动循环逻辑 while (await page.locator('text="Load more"').isVisible()) { await page.locator('text="Load more"').click(); await page.waitForTimeout(1500); }
内容的提问来源于stack exchange,提问作者scypx
相关产品推荐
相关产品推荐

