如何使用Puppeteer.js爬取网站
Web scraping是自动从网页中收集数据的最佳方法之一。通常我们称网页爬虫为“爬虫”,他们简单地浏览网页,然后为我们提供所选页面的爬取数据。有很多原因可以自动化数据爬取过程,因为它比手动从不同的网页中提取数据更容易。当我们想从中提取数据的网页没有提供任何API时,爬取也是一个很好的解决方案。
在本教程中,我们将看到如何使用Puppeteer.js在Node.js中创建一个网页爬虫。
构建这个爬虫有不同的阶段:
- 在第一步中,我们将编写该应用程序以能够打开Chromium并加载一个我们将进行爬取的特定网站链接。
-
在接下来的步骤中,我们将学习如何爬取单个页面上存在的所有书籍的详细信息。
-
最后,我们将学习如何爬取存在于多个页面上的所有书籍的详细信息。
先决条件
为了能够构建这个node应用程序,有两个先决条件:
- Node.js - 在本地计算机上安装最新稳定版本的Node.js。
-
代码编辑器/ IDE - 选择一个体验良好的代码编辑器或IDE。
现在我们已经完成了爬取的理论和先决条件,是时候专注于开始开发网页爬虫的主要步骤了。
项目设置
我们需要的第一件事是为网页爬虫设置项目。一旦我们安装了”node”,下一步就是在根目录中创建一个项目,然后在其中安装所需的依赖。
我们将使用”npm”来安装依赖。
我命名这个项目为”book-scraping-app”,并为此创建了一个同名的文件夹,在其中运行下面显示的命令。
npm init
一旦我们运行了上述命令,终端会出现不同的提示,您可以随意输入相应的值。完成后,将创建一个名为”package.json”的文件。
package.json
在我的情况下,package.json文件看起来像这样。
{
"name": "book-scraper-app",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": ""Mukul Latiyan"",
"license": "ISC"
}
现在的下一步是能够在我们的项目中添加 puppeteer ,我们可以使用下面显示的命令来实现:
npm install --save-dev puppeteer
以上命令将安装puppeteer以及puppeteer在内部使用的Chromium的版本。
运行以上命令后,我们可以通过检查package.json来验证是否成功安装了puppeteer。
{
"name": "book-scraper-app",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": ""Mukul Latiyan"",
"license": "ISC",
"devDependencies": {
"puppeteer": "^15.5.0"
}
}
现在,安装了 puppeteer 之后,下一步是更改脚本,以便我们可以用不同的方式执行我们的应用程序。
只需将以下代码添加到您的 “package.json” 的 “scripts” 标签中即可。
{
"start": "node index.js"
}
浏览器实例设置
我们已经完成了项目设置。现在让我们专注于浏览器实例设置,确保当我们运行我们的应用程序时,在Chromium浏览器中打开特定的URL。
总共,我们将在四个文件中编写我们的业务逻辑代码。它们将是:
- browser.js - 用于通过puppeteer启动浏览器实例
-
index.js - 网页应用的起始点
-
pageController.js - 一个简单的控制器,用于启动爬虫
-
pageScraper.js - 整个爬取逻辑将在此处
因此,让我们首先创建browser.js文件,并将以下代码放入其中。
browser.js
const puppeteer = require('puppeteer');
async function browserInit() {
let browser;
try {
console.log("Opening the browser......");
browser = await puppeteer.launch({
headless: false,
ignoreDefaultArgs: ['--disable-extensions'],
args: ["--disable-setuid-sandbox"], 'ignoreHTTPSErrors': true
});
} catch (err) {
console.log("Could not create a browser instance => : ", err);
}
return browser;
}
module.exports = {
browserInit
};
在上面的代码中,我们使用 launch 方法来启动一个Chromium浏览器的实例。这个 launch 方法返回一个JS Promise,所以我们必须确保通过使用”then”或”await”块来处理它。
我们使用”await”关键字,然后我们将整个代码包装在一个”try catch”块中。
还应该注意,我们在launch()方法的JSON参数中使用了不同的值。这些主要是 –
- headless - 允许我们以界面运行浏览器,从而确保我们的脚本执行。
-
ignoreHTTPSErrors - 确保您可以访问那些不使用安全协议网络托管的网站。
-
ignoreDefaultArgs - 确保我们能够打开Chromium,并避免阻止我们任务的任何扩展。
现在,我们完成了browser.js文件,下一步是使用index.js文件。
index.js
考虑下面显示的代码。
const browserObject = require('./browser');
const scraperController = require('./pageController');
let browserInstance = browserObject.browserInit();
scraperController(browserInstance)
在上述代码中,我们导入了”browser.js”文件和”pageController.js”文件,然后将浏览器实例传递给”pageController.js”文件中的一个函数。
pageController.js
现在让我们创建一个名为”pageController.js”的文件,然后将以下代码放入其中。
const pageScraper = require('./pageScraper');
async function scrapeAll(browserInstance){
let browser;
try{
browser = await browserInstance;
await pageScraper.scraper(browser);
}
catch(err){
console.log("Could not resolve the browser instance => ", err);
}
}
module.exports = (browserInstance) => scrapeAll(browserInstance)
在上述代码中,我们导出了一个函数,该函数接受浏览器实例,并将其传递给一个名为scrapeAll()的函数。这个scrapeAll()函数然后将浏览器的实例传递给pageScraper.scraper()函数。
pageScraper.js
最后,我们需要编写”pageScraper.js”文件。考虑下面所示的pageScraper的代码。
const scraperObject = {
url: 'http://books.toscrape.com/catalogue/category/books/childrens_11/index.html',
async scraper(browser){
let page = await browser.newPage();
console.log(`Navigating to ${this.url}...`);
await page.goto(this.url);
}
}
module.exports = scraperObject;
在上面的代码中,我们有一个固定的URL,一旦Chromium启动,我们将导航到该URL,然后我们只需调用goto()方法并等待响应。
现在,我们完成了第一个主要的设置或运行Chromium,然后等待响应。
目录结构
以上代码的目录结构应该类似于这样。
├── browser.js
├── index.js
├── package-lock.json
├── package.json
├── pageController.js
└── pageScraper.js
0 directories, 6 files
开始项目
为了开始项目,我们需要运行下面显示的命令 –
npm run start
运行以上命令后,Chromium浏览器将会打开,然后我们将被重定向到“pageScraper.js”文件中指定的URL。
爬取数据
现在让我们专注于如何通过加载数据的选择器来提取该URL上存在的不同书籍的详细信息。
请考虑以下示例中显示的 更新的pageScraper.js 文件代码。
在上面的代码中,我们使用了 pageSelector() 方法,其中我们在等待包含与渲染在DOM中的书籍相关信息的主要div之后使用了eval()方法,该方法帮助我们获取具有选择器部分 ol > li的URL元素。
输出
现在,如果我们重新运行应用程序,一个新的Chromium浏览器将会打开,然后您将会得到该URL中存在的不同书籍的URL地址。
> my-scraper@0.1.0 start
> node index.js
Opening the browser......
Navigating to http://books.toscrape.com/catalogue/category/books/childrens_11/index.html...
[
'http://books.toscrape.com/catalogue/birdsong-a-story-in-pictures_975/index.html',
'http://books.toscrape.com/catalogue/the-bear-and-the-piano_967/index.html',
'http://books.toscrape.com/catalogue/the-secret-of-dreadwillow-carse_944/index.html',
'http://books.toscrape.com/catalogue/the-white-cat-and-the-monk-a-retelling-of-the-poem-pangur-ban_865/index.html',
'http://books.toscrape.com/catalogue/little-red_817/index.html',
'http://books.toscrape.com/catalogue/walt-disneys-alice-in-wonderland_777/index.html',
'http://books.toscrape.com/catalogue/twenty-yawns_773/index.html',
'http://books.toscrape.com/catalogue/rain-fish_728/index.html',
'http://books.toscrape.com/catalogue/once-was-a-time_724/index.html',
'http://books.toscrape.com/catalogue/luis-paints-the-world_714/index.html',
'http://books.toscrape.com/catalogue/nap-a-roo_567/index.html',
'http://books.toscrape.com/catalogue/the-whale_501/index.html',
'http://books.toscrape.com/catalogue/shrunken-treasures-literary-classics-short-sweet-and-silly_484/index.html',
'http://books.toscrape.com/catalogue/raymie-nightingale_482/index.html',
'http://books.toscrape.com/catalogue/playing-from-the-heart_481/index.html',
'http://books.toscrape.com/catalogue/maybe-something-beautiful-how-art-transformed-a-neighborhood_386/index.html',
'http://books.toscrape.com/catalogue/the-wild-robot_288/index.html',
'http://books.toscrape.com/catalogue/the-thing-about-jellyfish_283/index.html',
'http://books.toscrape.com/catalogue/the-lonely-ones_261/index.html',
'http://books.toscrape.com/catalogue/the-day-the-crayons-came-home-crayons_241/index.html'
]
现在让我们对我们的pageScraper.js进行更改,以便我们可以提取所有抓取链接的URL并打开一个新的页面实例,然后检索相关数据。
pageScraper.js
考虑下面显示的更新后的pageScraper.js文件代码。
现在我们可以从所有的URL中提取URL,然后当我们遍历这个数组时,会打开一个新的URL并在该页面上抓取数据,之后关闭该页面,然后打开一个新的页面用于下一个在数组中的URL。
输出
现在你可以重新运行应用程序,你应该能够看到以下输出:
> my-scraper@0.1.0 start
> node index.js
Opening the browser......
Navigating to http://books.toscrape.com/catalogue/category/books/childrens_11/index.html...
{
bookTitle: 'Birdsong: A Story in Pictures',
bookPrice: '£54.64',
noAvailable: '19',
imageUrl: 'http://books.toscrape.com/media/cache/af/2f/af2fe2419ea136f2cd567aa92082c3ae.jpg',
bookDescription: "Bring the thrilling story of one red bird to life. When an innocent bird meets two cruel kids, their world is forever changed. But exactly how that change unfolds is up to you, in the tradition of Kamishibai—Japanese paper theater. The wordless story by master cartoonist James Sturm is like a haiku—the elegant images leave space for children to inhabit this timeless tale—a Bring the thrilling story of one red bird to life. ...more",
upc: '9528d0948525bf5f'
}
{
bookTitle: 'The Bear and the Piano',
bookPrice: '£36.89',
noAvailable: '18',
imageUrl: 'http://books.toscrape.com/media/cache/d0/87/d0876dcd1a6530a4cb54903aad7a3e28.jpg',
bookDescription: 'One day, a young bear stumbles upon something he has never seen before in the forest. As time passes, he teaches himself how to play the strange instrument, and eventually the beautiful sounds are heard by a father and son who are picnicking in the woods....more',
upc: '9f6568e9c95f60b0'
}
….
结论
在本教程中,我们学习了如何使用puppeteer.js在node.js中创建一个网络爬虫。