本想作作爬蟲,而後持久化到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的,後來感受偏離了路線。後面會在這個基礎上加上這方面功能。至於這個獲取百度文庫資源的,只是針對這篇三年級上冊數學期末試卷及答案,還沒作其餘靈活處理,之後會考慮更多實際狀況。