搜索
首页web前端js教程如何从无限滚动的页面中抓取数据

您是否遇到过需要“单击按钮”等操作才能显示更多内容的网页?此类页面称为“动态网页”,因为它们根据用户交互加载更多内容。相比之下,静态网页会立即显示所有内容,无需用户操作。

从动态页面中抓取内容可能会令人畏惧,因为它需要模拟用户交互,例如单击按钮来访问其他隐藏内容。在本教程中,您将学习如何通过“加载更多”按钮从无限滚动的网页中抓取数据。

先决条件

要学习本教程,您需要:

  • Node.js:安装标记为“LTS”(长期支持)的版本,该版本比最新版本更稳定。
  • Npm:这是一个用于安装包的包管理器。好消息是“npm”会自动随 Node.js 安装,这使得速度更快。
  • Cheerio:用于解析 HTML
  • Puppeteer:您将使用它来控制无头浏览器。
  • 用于构建 Scraper 的 IDE:您可以获得任何代码编辑器,例如 Visual Studio Code。

此外,您需要对 HTML、CSS 和 JavaScript 有基本的了解。您还需要一个网络浏览器,例如 Chrome。

初始化项目

创建一个新文件夹,然后在代码编辑器中打开它。在代码编辑器中找到“终端”选项卡并打开一个新终端。以下是使用 Visual Studio Code 发现它的方法。

How to Scrape Data from a Page with Infinite Scroll

接下来,在终端中运行以下命令来安装此构建所需的软件包。

$ npm install cheerio puppeteer

在代码编辑器中的项目文件夹中创建一个新文件,并将其命名为dynamicScraper.js。

干得好,伙计!

访问页面内容

Puppeteer 是一个功能强大的 Node.js 库,可让您控制无头 Chrome 浏览器,使其成为与网页交互的理想选择。借助 Puppeteer,您可以使用 URL 定位网页、访问内容并轻松从该页面提取数据。

在本节中,您将学习如何使用无头浏览器打开页面、访问内容以及检索该页面的 HTML 内容。您可以在这里找到本教程的目标网站。

注意:您要将所有代码编写在dynamicScraper.js 中。

首先使用 Node.js 内置函数 require() 导入 Puppeteer,它可以帮助您加载模块:核心模块、第三方库(如 Puppeteer)或自定义模块(如本地 JS 文件)。

$ npm install cheerio puppeteer

接下来,定义一个变量来存储您的目标 URL。这样做不是强制性的,但它使您的代码更清晰,因为您只需从代码中的任何位置引用此全局变量即可。

const puppeteer = require('puppeteer');

下一步是创建启动无头浏览器并检索目标页面的 HTML 内容的函数。您应该选择立即调用函数表达式 (IIFE) 方法以使事情变得更快。

使用 try-and-catch 块定义异步 IIFE:

const url = 'https://www.scrapingcourse.com/button-click';

注意:您应该在 try 块内编写本教程片段的所有其他代码。

在 IIFE 内部,创建一个新的 Puppeteer 实例并打开一个新页面进行交互。

使用 launch 方法启动 puppeteer 库的新实例,并将无头模式传递给它。无头模式可以设置为 true 或 false。将无头模式设置为 true 会使无头浏览器在 puppeteer 启动时不可见,但将其设置为 false 会使浏览器可见。

启动 Puppeteer 后,您还需要调用 newPage 方法,该方法会触发在无头浏览器中打开新选项卡。

(async () => {
    try {
        // Code goes here
    } catch (error) {
        console.error('Error:', error.message);
    }
})();

现在,查询 newPage 方法以定位预期的 URL,并使用 page.goto 方法在此新选项卡中打开该网站。除此之外,您要确保 Puppeteer 仅当且仅当页面加载了所有必需资源(如图像和 JS)时才认为页面已准备好进行交互和数据提取。

为了确保页面准备就绪,Puppeteer 提供了一个名为 waitUntil 的选项,它可以接受定义加载页面的不同条件的各种值:

  • load:等待加载事件触发,该事件在 HTML 文档及其资源(例如图像、CSS、JS)加载后发生。但是,这可能无法解释加载事件后加载的其他 JavaScript 渲染内容。

  • domcontentloaded:等待 DOMContentLoaded 事件,该事件在解析初始 HTML 后触发。但这会在外部资源(如图像或其他 JS)加载之前加载。

  • networkidle2:等待 500 毫秒,直到没有超过两个活动网络请求(正在进行的 HTTP 请求(例如,加载图像、脚本或其他资源))。当处理发出小型连续请求但不影响主要内容的页面时,首选此值。

