微信应用开发之搭建小说微信小程序
沉沙 2018-12-29 来源 : 阅读 2559 评论 0

摘要:本篇教程探讨了微信应用开发之搭建小说微信小程序,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

本篇教程探讨了微信应用开发之搭建小说微信小程序,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

微信应用开发之搭建小说微信小程序

<

由于上下班期间会看会小说,但是无奈广告太多,还要收费,于是结合课程,进行开发,并上传到自己的微信小程序。
clipboard.png
github
大致的思路:
1.连接数据库
2.跑定时任务,进行数据库的更新
3.开启接口服务
4.微信小程序接口调用
1.连接数据库
连接本地的mongodb数据库
const mongoose = require('mongoose')
var db = 'mongodb://localhost/story-bookShelf'
exports.connect = () => {
  let maxConnectTimes = 0
  return new Promise((resolve, reject) => {
    if (process.env.NODE_ENV !== 'production') {
      mongoose.set('debug', false)
    }
    mongoose.connect(db)
    mongoose.connection.on('disconnected', () => {
      maxConnectTimes++
      if (maxConnectTimes < 5) {
        mongoose.connect(db)
      } else {
        throw new Error('数据库挂了吧,快去修吧')
      }
    })
    mongoose.connection.on('error', err => {
      console.log(err)
      maxConnectTimes++
      if (maxConnectTimes < 5) {
        mongoose.connect(db)
      } else {
        throw new Error('数据库挂了吧,快去修吧')
      }
    })
    mongoose.connection.once('open', () => {
      resolve()
      console.log('MongoDB Connected successfully!')
    })
  })
}
然后初始化定义好的Schema
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const bookSchema = new Schema({
  name: {
    type: String
  },
  bookId: {
    unique: true,
    type: Number
  }
})
......
mongoose.model('Book', bookSchema)
2.跑定时任务,进行数据库的更新
这一步骤主要是在定时进行数据库小说章节的更新,用的是 node-schedule进行定时跑任务。
    小说章节数是否增加,没增加不用进行爬取。同时在爬取的时候需要提前前5章爬取,避免一些作者为了占坑,提前写的预告。
    每一本小说就开一个子进程child_process去跑,将数据存储到mongo, 同时存储子进程对后续有用。
    定时跑任务时候会遇到上一条任务还在跑,所以在每一次跑之前都清空一遍储存的子进程,将子进程杀掉。
章节任务
// chapter.js 
const cp = require('child_process')
const { resolve } = require('path')
const mongoose = require('mongoose')
const { childProcessStore } = require('../lib/child_process_store') // 全局存储子进程
/**
 * 
 * @param {书本ID} bookId 
 * @param {从哪里开始查找} startNum 
 */
exports.taskChapter = async(bookId, startNum = 0) => {
  
  const Chapter = mongoose.model('Chapter')
  
  const script = resolve(__dirname, '../crawler/chapter.js') // 真正执行爬虫任务模块
  const child = cp.fork(script, []) // 开启IPC通道,传递数据
  let invoked = false
  
  // 这里等子进程将数据传回来,然后存储到mongo中(具体爬取看下一段代码)
  child.on('message', async data => {
    // 先找一下是否有数据了
    let chapterData = await Chapter.findOne({
      chapterId: data.chapterId
    })
    // 需要将拿到的章节与存储的章节做对比  防止作者占坑
    if (!chapterData) {
      chapterData = new Chapter(data)
      await chapterData.save()
      return
    } 
    
    // 进行字数对比 相差50字符
    if ((data.content.length - 50 >= 0) && (data.content.length - 50 > chapterData.content.length)) {
      Chapter.updateOne (
        { chapterId: +data.chapterId },
        { content : data.content }
      );
    }
  })
  
  child.send({ // 发送给子进程进行爬取
    bookId, // 哪本小说
    startNum // 从哪个章节开始爬
  })
  // 存储所有章节的爬取  用于跑进程删除子进程
  childProcessStore.set('chapter', child)
}
 
真正开启爬虫,用的是 puppeteer,谷歌内核的爬取,功能很强大。
分两步:
1.爬对应小说的章节目录,拿到章节数组
2.根据传进来的startNum 进行章节startNum 的往后爬取
// crawler/chapter.js
const puppeteer = require('puppeteer')
let url = `//www.mytxt.cc/read/` // 目标网址
const sleep = time => new Promise(resolve => {
  setTimeout(resolve, time)
})
process.on('message', async book => {
  url = `${url}${book.bookId}/`
  console.log('Start visit the target page --- chapter', url)
  // 找到对应的小说,拿到具体的章节数组
  const browser = await puppeteer.launch({
    args: ['--no-sandbox'],
    dumpio: false
  }).catch(err => {
    console.log('browser--error:', err)
    browser.close
  })
  const page = await browser.newPage()
  await page.goto(url, {
    waitUntil: 'networkidle2'
  })
  await sleep(3000)
  await page.waitForSelector('.story_list_m62topxs') // 找到具体字段的class
  let result = await page.evaluate((book) => {
    let list = document.querySelectorAll('.cp_dd_m62topxs li')
    let reg = new RegExp(`${book.bookId}\/(\\S*).html`)
    let chapter = Array.from(list).map((item, index) => {
      return {
        title: item.innerText,
        chapterId: item.innerHTML.match(reg)[1]
      }
    })
    return chapter
  }, book)
  // 截取从哪里开始爬章节
  let tempResult = result.slice(book.startNum, result.length)
  for (let i = 0; i < tempResult.length; i++) {
    let chapterId = tempResult[i].chapterId
    console.log('开始爬url:', `${url}${chapterId}.html`)
    await page.goto(`${url}${chapterId}.html`, {
      waitUntil: 'networkidle2'
    })
    await sleep(2000)
    const content = await page.evaluate(() => {
      return document.querySelectorAll('.detail_con_m62topxs p')[0].innerText
    })
    tempResult[i].content = content
    tempResult[i].bookId = book.bookId
    
    process.send(tempResult[i]) // 通过IPC将数据传回去,触发child.on('message')
  }
  browser.close()
  process.exit(0)
})
3.开启接口
做的任务主要是,拿mongodb的数据,同时通过koa-router发布路由
先定义好路由装饰器,方便后续使用 具体看 decorator.js
底层拿到数据库的数据
service/book.js // 拿到数据库存储的值
const Chapter = mongoose.model('Chapter')
// 获取具体的章节内容
export const getDetailChapter = async (data) => {
  const chapter = await Chapter.findOne({
    chapterId: data.chapterId,
    bookId: data.bookId
  }, {
    content: 1,
    title: 1,
    chapterId: 1
  })
  // console.log('getDetailChapter::', chapter)
  return chapter
}
...
路由定义 后续的接口就是 ‘/api/book/chapter’
@controller('/api/book')
export class bookController {
  @post('/chapter')
  async getDetailChapter (ctx, next) {
    const { chapterId, bookId } = ctx.request.body.data
    const list = await getDetailChapter({ 
      chapterId, 
      bookId 
    })
    ctx.body = {
      success: true,
      data: list
    }
  }
}
4.微信小程序
使用wepy进行开发,功能也是很简单,具体开发可以参见小程序代码,这里不做详细讲述。
支持记录每一章的进度,与全局设置。后续可以自己发挥。
在目标网站找到小说的Id之后就能进行查找了。    

本文由职坐标整理发布,学习更多的相关知识,请关注职坐标IT知识库!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程