puppeteer?
高級API的node庫,能夠通過devtool控制headless模式的chrome或者chromium,它可以在headless模式下模擬任何的人為操作。
與cheerio的區別
cherrico本質上只是一個使用類似jquery的語法操作HTML文檔的庫,使用cherrico爬取數據,只是請求到靜態的HTML文檔,如果網頁內部的數據是通過ajax動態獲取的,那么便爬去不到的相應的數據。而Puppeteer能夠模擬一個瀏覽器的運行環境,能夠請求網站信息,並運行網站內部的邏輯。然后再通過WS協議動態的獲取頁面內部的數據,並能夠進行任何模擬的操作(點擊、滑動、hover等),並且支持跳轉頁面,多頁面管理。甚至能注入node上的腳本到瀏覽器內部環境運行,總之,你能對一個網頁做的操作它都能做,你不能做的它也能做。
例子:
爬取網頁的數據,並把數據保存到數據庫
//爬取疫情數據
const chalk = require("chalk")
const fs = require("fs")
const puppeteer = require('puppeteer');
const mysql = require("mysql");
//數據庫信息根據自己的情況來配
const sqlInfo = {
host: '***.***.***.***',
user: 'root',
password: 'root',
database: '****',
port: 3306
};
// 創建mysql數據庫連接
const con = mysql.createConnection(sqlInfo);
// 連接數據庫
con.connect();
puppeteer.launch({
headless: false, //不使用無頭模式使用本地可視化
//executablePath: "./Chromium/chrome-win/chrome.exe", //因為是yarn add puppeteer --ignore-scripts沒有安裝chromium,需要制定本地chromium的chrome.exe路徑所在,剛才下載后解壓后的全路徑
//設置超時時間
timeout: 15000,
//如果是訪問https頁面 此屬性會忽略https錯誤
ignoreHTTPSErrors: true,
// 打開開發者工具, 當此值為true時, headless總為false
devtools: true,
}).then(async browser => {
const page = await browser.newPage()
await page.goto('https://voice.baidu.com/act/newpneumonia/newpneumonia/?from=osari_aladin_banner', { waitUntil: "networkidle2" })
const moreBtn = await page.$(".Common_1-1-287_3lDRV2");
await moreBtn.click();
await page.waitForSelector('.VirusTable_1-1-287_3m6Ybq');
const data = await page.$$eval('.VirusTable_1-1-287_3m6Ybq', data => {
return data.map(a => {
return {
'area_name': a.children[0].children[0].children[1].innerText,
'newAdd': a.children[1].innerText,
'nowHas': a.children[2].innerText,
'total': a.children[3].innerText,
'cure': a.children[4].innerText,
'death': a.children[5].innerText,
}
});
});
let json = JSON.stringify(data,null,2)
console.log(chalk.green("所有數據抓取完畢:\n", json))
fs.writeFile('YQ.json', json, 'utf8', function(error){
if(error){
console.log(chalk.green(error));
return false;
}
console.log(chalk.blue('數據寫入文件成功!'));
})
await browser.close()
// 開始插入數據庫了
for(let i = 0;i<data.length;i++){
con.query("insert into yiqing(area, newAdd, nowHas, total, cure, death) values(?,?,?,?,?,?)",
[
data[i].area_name,
data[i].newAdd,
data[i].nowHas,
data[i].total,
data[i].cure,
data[i].death
],function(err) {
//這里呢,插入很可能出錯,所以還是要走個形式判斷一下嘛(雖然可能性基本為0只要數據庫能連接上)
if (err) {
//輸出錯誤
console.log(err);
} else {
//到這里,一條數據就插入成功了
console.log(chalk.blue('第'+(i+1)+'條數據成功插入數據庫'));
}
});
}
}).catch(err => console.log(err))
爬到的數據:

寫入到數據庫中的數據:

