前言
爬虫大家应该都不陌生,通过一系列操作去爬取网页上的数据,最近也是在学习node数据库,下面就简单介绍一下,顺便爬取豆瓣读书的部分书籍名字图片作者等...(为什么提到爬虫就爬豆瓣呢),只作为练习,不做盈利等等,否则可能就有点"刑"了 下面就是我们要爬取的地址 book.douban.com/latest
准备工作
身为前端开发者,我们肯定对这个库很熟悉 axios,本次爬虫要用到了两大库 axios与cheerio。 下面是npm 地址,具体大家可以看对应的第三方库
axios:www.npmjs.com/package/axi...
cheerio:github.com/cheeriojs/c... sequelize:www.sequelize.cn/core-concep... cheerio
是 jquery
核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对 DOM
进行操作的地方。大家可以简单的理解为用来解析 html
非常方便的工具。
第一步获取源代码
导入两个库,并获取源代码
js
const axios = require("axios");
const cheerio = require("cheerio");
async function getBooks() {
//获取豆瓣读书网页的源代码
const resp = await axios.get("https://book.douban.com/latest");
return resp.data;
}
根你在网站右键查看源代码是一样的
第二步从详情页拿数据
从这个页面上看,我们可以获取的信息很少,所以我们需要进入详情页才能获取更多的信息,所以我们打开控制台,查看可以发现,图片中有个a元素可以导航到详细页面,所以,我们第二步就是拿到每一个详情页的网址
js
async function getBooksListUrl() {
const html = await getBooks(); //拿到源代码
const $ = cheerio.load(html); //使用load方法解析源代码
const list = $(".chart-dashed-list .media .media__img a"); //找到指定的元素
const links = list
.map((i, ele) => {
const herf = ele.attribs["href"]; //获取href地址
return herf;
})
.get();
return links;
}
}
第三步进入详情页获取信息
进入详情页后,我们发现如下所示,这里我们获取书名,作者,创作时间以及书籍图片(想获取更多大家可以自行按照这样的方式获取)
js
async function getBookDetail(url) {
const resp = await axios.get(url); //获取详情页的源代码
const $ = cheerio.load(resp.data); //解析源代码
const name = $("h1").text().trim(); //获取标题
const imgurl = $("#mainpic img").attr("src"); //图片地址
const author = $("#info span a").text(); //作者名字
const date = $("#info span.pl");
const result = date.filter((i, ele) => {
return $(ele).text().includes("出版年");
});
const publishDate = result[0].nextSibling.nodeValue.trim(); //创作日期
return {
name,
author,
imgurl,
publishDate,
};
}
我们可以发现,标题是由一个h1元素包裹的,且没有第二个h1
图片地址我们可以发现实在id为mainpic的下面的img身上
作者名字,使用text()获取元素中的文字
日期稍微麻烦一点,可以看到,日期由.pl的兄弟元素,所以我们使用如下方式
js
const date = $("#info span.pl");
const result = date.filter((i, ele) => {
return $(ele).text().includes("出版年"); //找到出版年元素
});
const publishDate = result[0].nextSibling.nodeValue.trim();
//创作日期,使用nextSibling获取下一个元素,nodeValue拿到值,去空格
将数据存入数据库
首先我们使用sequelize创建数据库模型
建立连接
js
const { Sequelize } = require("sequelize");
//数据库连接
const sequelize = new Sequelize("mySchoolDB", "root", "dizao06", {
host: "localhost",
// logging: null, //不记录日志
timezone: "+08:00", //保证时间准确
dialect:
"mysql" /* one of 'mysql' | 'postgres' | 'sqlite' | 'mariadb' | 'mssql' | 'db2' | 'snowflake' | 'oracle' */,
});
module.exports = sequelize;
创建book模型
js
const sequelize = require("./index");
const { DataTypes } = require("sequelize");
//创建模型对象,创建表
const Book = sequelize.define(
"Book", //表名
{
//表列
name: {
type: DataTypes.STRING(50),
allowNull: false,
},
imgurl: {
type: DataTypes.STRING,
},
publishDate: {
type: DataTypes.STRING,
allowNull: false,
},
author: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
// freezeTableName: true, // false时 admin-->admins
// createdAt:false, // false 不生成这一列
// updatedAt:false, // false 不生成
paranoid: true, //设置后改表的数据不会真正的删除,而是增加一列deletedAt标识删除时间
}
);
module.exports = Book;
初始化
js
const sequelize = require("./index");
sequelize
.sync({
alter: true,
})
.then((e) => {
console.log("同步完成");
});
存入数据
js
async function getBook() {
const links = await getBooksListUrl(); //详情页地址
const prom = links.map((e) => {
return getBookDetail(e);
});
return Promise.all(prom); //使用promise.all方法等待异步完成
}
async function saveDB() {
const book = await getBook();
// console.log(book);
await Book.bulkCreate(book);//使用bulkCreate存入多条数据
console.log("书籍抓取成功");
}
saveDB();
全代码便于大家复制
js
const axios = require("axios");
const cheerio = require("cheerio");
const Book = require("../models/Book");
// import
async function getBooks() {
//获取豆瓣读书网页的源代码
const resp = await axios.get("https://book.douban.com/latest");
return resp.data;
}
async function getBooksListUrl() {
const html = await getBooks(); //拿到源代码
const $ = cheerio.load(html); //使用load方法解析源代码
const list = $(".chart-dashed-list .media .media__img a"); //找到指定的元素
const links = list
.map((i, ele) => {
const herf = ele.attribs["href"]; //获取href地址
return herf;
})
.get();
return links;
}
async function getBookDetail(url) {
const resp = await axios.get(url); //获取详情页的源代码
const $ = cheerio.load(resp.data); //解析源代码
const name = $("h1").text().trim(); //获取标题
const imgurl = $("#mainpic img").attr("src"); //图片地址
const author = $("#info span a").text(); //作者名字
const date = $("#info span.pl");
const result = date.filter((i, ele) => {
return $(ele).text().includes("出版年");
});
const publishDate = result[0].nextSibling.nodeValue.trim(); //创作日期
return {
name,
author,
imgurl,
publishDate,
};
}
async function getBook() {
const links = await getBooksListUrl(); //详情页地址
const prom = links.map((e) => {
return getBookDetail(e);
});
return Promise.all(prom);
}
async function saveDB() {
const book = await getBook();
console.log(book);
await Book.bulkCreate(book);
console.log("书籍抓取成功");
}
saveDB();
至此就全部结束了,大家可以通过npm进行安装与学习,总之node爬虫还是比较方便的,存入数据库后,我们可以随心所欲的使用,注意不要盈利,那么问题来了,为什么一说爬虫就是豆瓣呢?