Node.js实现爬虫
什么是爬虫?
网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区两头,更常常的称为网页追赶者),是一种依照肯定的规定,主动地抓取万维网信息的程序或者脚本。另外一些不常应用的名字还有蚂蚁、主动索引、模拟程序或者蠕虫。大多数爬虫都是按“发送申请”-“获取页面”-“解析页面”-“抽取并贮存内容”这样的流程来进行,这其实也是模仿了咱们应用浏览器获取网页信息的过程。
所须要的模块
- puppeteer,下载puppeteer模块,用于Node.js爬虫
- mongoose,下载mongoose模块,用于连贯数据库,将爬取的数据传入数据库中。
//下载puppeteer
npm install puppeteer
//下载mongoose
npm install mongoose
正式开始
在这里咱们爬取豆瓣的电影信息来进行测试哦!
看到下面电影信息列表,是不是有种爬取列表信息的激动?好,咱们先关上开发者选项,查看该列表信息。
咱们能够看到每个li标签的data-xxx属性中都带有该电影项的信息,咱们通过获取到该信息,并且将其输入到某界面或存储到数据库中,这就实现了爬虫多种用处的一小部分。话不多说咱们来上代码。
应用爬虫获取界面电影列表的信息
//引入puppeteer模块
const puppeteer = require('puppeteer');
//爬取热门电影信息,的网址
const url = 'https://movie.douban.com/cinema/nowplaying/beijing/';
//因为要申请信息,这里咱们退出async
module.exports = async () => {
//1. 关上浏览器
const browser = await puppeteer.launch({
args: ['--no-sandbox'],
// headless: false //以无头浏览器的模式关上浏览器,没有界面显示,在后盾运行的
});
//2. 创立tab标签页
const page = await browser.newPage();
//3. 跳转到指定网址
await page.goto(url, {
waitUntil: 'networkidle2' //期待网络闲暇时,在跳转加载页面
});
//4. 期待网址加载实现,开始爬取数据
//开启延时器,延时2秒钟在开始爬取数据
await timeout();
let result = await page.evaluate(() => {
//对加载好的页面进行dom操作
//所有爬取的数据数组
let result = [];
//获取所有热门电影的li,这里能够关上开发者选项进行标签的筛选
const $list = $('#nowplaying>.mod-bd>.lists>.list-item');
//这里咱们只取8条数据
for (let i = 0; i < 8; i++) {
const liDom = $list[i];
//电影题目
let title = $(liDom).data('title');
//电影评分
let rating = $(liDom).data('score');
//电影片长
let runtime = $(liDom).data('duration');
//导演
let directors = $(liDom).data('director');
//主演
let casts = $(liDom).data('actors');
//豆瓣id
let doubanId = $(liDom).data('subject');
//电影的详情页网址
let href = $(liDom).find('.poster>a').attr('href');
//电影海报图
let image = $(liDom).find('.poster>a>img').attr('src');
//将爬取到的数据退出进该数组中
result.push({
title,
rating,
runtime,
directors,
casts,
href,
image,
doubanId
})
}
//将爬取的数据返回进来
return result;
})
console.log(result);
//遍历爬取到的8条数据
for (let i = 0; i < result.length; i++) {
//获取条目信息
let item = result[i];
//获取电影详情页面的网址
let url = item.href;
//跳转到电影详情页
await page.goto(url, {
waitUntil: 'networkidle2' //期待网络闲暇时,在跳转加载页面
});
//爬取其余数据
let itemResult = await page.evaluate(() => {
let genre = [];
//类型
const $genre = $('[property="v:genre"]');
for (let j = 0; j < $genre.length; j++) {
genre.push($genre[j].innerText);
}
//简介
const summary = $('[property="v:summary"]').html().replace(/\s+/g, '');
//上映日期
const releaseDate = $('[property="v:initialReleaseDate"]')[0].innerText;
//给单个对象增加两个属性
return {
genre,
summary,
releaseDate
}
})
// console.log(itemResult);
//在最初给以后对象增加三个属性
//在evaluate函数中没方法读取到服务器中的变量
item.genre = itemResult.genre;
item.summary = itemResult.summary;
item.releaseDate = itemResult.releaseDate;
}
console.log(result);
//5. 敞开浏览器
await browser.close();
//最终会将数据全副返回进来
return result;
}
function timeout() {
return new Promise(resolve => setTimeout(resolve, 2000))
}
将爬取的数据存入进数据库
创立数据库连贯
在此时咱们引入mongoose,进行数据库的连贯。话不多说上代码。
//引入mongoose
const mongoose = require('mongoose');
module.exports = new Promise((resolve, reject) => {
//连贯数据库
mongoose.connect('mongodb://localhost:27017/movie_list', {
useNewUrlParser: true,
useUnifiedTopology: true
});
//绑定事件监听
mongoose.connection.once('open', err => {
if (!err) {
console.log('数据库连贯胜利了~~');
resolve();
} else {
reject('数据库连贯失败:' + err);
}
})
})
数据库建表
//引入mongoose
const mongoose = require('mongoose');
//获取Schema
const Schema = mongoose.Schema;
//创立束缚对象
const theatersSchema = new Schema({
title: String,
rating: Number,
runtime: String,
directors: String,
casts: String,
image: String,
doubanId: {
type: Number,
unique: true
},
genre: [String],
summary: String,
releaseDate: String,
posterKey: String, //图片上传到七牛中,返回的key值
createTime: {
type: Date,
default: Date.now()
}
})
//创立模型对象
const Theaters = mongoose.model('Theaters', theatersSchema);
//裸露进来
module.exports = Theaters;
将爬虫爬取的数据引入数据库
//引入Theaters
const Theaters = require('../../model/theaters');
module.exports = async data => {
for (var i = 0; i < data.length; i++) {
let item = data[i];
await Theaters.create({
title: item.title,
rating: item.rating,
runtime: item.runtime,
directors: item.directors,
casts: item.casts,
image: item.image,
doubanId: item.doubanId,
genre: item.genre,
summary: item.summary,
releaseDate: item.releaseDate,
})
console.log('数据保留胜利');
}
}
将子模块引入该主模块中执行
//引入数据库连贯
const db = require('../db');
//引入爬虫
const theatersCrawler = require('./crawler/theatersCrawler');
//引入将爬取信息保留到数据库模块
const saveTheaters = require('./save/saveTheaters');
(async () => {
//连贯数据库
await db;d
//爬取数据
const data = await theatersCrawler();
//将爬取的数据保留在数据库中
await saveTheaters(data);
})()
有帮忙的话就点个赞呗!
发表回复