如何使用Puppeteer在Node JS服務(wù)器上實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)抓取

億牛云代理

### 導(dǎo)語(yǔ)

動(dòng)態(tài)網(wǎng)頁(yè)抓取是指通過(guò)模擬瀏覽器行為,獲取網(wǎng)頁(yè)上的動(dòng)態(tài)生成的數(shù)據(jù),如JavaScript渲染的內(nèi)容、Ajax請(qǐng)求的數(shù)據(jù)等。動(dòng)態(tài)網(wǎng)頁(yè)抓取的難點(diǎn)在于如何處理網(wǎng)頁(yè)上的異步事件,如點(diǎn)擊、滾動(dòng)、等待等。Puppeteer是一個(gè)基于Node JS的庫(kù),它提供了一個(gè)高級(jí)的API,可以控制Chrome或Chromium瀏覽器,實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)抓取。本文將介紹如何使用Puppeteer在Node JS服務(wù)器上實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)抓取,并給出一個(gè)簡(jiǎn)單的案例。

### 概述

Puppeteer的核心功能是提供了一個(gè)Browser類(lèi),它可以啟動(dòng)一個(gè)Chrome或Chromium瀏覽器實(shí)例,并返回一個(gè)Browser對(duì)象。Browser對(duì)象可以創(chuàng)建多個(gè)Page對(duì)象,每個(gè)Page對(duì)象對(duì)應(yīng)一個(gè)瀏覽器標(biāo)簽頁(yè),可以用來(lái)加載和操作網(wǎng)頁(yè)。Page對(duì)象提供了一系列的方法,可以模擬用戶(hù)的各種行為,如輸入、點(diǎn)擊、滾動(dòng)、截圖、PDF等。Page對(duì)象還可以監(jiān)聽(tīng)網(wǎng)頁(yè)上的事件,如請(qǐng)求、響應(yīng)、錯(cuò)誤、加載等。通過(guò)這些方法和事件,可以實(shí)現(xiàn)對(duì)動(dòng)態(tài)網(wǎng)頁(yè)的抓取。

### 正文

要使用Puppeteer進(jìn)行動(dòng)態(tài)網(wǎng)頁(yè)抓取,首先需要安裝Puppeteer庫(kù)。可以通過(guò)npm或yarn來(lái)安裝:

```javascript

// 使用npm安裝

npm i puppeteer

// 使用yarn安裝

yarn add puppeteer

```

安裝完成后,就可以在Node JS代碼中引入Puppeteer庫(kù),并使用它來(lái)啟動(dòng)瀏覽器和創(chuàng)建頁(yè)面:

```javascript

// 引入puppeteer庫(kù)

const puppeteer = require('puppeteer');

// 啟動(dòng)瀏覽器并創(chuàng)建頁(yè)面

(async () => {

? // 啟動(dòng)瀏覽器,可以傳入一些選項(xiàng),如無(wú)頭模式、代理等

? const browser = await puppeteer.launch({

? ? headless: false, // 是否無(wú)頭模式,默認(rèn)為true

? ? args: ['--proxy-server=http://username:password@domain:port'] // 設(shè)置代理服務(wù)器,使用億牛云爬蟲(chóng)代理的域名、端口、用戶(hù)名、密碼

? });

? // 創(chuàng)建頁(yè)面

? const page = await browser.newPage();

})();

```

創(chuàng)建頁(yè)面后,就可以使用page對(duì)象的方法來(lái)加載和操作網(wǎng)頁(yè)。例如,可以使用page.goto(url)方法來(lái)訪(fǎng)問(wèn)一個(gè)網(wǎng)址,并等待網(wǎng)頁(yè)加載完成:

```javascript

// 訪(fǎng)問(wèn)一個(gè)網(wǎng)址,并等待網(wǎng)絡(luò)空閑(即沒(méi)有超過(guò)500ms的請(qǐng)求)

await page.goto('https://www.example.com', {waitUntil: 'networkidle0'});

```

然后,可以使用page.evaluate(pageFunction, ...args)方法來(lái)在瀏覽器中執(zhí)行一些JavaScript代碼,并返回結(jié)果。例如,可以獲取網(wǎng)頁(yè)上的某個(gè)元素的文本內(nèi)容:

```javascript

// 獲取網(wǎng)頁(yè)上的h1元素的文本內(nèi)容

const h1Text = await page.evaluate(() => {

? return document.querySelector('h1').textContent;

});

```

除了evaluate方法外,page對(duì)象還提供了一些其他的方法來(lái)獲取和操作網(wǎng)頁(yè)上的元素,如page.$(selector)、page.$$(selector)、page.click(selector)、page.type(selector, text)等。例如,可以模擬用戶(hù)在搜索框中輸入關(guān)鍵詞,并點(diǎn)擊搜索按鈕:

```javascript

// 在搜索框中輸入關(guān)鍵詞

await page.type('#search-input', 'puppeteer');

// 點(diǎn)擊搜索按鈕

await page.click('#search-button');

```