// Launch Puppeteer
const browser = await puppeteer.launch({ headless: false }); // Headless mode
const page = await browser.newPage(); // Open a new page

最后,您只需要使用 page.content() 检索当前页面的所有 HTML 内容即可。最重要的是,您应该关闭浏览器实例,以避免不必要的内存使用,这会降低系统速度。在脚本末尾使用 browser.close() 来关闭浏览器。

$ npm install cheerio puppeteer

使用您现在的代码,浏览器加载和关闭的速度会非常快,您甚至可能无法很好地查看页面。在这种情况下,您可以使用 page.waitForTimeout 方法将浏览器延迟几秒钟。该方法应该出现在 browser.close 方法之前。

const puppeteer = require('puppeteer');

这是本节的完整代码:

const url = 'https://www.scrapingcourse.com/button-click';

保存文件并使用以下命令在终端内运行脚本:

(async () => {
    try {
        // Code goes here
    } catch (error) {
        console.error('Error:', error.message);
    }
})();

该脚本将打开一个无头浏览器,如下所示:

How to Scrape Data from a Page with Infinite Scroll

浏览器加载,Puppeteer 获取其整个 HTML 内容,Console 将内容记录到终端。

这是您应该在终端中获得的输出:

// Launch Puppeteer
const browser = await puppeteer.launch({ headless: false }); // Headless mode
const page = await browser.newPage(); // Open a new page

接下来,您想要循环模拟点击。模拟将使用运行 i 次的 for 循环,其中 i 将是 clicks 变量。

// Navigate to the target URL
await page.goto(url, {
    waitUntil: 'networkidle2', // Ensure the page is fully loaded
});

注意:本节的其余代码应编写在 for 循环的 try 块内。

为了帮助调试和跟踪输出,请注销当前的点击尝试。

// Get the full HTML content of the page
const html = await page.content();

// Log the entire HTML content
console.log(html);

// Close the browser
await browser.close();

接下来,您希望能够找到“加载更多”按钮并单击至少三次。但在模拟点击之前,您应该确保“加载更多”按钮可用。

Puppeteer 提供了 waitForSelector() 方法来在使用元素之前检查它的可见性。

对于“加载更多”按钮,您必须首先使用其 id 选择器的值找到它,然后检查可见性状态,如下所示:

// Delay for 10 seconds to allow you to see the browser
await page.waitForTimeout(10000);

现在您知道“加载更多”按钮可用,您可以使用 Puppeteer click() 方法单击它。

const puppeteer = require('puppeteer');

const url = 'https://www.scrapingcourse.com/button-click';

(async () => {
    try {
        // Launch Puppeteer
        const browser = await puppeteer.launch({ headless: false }); // Headless mode
        const page = await browser.newPage(); // Open a new page

        // Navigate to the target URL
        await page.goto(url, {
            waitUntil: 'networkidle2', // Ensure the page is fully loaded
        });

        // Get the entire HTML content of the page
        const html = await page.content();

        // Log the entire HTML content
        console.log(html);

        // Delay for 10 seconds to allow you to see the browser
        await page.waitForTimeout(10000);

        // Close the browser
        await browser.close();
    } catch (error) {
        console.error('Error fetching the page:', error.message);
    }
})();

一旦模拟单击“加载更多”按钮,您应该等待内容加载后再模拟另一次单击,因为数据可能取决于服务器请求。您必须使用 setTimeout() 在请求之间引入延迟。

下面的代码通知脚本等待至少两秒钟,然后再模拟再次单击“加载更多”按钮。

$ node dynamicScraper.js

为了总结本节的内容,您希望在每次单击后使用 content() 方法获取当前的 HTML 内容,然后将输出注销到终端。



    <title>Load More Button Challenge - ScrapingCourse.com</title>


    <header>
        <!-- Navigation Bar -->
        <nav>
            <a href="/">
                <img src="/static/imghwm/default1.png" data-src="logo.svg" class="lazy" alt="如何从无限滚动的页面中抓取数据">
                <span>Scraping Course</span>
            </a>
        </nav>
    </header>

    <main>
        <!-- Product Grid -->
        <div>



<p>Note that the code structure above is what your output should look like.</p>

<p>Wow! You should be proud of yourself for getting this far. You’ve just completed your first attempt at scraping the contents of a webpage. </p>

<h2>
  
  
  Simulate the LOad More Products Process
</h2>

<p>Here, you want to access more products, and to do that, you need to click on the “Load more” button multiple times until you’ve either exhausted the list of all products or gotten the desired number of products you want to access. </p>

