官方稱:「Most things that you can do manually in the browser can be done using Puppeteer」,那麼具體能夠作些什麼呢?javascript
更多請查閱官方文檔 github地址java
# 安裝puppeteer
npm install puppeteer --save
# puppeteer 須要安裝 chromium,能夠選擇修改 puppeteer 的下載源:
npm config set puppeteer_download_host https://npm.taobao.org/mirrors
# 安裝chalk
npm install chalk --save
複製代碼
咱們能夠先去觀察下這個 頁面 的HTML
結構, 爬取這個頁面以及每一個詳情頁面咱們須要什麼git
async index() {
const { ctx } = this;
const log = console.log;
/// 圖方便我把經常使用的數據寫在了這裏
const scrape = {
url: 'https://movie.douban.com/tag/#/',
click: '.more',
page: 2,
itemList: '.list-wp > a',
};
/// 啓動一個瀏覽器環境
const browser = await puppeteer.launch();
log(chalk.green('服務正常啓動'));
/// 捕獲錯誤
try {
/// 打開一個新的頁面
const page = await browser.newPage();
/// 咱們須要監聽 request的話 必需要開啓
await page.setRequestInterception(true);
/// 監聽內部的request
page.on('request', interceptedRequest => {
if (interceptedRequest.url().endsWith('.png') || interceptedRequest.url().endsWith('.jpg'))
interceptedRequest.abort();
else
interceptedRequest.continue();
});
/// 打開一個頁面 config 請自行查閱文檔
await page.goto(scrape.url, {
waitUntil: 'networkidle2',
timeout: 0,
});
/// scrape.page 爬取幾頁內容
for (let l = 0; l < scrape.page; l++) {
/// 等待頁面元素加載完畢
await page.waitForSelector(scrape.click);
if (l > 0) {
const submit = await page.$(scrape.click);
if (!submit) {
log(chalk.red('按鈕不存在!'));
return;
}
await submit.click();
await page.waitFor(2500);
}
console.clear();
/// 格式化進度
log(chalk.yellow(ctx.helper.formatProgress(ctx, l, scrape.page)));
/// 獲取當前列表
const itemList = await page.$$(scrape.itemList);
// 開始循環當前列表 咱們看到列表一頁數據在20條 因此咱們從當前頁面*20開始循環 這樣就不會出現每次從新循環都從第一條數據開始
for (let i = l * 20; i < itemList.length; i++) {
const items = await page.$$(scrape.itemList);
const item = items[i];
/// 獲取列表的第i個元素的url
const url = await page.evaluate(item => {
return item ? item.href : '';
}, items[i]);
if (url) {
const page2 = await browser.newPage();
await page2.goto(url, {
timeout: 0,
});
/// 等待一會
await page2.waitFor(1000);
/// page2.evaluate 使咱們能夠在頁面中執行js方法
const result = await page2.evaluate(() => {
const info = document.querySelector('#info');
const screenwriter = [];
const starring = [];
const types = [];
info.querySelectorAll('.attrs')[1].querySelectorAll('a').forEach(item => {
screenwriter.push(item.innerText);
});
info.querySelectorAll('.attrs')[2].querySelectorAll('a').forEach(item => {
starring.push(item.innerText);
});
info.querySelectorAll('[property="v:genre"]').forEach(item => {
types.push(item.innerText);
});
return {
title: document.querySelector('h1') ? document.querySelector('h1').innerText : '',
mainpic: document.querySelector('.nbgnbg > img') ? document.querySelector('.nbgnbg > img').src : '',
director: info.querySelectorAll('.attrs')[0].querySelector('a') ? info.querySelectorAll('.attrs')[0].querySelector('a').innerText : '',
screenwriter,
starring,
types,
release_date: info.querySelector('[property="v:initialReleaseDate"]') ? info.querySelector('[property="v:initialReleaseDate"]').innerText : '',
length: info.querySelector('[property="v:runtime"]') ? info.querySelector('[property="v:runtime"]').innerText : '',
rating_num: document.querySelector('[property="v:average"]') ? document.querySelector('[property="v:average"]').innerText : '',
};
});
/// 寫入文件
fs.appendFile('./movie.json', JSON.stringify(result, null, '\t', {
flag: 'a',
}), function(err) {
if (err) {
throw err;
}
});
}
}
}
await browser.close();
log(chalk.green('服務正常結束'));
} catch (error) {
console.log(error);
log(chalk.red('服務意外終止'));
await browser.close();
}
}
複製代碼
{
"title": "致命女人 第一季 Why Women Kill Season 1 (2019)",
"mainpic": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2566967861.webp",
"director": "大衛·格羅斯曼",
"screenwriter": [
"馬克·切利",
"艾莉莎·榮格"
],
"starring": [
"劉玉玲",
"金妮弗·古德溫",
"柯爾比·豪威爾-巴普蒂斯特",
"傑克·達文波特",
"山姆·賈格",
"裏德·斯科特",
"亞歷珊德拉·達達里奧",
"賽迪·卡爾瓦諾",
"里奧·霍華德",
"艾麗莎·科波拉",
"凱蒂·芬內朗",
"更多..."
],
"types": [
"劇情",
"喜劇",
"犯罪"
],
"release_date": "2019-07-21(洛杉磯LGBT電影節)",
"length": "",
"rating_num": "9.4"
}
複製代碼
無事擼一擼,擼的不對勿噴,你們一塊兒學習一塊兒成長 Come ongithub