有時(shí)候,我們需要等待一些異步事件發(fā)生后再進(jìn)行下一步操作,如等待某個(gè)元素出現(xiàn)、等待某個(gè)請(qǐng)求完成等。這時(shí)候,我們可以使用page.waitFor(selectorOrFunctionOrTimeout, options, ...args)方法來(lái)設(shè)置等待條件。例如,可以等待搜索結(jié)果的列表出現(xiàn)后再獲取其內(nèi)容:

```javascript

// 等待搜索結(jié)果的列表出現(xiàn)

await page.waitFor('#search-results');

// 獲取搜索結(jié)果的列表的文本內(nèi)容

const resultsText = await page.evaluate(() => {

? return document.querySelector('#search-results').textContent;

});

```

最后,當(dāng)我們完成了對(duì)網(wǎng)頁(yè)的抓取,我們可以使用page.screenshot(options)或page.pdf(options)方法來(lái)保存網(wǎng)頁(yè)的截圖或PDF文件。例如,可以將網(wǎng)頁(yè)保存為png格式的圖片:

```javascript

// 將網(wǎng)頁(yè)保存為png格式的圖片

await page.screenshot({path: 'example.png'});

```

當(dāng)我們不再需要瀏覽器和頁(yè)面時(shí),我們可以使用browser.close()方法來(lái)關(guān)閉瀏覽器:

```javascript

// 關(guān)閉瀏覽器

await browser.close();

```

### 案例

下面給出一個(gè)簡(jiǎn)單的案例,使用Puppeteer在Node JS服務(wù)器上實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)抓取。該案例的目標(biāo)是訪(fǎng)問(wèn)百度首頁(yè),輸入關(guān)鍵詞“puppeteer”,點(diǎn)擊搜索按鈕,等待搜索結(jié)果出現(xiàn),并將搜索結(jié)果的第一條鏈接的標(biāo)題和網(wǎng)址保存到一個(gè)文件中。

```javascript

// 引入puppeteer庫(kù)和fs庫(kù)(用于文件操作)

const puppeteer = require('puppeteer');

const fs = require('fs');

// 定義一個(gè)異步函數(shù),用于執(zhí)行動(dòng)態(tài)網(wǎng)頁(yè)抓取

(async () => {

? // 啟動(dòng)瀏覽器,設(shè)置代理服務(wù)器為億牛云爬蟲(chóng)代理的域名、端口、用戶(hù)名、密碼

? const browser = await puppeteer.launch({

? ? args: ['--proxy-server=http://16YUN:16IP@www.16yun.cn:3100']

? });

? // 創(chuàng)建頁(yè)面

? const page = await browser.newPage();

? // 訪(fǎng)問(wèn)百度首頁(yè),并等待網(wǎng)絡(luò)空閑

? await page.goto('https://www.baidu.com', {waitUntil: 'networkidle0'});

? // 在搜索框中輸入關(guān)鍵詞“puppeteer”

? await page.type('#kw', 'puppeteer');

? // 點(diǎn)擊搜索按鈕

? await page.click('#su');

? // 等待搜索結(jié)果的列表出現(xiàn)

? await page.waitFor('#content_left');

? // 獲取搜索結(jié)果的第一條鏈接的標(biāo)題和網(wǎng)址

? const firstResult = await page.evaluate(() => {

? ? // 獲取第一條鏈接的元素

? ? const firstLink = document.querySelector('#content_left .result.c-container a');

? ? // 返回標(biāo)題和網(wǎng)址

? ? return {

? ? ? title: firstLink.innerText,

? ? ? url: firstLink.href

? ? };

? });

? // 將標(biāo)題和網(wǎng)址保存到一個(gè)文件中

? fs.writeFileSync('result.txt', `${firstResult.title}\n${firstResult.url}`);

? // 關(guān)閉瀏覽器

? await browser.close();

})();

```

### 結(jié)語(yǔ)

本文介紹了如何使用Puppeteer在Node JS服務(wù)器上實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)抓取,并給出了一個(gè)簡(jiǎn)單的案例。Puppeteer是一個(gè)強(qiáng)大而靈活的庫(kù),可以用來(lái)處理各種復(fù)雜的動(dòng)態(tài)網(wǎng)頁(yè)抓取場(chǎng)景。使用Puppeteer進(jìn)行動(dòng)態(tài)網(wǎng)頁(yè)抓取時(shí),需要注意以下幾點(diǎn):

- 設(shè)置合適的代理服務(wù)器,以避免被目標(biāo)網(wǎng)站屏蔽或限制??梢允褂脙|牛云爬蟲(chóng)代理提供的高質(zhì)量的代理IP,提高爬蟲(chóng)效果。

- 設(shè)置合適的等待條件,以確保網(wǎng)頁(yè)上的異步事件完成后再進(jìn)行下一步操作??梢允褂胮age.waitFor方法來(lái)設(shè)置等待條件,如元素、函數(shù)、時(shí)間等。

- 設(shè)置合適的異常處理,以應(yīng)對(duì)可能發(fā)生的錯(cuò)誤或異常。可以使用try...catch語(yǔ)句來(lái)捕獲和處理錯(cuò)誤或異常。

希望本文對(duì)你有所幫助,如果你有任何問(wèn)題或建議,請(qǐng)?jiān)谙旅媪粞浴Vx謝!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容