<p>To access this button and click on it, you must first locate the element using any CSS selectors (the class, id, attribute of the element, or tag name). </p>

<p>This tutorial aims to get at least 48 products from the target website, and to do that, you’ll have to click on the “Load more” button at least three times.</p>

<p>Start by locating the “Load more” button using any of the CSS selectors on it. Go to the target website, find the “Load more” button, right-click, and select the inspect option. </p>

<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173587927350910.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="How to Scrape Data from a Page with Infinite Scroll"></p>

<p>Selecting the inspect option will open up developer tools just like the page below:</p>

<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173587927639663.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="How to Scrape Data from a Page with Infinite Scroll"></p>

<p>The screenshot above shows that the “Load more” button element has an id attribute with the value "load-more-btn". You can use this id selector to locate the button during the simulation and click on it multiple times.</p>

<p>Back to the code, still inside the try block, after the line of code that logs out the previous HTML content for the default 12 products on the page.</p>

<p>Define the number of times you want to click the button. Recall that each click loads an additional 12 products. For 48 products, three clicks are required to load the remaining 36.<br>
</p>

<pre class="brush:php;toolbar:false">// Number of times to click "Load More"
const clicks = 3;

到目前为止您的完整代码:

for (let i = 0; i 



<p>以下是模拟按钮点击三次获得 48 个产品的输出:<br>
</p>

<pre class="brush:php;toolbar:false">console.log(`Clicking the 'Load More' button - Attempt ${i + 1}`);

现在,您应该只关心与所有 48 个产品的输出进行交互。为此,您需要清理上一节中的先前代码。

您还需要在 for 循环块之后降低 html 变量,这样您就只能获得所有 48 种产品的一个输出。

您的清理代码应与此代码片段相同:

$ npm install cheerio puppeteer

现在,让我们使用 Cheerio 进行 HTML 解析。

首先,Cheerio 需要访问它想要解析的 HTML 内容,为此,它提供了一个 load() 方法来接收该 HTML 内容,使其可以使用类似 jQuery 的语法进行访问。

使用 HTML 内容创建 Cheerio 库的实例:

const puppeteer = require('puppeteer');

您现在可以使用 $ 来查询和操作加载的 HTML 中的元素。

接下来,初始化一个数组来存储产品信息。该数组将保存提取的数据,每个产品将存储为一个对象,包含其名称、价格、图像和链接。

const url = 'https://www.scrapingcourse.com/button-click';

回想一下,每个产品都有一个类 .product-item。您将使用它与 Cheerio ($) 的变量实例来获取每个产品,然后执行一些操作。

.each() 方法用于使用 .product-item 类选择器迭代每个匹配的元素。

(async () => {
    try {
        // Code goes here
    } catch (error) {
        console.error('Error:', error.message);
    }
})();

让我们使用特定详细信息的类选择器从每个产品中检索产品详细信息。例如,要获取产品名称,您需要使用类选择器 .product-item 查找每个产品中的子元素。检索该子元素的文本内容并修剪它以防出现任何空格。

// Launch Puppeteer
const browser = await puppeteer.launch({ headless: false }); // Headless mode
const page = await browser.newPage(); // Open a new page
  • $(element).find('.product-name'):在当前 .product-item 中搜索类为 .product-name 的子元素。
  • .text():检索元素内的文本内容。
  • .trim():删除文本中不必要的空格。

利用这个概念,让我们使用它们的类属性来获取价格、图像 URL 和链接。

// Navigate to the target URL
await page.goto(url, {
    waitUntil: 'networkidle2', // Ensure the page is fully loaded
});

现在您已经获得了所有预期的信息,下一步是将每个解析的产品信息作为单独的对象推送到产品数组中。

// Get the full HTML content of the page
const html = await page.content();

// Log the entire HTML content
console.log(html);

// Close the browser
await browser.close();

最后,注销产品数组以在终端中获得预期的输出。

// Delay for 10 seconds to allow you to see the browser
await page.waitForTimeout(10000);

您的整个代码应类似于以下代码片段:

const puppeteer = require('puppeteer');

const url = 'https://www.scrapingcourse.com/button-click';

(async () => {
    try {
        // Launch Puppeteer
        const browser = await puppeteer.launch({ headless: false }); // Headless mode
        const page = await browser.newPage(); // Open a new page

        // Navigate to the target URL
        await page.goto(url, {
            waitUntil: 'networkidle2', // Ensure the page is fully loaded
        });

        // Get the entire HTML content of the page
        const html = await page.content();

        // Log the entire HTML content
        console.log(html);

        // Delay for 10 seconds to allow you to see the browser
        await page.waitForTimeout(10000);

        // Close the browser
        await browser.close();
    } catch (error) {
        console.error('Error fetching the page:', error.message);
    }
})();

以下是保存并运行脚本时的输出:

$ node dynamicScraper.js

将产品信息导出至 CSV

下一步是将解析后的产品信息(目前采用 JavaScript 对象表示法 (Json) 格式)导出为逗号分隔值 (CSV) 格式。我们将使用 json2csv 库将解析的数据转换为其相应的 CSV 格式。

首先导入所需的模块。

Node.js 提供了用于文件处理的文件系统(fs)模块,例如将数据写入文件。导入 fs 模块后,您应该解构 json2csv 库中的 parse() 方法。

$ npm install cheerio puppeteer

CSV 文件通常需要列标题;按照与解析信息相同的顺序仔细写下此内容。这里,解析的数据是产品数组,其中每个元素都是一个具有四个键(名称、价格、图像和链接)的对象。您应该使用这些对象键来命名列标题以进行正确的映射。

定义 CSV 文件的字段(列标题):

const puppeteer = require('puppeteer');

现在您已经定义了字段,下面的操作是将当前解析的信息转换为 CSV 格式。 parse() 方法的工作格式如下: parse(WHAT_YOU_WANT_TO_CONVERT, { YOUR_COLUMN_HEADERS }).

const url = 'https://www.scrapingcourse.com/button-click';

您现在必须将此 CSV 信息保存到文件扩展名为 .csv 的新文件中。使用 Node.js 时,您可以使用 fs 模块上的 writeFileSync() 方法来处理文件创建。该方法有两个参数:文件名和数据。

(async () => {
    try {
        // Code goes here
    } catch (error) {
        console.error('Error:', error.message);
    }
})();

本节的完整代码应如下所示:

// Launch Puppeteer
const browser = await puppeteer.launch({ headless: false }); // Headless mode
const page = await browser.newPage(); // Open a new page

保存并运行脚本后,您应该会看到名为 products.csv 的文件自动添加到您的文件结构中。

输出 - products.csv:
How to Scrape Data from a Page with Infinite Scroll

结论

本教程深入研究了从需要模拟才能访问其隐藏内容的页面中抓取数据的复杂性。您学习了如何使用 Node.js 和一些附加库在动态页面上执行网页抓取,将抓取的数据解析为更有条理的格式,并将其解压到 CSV 文件中。

以上是如何从无限滚动的页面中抓取数据的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
相关文章
在JavaScript中替换字符串字符在JavaScript中替换字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

自定义Google搜索API设置教程自定义Google搜索API设置教程Mar 04, 2025 am 01:06 AM

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

示例颜色json文件示例颜色json文件Mar 03, 2025 am 12:35 AM

本文系列在2017年中期进行了最新信息和新示例。 在此JSON示例中,我们将研究如何使用JSON格式将简单值存储在文件中。 使用键值对符号,我们可以存储任何类型的

构建您自己的Ajax Web应用程序构建您自己的Ajax Web应用程序Mar 09, 2025 am 12:11 AM

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

10个jQuery语法荧光笔10个jQuery语法荧光笔Mar 02, 2025 am 12:32 AM

增强您的代码演示:开发人员的10个语法荧光笔 在您的网站或博客上共享代码片段是开发人员的常见实践。 选择合适的语法荧光笔可以显着提高可读性和视觉吸引力。 t

8令人惊叹的jQuery页面布局插件8令人惊叹的jQuery页面布局插件Mar 06, 2025 am 12:48 AM

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

10 JavaScript和JQuery MVC教程10 JavaScript和JQuery MVC教程Mar 02, 2025 am 01:16 AM

本文介绍了关于JavaScript和JQuery模型视图控制器(MVC)框架的10多个教程的精选选择,非常适合在新的一年中提高您的网络开发技能。 这些教程涵盖了来自Foundatio的一系列主题

什么是这个&#x27;在JavaScript?什么是这个&#x27;在JavaScript?Mar 04, 2025 am 01:15 AM

核心要点 JavaScript 中的 this 通常指代“拥有”该方法的对象,但具体取决于函数的调用方式。 没有当前对象时,this 指代全局对象。在 Web 浏览器中,它由 window 表示。 调用函数时,this 保持全局对象;但调用对象构造函数或其任何方法时,this 指代对象的实例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。这些方法使用给定的 this 值和参数调用函数。 JavaScript 是一门优秀的编程语言。几年前,这句话可

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。