使用JavaScript和Node.js进行Web爬取的指南
2021-01-12 18:12:57
37次阅读
0个评论

随着Internet上数据量的大量增加,该技术在从网站检索信息并将其应用于各种使用案例中变得越来越有益。通常,Web数据提取涉及到对给定网页的请求,访问其HTML代码以及解析该代码以获取一些信息。由于JavaScript在处理Web浏览器中的DOM(文档对象模型)方面表现出色,因此在Node.js中创建数据提取脚本可能非常通用。因此,本教程重点介绍JavaScript网络抓取。

在本文中,我们将说明如何使用JavaScript和Node.js执行Web抓取。

我们将首先演示如何使用Axios和Cheerio软件包从简单的网站提取数据。

然后,我们将展示如何使用无头浏览器Puppeteer从动态网站检索数据,该网站通过JavaScript加载内容。

你需要什么
网页浏览器
一个从中提取数据的网页
代码编辑器,例如Visual Studio Code
Node.js
入门
安装Node.js
Node.js是一种流行的JavaScript运行时环境,它具有许多功能,可以自动执行从网站收集数据的艰巨任务。

要将其安装在系统上,请按照其网站上的下载说明进行操作。npm(节点软件包管理器)也将与Node.js一起自动安装。

npm是Node.js的默认软件包管理工具。由于我们将使用软件包来简化Web抓取,因此npm将使使用它们的过程变得快捷而轻松。

安装Node.js之后,转到项目的根目录并运行以下命令来创建package.json文件,该文件将包含与项目相关的所有详细信息:

npm init
安装Axios
Axios是一个强大的基于诺言的HTTP客户端,可以部署在Node.js和Web浏览器中。使用此npm软件包,您可以使用Promise从Node.js发出HTTP请求,并轻松快捷地从Internet下载数据。

此外,Axios会自动将数据转换为JSON格式,拦截请求和响应,并可以处理多个并发请求。

要安装它,请在终端中导航到项目的目录文件夹,然后运行以下命令:
npm install axios
默认情况下,NPM会将Axios安装在名为node_modules的文件夹中,该文件夹将在项目目录中自动创建。
安装Cheerio
Cheerio是一个高效且精益的模块,它提供了类似jQuery的语法来处理网页内容。它极大地简化了在网页上选择,编辑和查看DOM元素的过程。
尽管Cheerio允许您轻松解析和操作DOM,但其工作方式与Web浏览器不同。这意味着它不会接受请求,执行JavaScript,加载外部资源或应用CSS样式。

要安装它,请在终端中导航到项目的目录文件夹,然后运行以下命令:

npm install cheerio 
默认情况下,就像Axios一样,npm会将Cheerio安装在名为node_modules的文件夹中,该文件夹将在项目目录中自动创建。

安装木偶
Puppeteer是一个Node库,可让您以编程方式控制无头Chrome浏览器,并平稳,快速地提取数据。
由于某些网站依赖JavaScript加载其内容,因此使用基于HTTP的工具(如Axios)可能无法获得预期的结果。使用Puppeteer,您可以模拟浏览器环境,像浏览器一样执行JavaScript,并从网站中抓取动态内容。
要安装它,就像其他软件包一样,在终端中导航到项目的目录文件夹,然后运行以下命令:

npm install puppeteer
抓取一个简单的网站
现在,让我们看看如何使用Axios和Cheerio从一个简单的网站提取数据。
对于本教程,我们的目标将是此网页。我们将寻求提取页面顶部列出的评论数。

要查找保存我们要查找的数据的特定HTML元素,请使用Web浏览器上的检查器工具:

如上图所示,评论数据的数量包含在 <a> 标签,它是 <span> 标记为 comment-bubble。在使用Cheerio在页面上选择这些元素时,我们将使用此信息。

以下是创建抓取逻辑的步骤:

1.让我们开始创建一个名为index.js的文件,该文件将包含用于从网页检索数据的编程逻辑。

2.然后,我们使用Node.js内置的`require`函数来包含我们将在项目中使用的模块。
const axios = require('axios');
const cheerio = require('cheerio');

3.让我们使用Axios向目标网页发出GET HTTP请求。

