跨平台脚本开发技术实验报告 github cache

2021-2022学年第2学期

实 验 报 告

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKYnUdkJ-1665463185652)(zucc.png “ZUCC”)]

  • 课程名称:跨平台脚本开发技术
  • 实验项目: 期末大作业
  • 专业班级__
  • 学生学号_
  • 学生姓名__
  • 实验指导教师

代码 后端 egg js

实验内容

  1. 最终报告 以上部分自己删除

  2. 项目分工表格

    • 1人项目权重为1.0
    • 2人项目权重和为 1.9
  3. 项目自我评估表

    frp使用教程(转) - 简书 (jianshu.com)

    响应式编程(Reactive Programming)介绍 - 知乎 (zhihu.com)

    FRP(函数时 反应式编程,不是公网穿透啊,那没事了
    

    没有内网穿透,放在阿里云上了,直接公网

    给 MQTTX项目提了一个issue,虽然没写代码,而且和我的项目没啥关系,但是他是个ts项目,也是electron跨平台的,而且我觉得我的这个issue是关于数据量大的时候性能改进的,虽然我没写代码,但是我觉得我想法还可以,也去看了源码,不知道能不能在老师这加点印象分

    When the data volume exceeds 7000, mqttx will become abnormally stuck · Issue #914 · emqx/MQTTX (github.com)

    响应式编程 ,on 什么的应该就是响应式吧,http库的使用

       http.get(wz, function (res) {
                res.on("data", function (chunk) {
                    strHtml += chunk;
                })
                res.on("end", function () {
                    var $ = cheerio.load(strHtml);
    

    函数式 cheerio爬虫,函数当参数,函数连续点,应该就是函数式了

    let title = $(" h2 > a",titleDiv).text()
    
    技术点 自评等级:(1-5) 备注
    FRP(函数式 反应式编程 1 没有吧
    session Storage 1 无状态没有session
    响应式编程 3 http库的使用
    函数式编程 3 cheerio爬虫
    xx 框架 5 egg.js
    ORM 工具 4 egg.js 的mysql
    Graph QL 1 这好像是前端直接sql,我没有
    cheerio爬虫 5
    后台轮询 5
    got reqPromise https http 请求 4 调试了多种请求库
    pm2部署服务器 4
    防抖 3
    上传图片 fs 文件操作、删除等 4
    超时函数 3
  4. 项目说明

    1. 项目 是基于现有的egg-demon代码

      starplatinum111/egg-demon (gitee.com)

      他的项目作为demo,egg的框架有了,但是业务逻辑都是我自己写的

      可见项目文档

      https://acc15t4bm5.feishu.cn/docs/doccnLnginRRAuyalHbuiCevYhf

      运行视频 https://www.bilibili.com/video/bv1zr4y1q7NC

      http://starplatinumora.top:8086/ 在线预览

      图片 https://acc15t4bm5.feishu.cn/docs/doccnzg9HsaG6pP0QQEmDrRxuug

      可以是手机版本的,界面是按照手机版的界面分辨率做css的

      一开始是我自己想做的一个小工具,因为GitHub访问慢嘛,我就希望把他的数据cache下来,放在自己服务器,不就快了嘛,想法很简单,但是我觉得效果不错。当时我先拿SpringBoot写的,后来听说这节课要拿NodeJs写后端,我看刚好合适,就改技术栈,用egg.js 写后端,拿来当作大作业了

      github本身不稳定,有时候加载10s都是有的,挺常见的,但是我这个用的github API,首先他不请求前端,已经快了,然后我再缓存自己服务器,那更快了,不用去访问国外服务器了。issues我本身是不缓存的,直接github API拿,也挺快的,一页一秒钟应该是可以出来的

      因为github慢很多的原因是前端的资源,js,css啊啥的,是从各种cdn里拿来的,但是有些被墙了,所以很慢,然而github本身没有被墙,所以他的后端api还是挺快的。然后还有个特点,github仓库的仓库名和描述是不容易改的,所以他的数据缓存也问题不大,他的一致性要求不高,所以哪怕一个礼拜删一次缓存,那也没关系,不像秒杀啊啥的,需要高一致性,毕竟是钱,搞错了一个订单都不行。

      还有就是api不设防,直接跨域,所以直接axios请求就行,不像知乎,参数都是加密的,没办法请求,毕竟他的内容都是可以用来赚钱的,数据为王,本来就是商业性的,这挺正常的。如果能解决这个加密问题,我觉得别说毕设了,拿个博士论文应该问题不大吧。那这个api开源的好处就是可以很简单的使用,我做起来也方便。所以我觉得这个题目很适合我来做课设。

      公司规定所有接口都用 post 请求,这是为什么? - 知乎 (zhihu.com)

  5. 解决技术要点说明

    • 解决 服务器部署问题 问题, 关键代码与步骤如下

    • egg.js 打包后台 部署 https://blog.csdn.net/qq_35241223/article/details/97306900

      cnpm install pkg -g

      本来想要pkg 打包为 可执行文件 ,部署到服务器上的,但是踩了很多坑。后来发现这种想法是不对的,js的服务应该直接源代码扔到服务器上,cnpm install,然后拿pm2跑服务

      过程错误可见

      https://acc15t4bm5.feishu.cn/docs/doccn0a4VbMf2GDg0JE5kLLErxc

      打包失败

      https://acc15t4bm5.feishu.cn/docs/doccnE5zeKRbx0Y9i3ReMcukyfb

    • 解决问题 cheerio不知道怎么在某个节点之下去找节点, 关键代码与步骤如下
    • https://acc15t4bm5.feishu.cn/docs/doccnFp7PwLdygo0fUnykeedicd

    • cheerio 在一个元素基础上查询

      请问我在查询到一个元素之后,再在这个元素的基础上查询应该怎么做呢。比如在java里用 jsoup 是这样实现的。搜索了repoLis,然后遍历这个lis ,每个元素里面再通过elementLi.select查找

      Elements repoLis= newDoc.select("#js-pjax-container > div > div.col-12.col-md-9.float-left.px-2.pt-3.pt-md-0.codesearch-results > div > ul > li");
      Listlist=new ArrayList<>();
      for (Element elementLi : repoLis) {
         Elements repo1Dom = elementLi.select("div.mt-n1.flex-auto");
      

      但是在cheerio 里面就不知道怎么弄了,也没有代码提示。。

      感觉这样也不对。。

        let repoLis = $("#js-pjax-container > div > div.col-12.col-md-9.float-left.px-2.pt-3.pt-md-0.codesearch-results > div > ul > li");
      
          repoLis.each((idx, item) => {
      
              let repo1Dom = $(item).$("div.mt-n1.flex-auto")
      
              console.log(repo1Dom.text());
          })
      

      我知道了 这样应该可行 let title = $(" h2 > a",titleDiv).text(), 第二个参数是从这个root开始找

         getBaidu:function(query, page) {
        
              const wz = "http://cn.bing.com/search?q=%E7%99%BE%E5%BA%A6&cvid=26d0fce0bc27499b9eabc8bec30cc1b9&aqs=edge..69i57j0l4j69i61l3j69i65.894j0j1&pglt=43&FORM=ANNTA1&PC=U531"; //网址
      
              var strHtml = "";
              var results = [];
              http.get(wz, function (res) {
                  res.on("data", function (chunk) {
                      strHtml += chunk;
                  })
                  res.on("end", function () {
                      var $ = cheerio.load(strHtml);
                
                      let titleDiv = $("#b_results > li:nth-child(1) > div.b_title");
                      let title = $(" h2 > a",titleDiv).text()
                      // 这样应该是可行的
                      console.log("title");
                      console.log(title);
                 
                  });
              })
      
          },
      

因为js类型系统还是差了点,不像java代码即是文档,js的api文档查不到就很难写,当时花了很多时间去查资料,还有自己试代码

因为 rp 是没有timeout参数的,或者说我文档里没找到,然后就找了个超时用的函数,这个我觉得挺通用的,挺好

因为是两个promise 竞赛,所以要用 const rp = require(‘request-promise’); 这个库,返回的是promise

function waitWithTimeout(promise, timeout, timeoutMessage = 'timeout') {
  let timer;
  const timeoutPromise = new Promise((_, reject) => {
    timer = setTimeout(() => reject(timeoutMessage), timeout);
  });
  // race 他俩比赛,谁先成功就干啥 ,因为timeoutPromise 设置了超时之后返回超时的信息
  // 所以外面接到他超时的字符串就是超时啦,虽然说也不是很优雅吧,因为万一不超时的时候也返回这个字符串呢,
  // 但是这种情况很少见 , 或者说只要只要你把timeoutMessage写成一个很乱的,不可能是正常返回的东西,那他就是准确的
  return Promise.race([ timeoutPromise, promise ])
    .finally(() => clearTimeout(timer)); // 别忘了清 timer
}

github 是https的,所以http不能请求,需要用https

const http = require(‘http’);

const https = require(‘https’);

cheerio最后不能是空格

 const topics = $('  div:nth-child(3) > div:nth-child(1) > a', repo1Dom);
 正确
 const topics = $('  div:nth-child(3) > div:nth-child(1) > a ', repo1Dom);
 错误
函数式 list.each
    repoLis.each((idx, item) => {
   
      const repo1Dom = $('div.mt-n1.flex-auto', item);

利用浏览器 方便的获取 xpath路径

爬虫获取路径_哔哩哔哩_bilibili

写了一个mysql save函数,JPA用多了, save还是爽的,搜出来了就更新,搜不出来就插入

const MySqlUtil = {
  async save(mysql, tableName, obj) {
    const firstById = await mysql.get(tableName, {
      id: obj.id,
    });
    if (firstById === null) {
      return await mysql.insert(tableName, obj);
    }
    return await mysql.update(tableName, obj);

  },
};

一个典型的 axios请求Global.axiosUrl 写在一个类里,其他地方都是调用他,这样改api位置了只要改一处,codeError 也是Global里定义

 axios
        .post(Global.axiosUrl + "issue/issues", data, jsonDic)
        .then((response) => {
          if (response.data.port === codeError) {
            // this.$message.error('账号或者密码有误');
            ElMessage.success("账号或者密码有误");
          } else {
            this.tableData = response.data.data;
            console.log("this.tableData");
            console.log(this.tableData);
          }
        })
        .catch(function (error) {
          console.log(error);
        });

因为点击获取issues 万一点击了很多次呢,万一一秒钟点击10次,请求太多,不好的,所以要防抖,隔了几秒才能发请求

  getIssues() {
      if (this.canHit) {
        this.getIssuesDo();
        // 防抖
        this.canHit = false;
        var auth_timetimer = setInterval(() => {
          // this.timer--;
          this.canHit = true;
          clearInterval(auth_timetimer);
        }, 1000);
      }

上传图片

https://acc15t4bm5.feishu.cn/docs/doccnWpEyPaLRAMcRzpTQNVcTyc

数据库字符集

https://acc15t4bm5.feishu.cn/docs/doccnHsCJTYHWkeOBbIepRLQ00e

pm2 log 打印

https://acc15t4bm5.feishu.cn/docs/doccnAJoVJG3F5vpSaFXiJtYZnG

nodejs 报错

https://acc15t4bm5.feishu.cn/docs/doccnAfMDDr0TIpTcBWL1UKBY5c

delete

let  id=ctx.params.id

  axios.delete(`${Global.axiosUrl}img/delete/${img.id}`, {id:img.id}).then((res) => {
        console.log("res");
         console.log(res);
      });
  
  w
  fs.unlink(target,function(error){
  if(error){
      console.log(error);
      return false;
  }
  console.log('删除文件成功');
})
  1. 心得体会(结合自己情况具体说明)

    • 大项目开发过程心得

      • 遇到哪些困难,经历哪里过程,有哪些收获
      • cnpm i egg-bus --save

        cnpm install --save request-promise

        因为库没有 的话 貌似是要重新 run dev的 ,当你启动了这个项目之后,cnpm i 了新的东西,应该是没办法使用的,需要重新run dev,新的库才会被编译

      • egg 报错不是很好,mysql ip 密码之类写错了,启动会失败,但是他的报错不明确

      • yarn 各种bug 目前觉得bug最少的还是cnpm,虽然有时候也会有bug吧

      • https://acc15t4bm5.feishu.cn/docs/doccnyPetglOT7BjKWiRAKsT0eh

      爬虫想扔到消息队列里去的,但是egg-bus没有调通。因为关键词查询仓库的接口github好像是没有给的,只能get他的html然后爬虫他的网页数据,但是这意味着他的前端也要拿到了,所以失败率非常高,基本5次能抓取到一次就很好了,而且很慢,所以要异步的放到队列里去做。

      https://acc15t4bm5.feishu.cn/docs/doccniNDEZ5CRu2swLEPxoaEPLf

      我是写了个"线程"去让他反复做耗时操作,虽然js没有线程 但是我给他这样取名了

      class WhileReqThread {

      因为他是异步的,用起来跟java的线程很像,这样理解是很方便的

      每秒去尝试执行一次,如果次数超过5次,就不做了

        if (that.times < that.tryTimes) {
              // reject("error times out")
              return;
            }
            setTimeout(() => {
              that.tryTimes++;
              that.reqTry(urlStr);
            }, 1000);
      
      
    • 本课程建议

      • 课程难度方面,

      • 计算的本质太难了,calcuslas 、lambda表达式都很难,虽然挺有意思的,但是要理解一个东西都需要很长时间,而且面试也不会考,找工作没用,所以不是很希望花时间在这里,比较适合计算机科学家去研究,而不是应用型大学来学,希望能让有钱人去学这个东西,因为先富带动后富,就是让有钱人,对于生活无忧的人,去研究科学,去发展生产力,去提高国家实力,然后不要和穷人、打工仔来卷前后端,这样穷人有工作,能过活,有钱人可以发展国家,多好啊。而不是有钱人、读书好的人,去卷考公,当了公务员也不知道在干嘛

      • 进度方面,

      • 挺合理的

      • 课程内容,

      • 有意思 但是难,画的时间多,不适合应用型大学,找工作计算的本质应该不太有用,应该卷面经,vue的diff算法,js的Promise啥的,其实也是学了吧,其实还是有点像面经的,

      • 怎么说呢,以后找个955的工作空闲时间学学计算的本质、编译器啥的,还挺有意思,996就算了,没时间学,现在上学期间忙着找工作,也没时间学

      • 授课方式等,

      • 资源很好 很多,放在网站上自己看,很舒服。其实我希望今年讲过的课,有学在城院的视频,可以直接给下届的同学看就行了,可以快进,返回去看,反复看,多好啊,上课可以让同学来问问题,上课可以不讲课了,可以去github上逛,搜集更多的好的资料给同学,不是更好吗

      • 不知道老师有没有兴趣看看我对好的课程的定义

      • 什么样的老师是好老师?应该怎么样做一个好老师? - 求你别让我写论文的回答 - 知乎 https://www.zhihu.com/question/25026687/answer/2344876775

空闲时间学学计算的本质、编译器啥的,还挺有意思,996就算了,没时间学,现在上学期间忙着找工作,也没时间学

授课方式等,

资源很好 很多,放在网站上自己看,很舒服。其实我希望今年讲过的课,有学在城院的视频,可以直接给下届的同学看就行了,可以快进,返回去看,反复看,多好啊,上课可以让同学来问问题,上课可以不讲课了,可以去github上逛,搜集更多的好的资料给同学,不是更好吗

不知道老师有没有兴趣看看我对好的课程的定义

什么样的老师是好老师?应该怎么样做一个好老师? - 求你别让我写论文的回答 - 知乎 https://www.zhihu.com/question/25026687/answer/2344876775

你可能感兴趣的:(数据库,node,github)