本想作作爬虫,而后持久化到mongodDb。后来,有需求要下载百度文库的资料,又没有下载券,因而想一想怎样可以免费下载资料,顺便保存下来。因此就有了获取百度文库的资料而顺便学习mongoose。html
按心理活动排序本文叙述分为如下几点。node
sudo brew install mongodb
复制代码
sudo mkdir -p /data/db
复制代码
sudo mongod
复制代码
mongo
复制代码
cd ~ && cnpm i mongodb
复制代码
var MongoClient = require('mongodb').MongoClient;
// 链接数据库
var url_test = 'mongodb://localhost:27017/test'; //数据库test本不存在,链接时会自动建立
var insertData = function(db){
// 往test数据库里新建一个site集合,并插入一条数据
db.collection('site').insertOne({name: 'guojc', age: 99, hobby: 'movie'}, function(err, result){
console.log('inserted successly');
console.log(result);
db.close();
console.log('close');
});
}
MongoClient.connect(url_test, function(err, db) {
console.log('Connected successly to server.');
insertData(db);
});
复制代码
node connect.js,发现链接成功,可是插入数据报错 ==db.collection is not a function==git
解决方法github
我改为这样mongodb
var MongoClient = require('mongodb').MongoClient;
// 链接数据库
var url = 'mongodb://localhost:27017';
var insertData = function(client){
// 往test数据库里新建一个site集合,并插入一条数据
client.db('test').collection('site').insertOne({name: 'guojc', age: 99, hobby: 'movie'}, function(err, result){
console.log('inserted successly');
console.log(result);
client.close();
console.log('close');
});
}
MongoClient.connect(url, function(err, client) {
console.log('Connected successly to server.');
insertData(client);
});
复制代码
Schema: 至关于一个数据库的模板,Schema不具有操做数据库的能力。数据库
Model: 由Schema编译而成的构造器,具备抽象属性和行为,能够对数据库进行增删查改。npm
Entity: 真实的数据。canvas
Schema 生成 Model ,Model 创造 Document,Model和Document均可对数据库操做形成影响。bash
简单demoapp
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');
const con = mongoose.connection;
con.on('error', console.error.bind(console, '链接数据库失败'));
con.once('open',()=>{
//定义一个schema
let Schema = mongoose.Schema({
name:String,
age:Number
});
// 自定义方法
Schema.methods.getAge = function(){
console.log("I am "+this.age + "years old");
}
//继承一个schema
let Model = mongoose.model("student",Schema);
//生成一个document
let student = new Model({
name:'hanmeimei',
age:16
});
//存放数据
student.save((err,res)=>{
if(err) return console.log(err);
res.getAge();
//查找数据
Model.find({name:'hanmeimei'},(err,data)=>{
console.log(data);
})
});
})
复制代码
输出
I am 16years old
[ { _id: 5ab1cad40b0132e9a9e6c65b,
name: 'hanmeimei',
age: 16,
__v: 0 } ]
复制代码
查看数据库,发现多了一个students的table,Mongoose会将集合名称设置为模型名称的小写版。若是名称的最后一个字符是字母,则会变成复数;若是名称的最后一个字符是数字,则不变;若是模型名称为"MyModel",则集合名称为"mymodels";若是模型名称为"Model1",则集合名称为"model1"
参考:
(PS) 前提是百度文库能看到内容,只是下载须要下载券。
一看到这个需求第一反应就是
然而打开文库看了看里面的内容是多张 图片 来的, 并且有 加载更多按钮 emmmm...
那就用 puppeteer吧,以前也用过,因而思路分为如下几点
直接上代码
1. 打开连接
await page.goto(url);
复制代码
2. 点击全屏
page.click('a[data-toolsbar-log=fullscreen]')
复制代码
3. 点击加载更多
page.click('.moreBtn')
复制代码
4. 去掉页面上的多余的dom节点
await page.evaluate(v => {
// dom操做
})
复制代码
5. 保存为pdf
page.pdf({path: 'page.pdf'});
or
page.screenshot({
path: '1.png',
fullPage:true
});
复制代码
看了看每张图片的外层都有一个pageNo-x的ID,
根据这个为切入点的话,就改良了上面步骤。
部分代码
// 找图片,并用一个新节点存起来
async function collectPng(index) {
const res = await page.evaluate(v => {
const div = document.getElementById('collection') || document.createElement('div')
div.id = 'collection'
document.getElementsByTagName('body')[0].appendChild(div)
const item = document.getElementById('pageNo-'+v)
const rpi = item?item.getElementsByClassName('reader-pic-item')[0]: null
rpi&&(rpi.style.position = 'relative')
rpi&&div.appendChild(rpi)
return {index:v, exist:!!rpi}
},index)
return res
}
// 根据返回值,判断是否继续查找仍是下拉页面
async function collecting(index) {
const res = await collectPng(index)
if(res.exist) {
index+=1
await collecting(index)
} else {
if(!hasLoadMore){
console.log('加载更多')
hasLoadMore = true
await loadMore()
await collecting(index)
} else if(index<9){
console.log('下拉')
await pressDown()
await collecting(index)
} else {
}
}
}
// 生成纯图片组合成的dom
async function createDom(){
await page.evaluate(v => {
const div = document.getElementById('collection');
const body = document.createElement('body');
body.appendChild(div)
document.getElementsByTagName('body')[0].remove()
document.getElementsByTagName('html')[0].appendChild(body)
})
}
//pressDown
async function pressDown() {
await page.keyboard.press('ArrowDown',{delay: 2500});
await timeout(1000);
}
复制代码
实际执行状况
最后优化图片背景
因为图片背景会有这些教育机构,为了打印出来更加清晰,能够尝试去掉背景
本身的思路是
若是你能看到这里,谢谢。文章、代码写的较为之粗糙,只是将本身的想法用代码实现,本文初衷是爬虫并持久化到mongoDb的,后来感受偏离了路线。后面会在这个基础上加上这方面功能。至于这个获取百度文库资源的,只是针对这篇三年级上册数学期末试卷及答案,还没作其余灵活处理,之后会考虑更多实际状况。