官方称:“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