这是代码:
axios.get('https://www.forextradingbig.com/instaforex- 
    broker-review/')
       .then(response => {
          const html = response.data;      
       })

请注意,将请求发送到网页时,它将返回响应。此Axios响应对象由各种组件组成,包括引用从服务器返回的有效负载的数据。

因此,当发出GET请求时,我们从响应中输出HTML格式的数据。
4.接下来,让我们将响应数据加载到Cheerio实例中。这样,我们可以创建一个Cheerio对象,以帮助我们解析目标网页中的HTML并查找所需数据的DOM元素,就像使用jQuery一样。
为了维护臭名昭著的jQuery约定,我们将命名为Cheerio对象 $。
const $ = cheerio.load(html);
5.让我们使用Cheerio的选择器语法来搜索包含所需数据的元素:

1个

const scrapedata = $('a', '.comment-bubble').text()
console.log(scrapedata);
注意,我们还使用了“ text()”方法以文本格式输出数据。

6.最后,让我们记录在抓取过程中遇到的所有错误。
.catch( error => {
    console.log(error);
}); 
//以下是抓取逻辑的完整代码:
const axios = require("axios");
const cheerio = require("cheerio");
//performing a GET request
axios
  .get("https://www.forextradingbig.com/instaforex-broker-review/")
  .then((response) => {
    //handling the success
    const html = response.data;

    //loading response data into a Cheerio instance
    const $ = cheerio.load(html);

    //selecting the elements with the data
    const scrapedata = $("a", ".comment-bubble").text();

    //outputting the scraped data
    console.log(scrapedata);
  })
  //handling error
  .catch((error) => {
    console.log(error);
  });

如果我们使用`node index.js`命令运行上面的代码,它将返回我们要从目标网页上抓取的信息。

这是结果的屏幕截图:
有效!
搜寻动态网站
现在,让我们看看如何使用Puppeteer从动态网站提取数据。
在此示例中,我们将使用ES2017异步 async/await syntax 与诺言舒适地合作。

的 async表达表示将兑现承诺。和await表达式使JavaScript等待执行承诺的其余部分,然后再执行其余代码。此语法将确保我们在成功加载网页后提取网页内容。
我们的目标将是此Reddit页面,该页面使用JavaScript呈现内容。我们将寻求提取页面上的标题和描述
要查找保存我们要查找的数据的特定HTML元素,请使用Web浏览器上的检查器工具:
1个
如上图所示,除其他内容外,每个帖子都包含在Post类中。通过仔细检查,我们发现每个帖子标题都有一个h3标签,每个描述都有ap标签。在页面上选择这些元素时,我们将使用此信息。
以下是创建抓取逻辑的步骤:
1.让我们从创建一个名为index.js的文件开始,该文件将包含用于从网页检索数据的编程逻辑。
2.然后,让我们使用Node.js内置的`require`函数将Puppeteer导入我们的项目。
const puppeteer = require ('puppeteer');
3.让我们启动Puppeteer。实际上,我们正在启动Chrome浏览器的实例,以用于访问目标网页。
puppeteer.launch()
4.让我们在无头浏览器中创建一个新页面。由于我们已经使用了await 表达式,我们将等待新页面打开,然后再将其保存到 page 变量。
创建页面后,我们将使用它来导航到Reddit页面。再次,因为我们已经使用await,我们的代码执行将暂停,直到页面加载或引发错误为止。
我们还将等待页面的body标签加载,然后再执行其余的执行。

这是代码:

.then (async browser => { 
const page = await browser.newPage ();
await page.goto ('https://www.reddit.com/r/scraping/');
await page.waitForSelector ('body');
5.调出Puppeteer中的Reddit页面后,我们可以使用它的 evaluate() 与页面互动的功能。
使用该函数,我们可以在Chrome中执行任意JavaScript,并使用其内置函数(如“ querySelector()”)来操纵页面并检索其内容。

这是代码:
let grabPosts = await page.evaluate (() => {
      let allPosts = document.body.querySelectorAll ('.Post');
           scrapeItems = [];
      allPosts.forEach (item => {
        let postTitle = item.querySelector ('h3').innerText;

        let postDescription = '';
        try {
          postDescription = item.querySelector ('p').innerText;
        } catch (err) {}
        scrapeItems.push ({
          postTitle: postTitle,

          postDescription: postDescription,
        });
      });

      let items = {
        "redditPosts": scrapeItems,
      };
      return items;
    });

console.log (grabPosts);

6.关闭浏览器。

await browser.close ();
7.最后,让我们记录在抓取过程中遇到的所有错误。
.catch (function (err) {
    console.error (err);
});
//以下是抓取逻辑的完整代码:

const puppeteer = require ('puppeteer');

//initiating Puppeteer
puppeteer
  .launch ()
  .then (async browser => {
  
    //opening a new page and navigating to Reddit
    const page = await browser.newPage ();
    await page.goto ('https://www.reddit.com/r/scraping/');
    await page.waitForSelector ('body');
  
    //manipulating the page's content
    let grabPosts = await page.evaluate (() => {
    let allPosts = document.body.querySelectorAll ('.Post');
      
    //storing the post items in an array then selecting for retrieving content
    scrapeItems = [];
    allPosts.forEach (item => {
      let postTitle = item.querySelector ('h3').innerText;
      let postDescription = '';
        try {
          postDescription = item.querySelector ('p').innerText;
        } catch (err) {}
        scrapeItems.push ({
          postTitle: postTitle,
          postDescription: postDescription,
        });
      });
      let items = {
        "redditPosts": scrapeItems,
      };
      return items;
    });
    //outputting the scraped data
    console.log (grabPosts);
    //closing the browser
    await browser.close ();
  })
  //handling any errors
  .catch (function (err) {
    console.error (err);
  });

如果我们使用`node index.js`命令运行上面的代码,它将返回我们要从目标网页上抓取的信息。

这是结果的屏幕截图(为简便起见,结果已被截断):

有效!

如果您打算在生产环境中使用以上内容,并提出数千次抓取数据的请求,则肯定会被禁止。在这种情况下,每隔几个请求就轮换IP地址可以帮助您避免受到干扰,并成功提取内容。

因此,连接到代理服务可以帮助您充分利用抓取工作。重要的是,借助住宅代理,您可以轻松应对抓取瓶颈并轻松快速地收集在线数据。

在Puppeteer中,您可以在启动代理时通过传递一行额外的参数来轻松连接到代理:

puppeteer.launch({
    args: [ '--proxy-server=145.0.10.11:7866' ]
});
结论
这样便可以使用JavaScript和Node.js执行Web抓取。借助这些技能,您可以从网页中收集有用的信息并将其集成到您的用例中。

请记住,如果您想构建高级的东西,可以随时查看Axios,Cheerio和Puppeteer文档,以帮助您快速入门。

收藏 0 0

登录 后评论。没有帐号? 注册 一个。

moutker

  • 0 回答
  • 0 粉丝
  • 0 关注