DW-32-rec_sys-Task04

Task04 前后端基础及交互

DW-32-rec_sys-Task04

1 前后端交互基本流程

本项目的前端采用基于vue框架的Vant UI组件库,完成用户注册页、用户退出页、用户热门列表页、用户推荐列表页、新闻详情页等功能;后端采用Flask框架,使用MySQL、MongoDB和Redis作为数据存储,根据新闻推荐系统的整体功能,提供用户注册、用户登录、用户推荐页列表、用户热门页列表、新闻详情、用户行为等服务请求,完成用户从注册到新闻浏览、点赞和收藏的全流程。

2 Web及前端基础

​ Web(World Wide Web)即全球广域网,也称为万维网,它是一种基于超文本和HTTP的、全球性的、动态交互的、跨平台的分布式图形信息系统。是建立在Internet上的一种网络服务,为浏览者在Internet上查找和浏览信息提供了图形化的、易于访问的直观界面,其中的文档及超级链接将Internet上的信息节点组织成一个互为关联的网状结构。

​ Web前端主要是通HTML,CSSJS,ajax,DOM等前端技术,实现网站在客服端的正确显示及交互功能。

2.1 Web 标准构成

主要包括结构(Structure)、表现(Presentation)和行为(Behavior)三个方面。

  • 结构标准:结构用于对网页元素进行整理和分类,对于网页来说最重要的一部分 。通过对语义的分析,可以对其划分结构。具有了结构的内容,将更容易阅读.

  • 表现标准:表现用于设置网页元素的版式、颜色、大小等外观样式,主要指的是CSS 。为了让网页能展现出灵活多样的显示效果.

  • 行为标准:行为是指网页模型的定义及交互的编写 。使用户对网页进行操作,网页可以做出响应性的变化。

总的来说,

  • Web标准有三层结构,分别是结构(HTML)、表现(CSS)和行为(JS)

  • 结构类似人的身体, 表现类似人的着装, 行为类似人的行为动作

  • 理想状态下,他们三层都是独立的, 放到不同的文件里面

2.2 HTML

  • HTML 指的是超文本标记语言 (Hyper Text Markup Language)是用来描述网页的一种语言。
  • HTML 不是一种编程语言,而是一种标记语言 (markup language)
  • 标记语言是一套标记标签 (markup tag)

超文本的含义

  • 超越文本限制:可以加入图片、声音、动画、多媒体等内容
  • 超级链接文本:可以从一个文件跳转到另一个文件,与世界各地主机的文件连接。

语法骨架格式

<!DOCTYPE html>
<html>   
    <head>
        <meta charset="utf-8">
        <title>我的第一个页面</title>
    </head>
    <body>
        <h1>一个一级标题</h1>
		<p>一个段落。</p>
    </body>
</html>
  • 声明为 HTML5 文档
  • 元素是 HTML 页面的根元素
  • 元素包含了文档的元(meta)数据
    • 定义网页编码格式
    • 元素描述了文档的标题
  • 元素包含了可见的页面内容
    • 元素定义一个标题

    • 元素定义一个段落

DW-32-rec_sys-Task04

参考链接:

https://www.runoob.com/html/html-tutorial.html

https://www.w3school.com.cn/html/index.asp

2.3 CSS

  • CSS(Cascading Style Sheets) ,通常称为CSS样式表或层叠样式表(级联样式表)
  • CSS主要用于设置 HTML页面中的文本内容(字体、大小、对齐方式等)、图片的外形(宽高、边框样式、边距等)以及版面的布局和外观显示样式。
  • CSS以HTML为基础,提供了丰富的功能,如字体、颜色、背景的控制及整体排版等,而且还可以针对不同的浏览器设置不同的样式。

1 CSS 规则

DW-32-rec_sys-Task04

  • 选择器:需要改变样式的 HTML 元素。

  • 声明:由一个属性和一个值组成。声明之间用分号结束。

    • 属性:希望设置的样式属性。每个属性有一个值。属性和值用冒号分开。

2 语法格式

<标签名 style="属性1:属性值1; 属性2:属性值2; 属性3:属性值3;"> 内容 </标签名>

例如:

<style>
   /*选择器{属性:值;}*/
   p {
   	  color:#06C; 
   	  font-size:14px;  
   	} 
   /*文字的颜色是 蓝色*/
   h4 {
   	 color:#900;
   }
   h1 {
   	 color:#090; 
   	 font-size:16px; 
   	}
   body { 
   	 background:url(bg2.jpg);
   }
</style>

参考链接:

https://www.runoob.com/css/css-tutorial.html

https://www.w3school.com.cn/css/index.asp

2.4 JS

  • JS (JavaScript)是 Web 的编程语言,是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言。同时也是一种广泛用于客户端Web开发的脚本语言,常常用来给HTML网页添加动态效果,从而实现人机交互的网页
  • 脚本语言不需要编译,在运行过程中由 js 解释器(js引擎)逐行来进行解释并执行

1 JS的组成

DW-32-rec_sys-Task04
  • ECMAScript: 是由ECMA 国际( 原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为 JavaScript或 JScript,但实际上后两者是 ECMAScript 语言的实现和扩展。
  • DOM:文档对象模型(DocumentObject Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)
  • BOM:浏览器对象模型(Browser Object Model,简称BOM) 是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。

2 书写位置

1.行内式

<input type="button" value="点我试试" onclick="alert('Hello World')" />
  • 可以将单行或少量 JS 代码写在HTML标签的事件属性中(以 on 开头的属性),如:onclick;
  • 可读性差, 在HTML中编写JS大量代码时,不方便阅读;
  • 引号易错,引号多层嵌套匹配时,非常容易弄混;

2.内嵌式

<script>
    alert('Hello  World~!');
</script>
  • 可以将多行JS代码写到 script 标签中

3.外部JS文件

<script src="myScript.js"></script>
//myScript.js文件内容
function myFunction()
{
    document.getElementById("demo").innerHTML="我的第一个 JavaScript 函数";
}
  • 利于HTML页面代码结构化,把大段 JS代码独立到 HTML 页面之外,既美观,也方便文件级别的复用
  • 引用外部 JS文件的 script 标签中间不可以写代码
  • 适合于JS 代码量比较大的情况

参考链接:

https://www.runoob.com/js/js-tutorial.html

https://www.w3school.com.cn/js/index.asp

2.5 Vue

​ Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

2.5.1 生命周期

​ 每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

​ 下图是一个Vue实例的生命周期:

DW-32-rec_sys-Task04

beforeCreate

​ 在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。

​ 此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data, computed等上的方法和数据。

created

​ 在实例创建完成后被立即同步调用。

​ 实例已完成对选项的处理,以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且 $el property 目前尚不可用。

​ 在这一步中可以调用methods中的方法,改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上,获取computed中的计算属性等等,通常我们可以在这里对实例进行预处理。但需要注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子beforeRouteEnter中完成

beforeMount

​ 在挂载开始之前被调用:相关的 render 函数首次被调用(虚拟DOM)。

​ 实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,但此时还没有挂在html到页面上。

mounted

​ 实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。

​ 模板中的HTML渲染到HTML页面中,此时一般可以做一些ajax操作,mounted只会执行一次

​ 但mounted 不会保证所有的子组件也都被挂载完成。如果希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick:

mounted: function () {
  this.$nextTick(function () {
    // 仅在整个视图都被渲染之后才会运行的代码
  })
}
//生命周期钩子的 this 上下文指向调用它的 Vue 实例。
beforeUpdate

​ 在数据发生改变后,DOM 被更新之前被调用。

​ 适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程.

updated

​ 在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。

​ 当这个钩子被调用时,组件 DOM 已经更新。,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。

​ 但updated 不会保证所有的子组件也都被重新渲染完毕。如果希望等到整个视图都渲染完毕,可以在 updated 里使用 vm.$nextTick:

updated: function () {
  this.$nextTick(function () {
    //  仅在整个视图都被重新渲染之后才会运行的代码     
  })
}
beforeDestroy

​ 实例销毁之前调用。在这一步,实例仍然完全可用。

​ 这一步还可以用this来获取实例,一般用来做一些重置的操作,比如清除掉组件中的定时器和监听的dom事件。

destroyed

​ 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

参考链接:

https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks

https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

2.5.2 创建一个Vue项目

​ Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供:

  • 通过 @vue/cli 实现的交互式的项目脚手架。
  • 通过 @vue/cli + @vue/cli-service-global 实现的零配置原型开发。
  • 一个运行时依赖 (@vue/cli-service),该依赖:
    • 可升级;
    • 基于 webpack 构建,并带有合理的默认配置;
    • 可以通过项目内的配置文件进行配置;
    • 可以通过插件进行扩展。
  • 一个丰富的官方插件集合,集成了前端生态中最好的工具。
  • 一套完全图形化的创建和管理 Vue.js 项目的用户界面。

​ Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接。与此同时,它也为每个工具提供了调整配置的灵活性,无需 eject

3 前后端交互请求

3.1 前端框架

3.1.1 目录结构

Vue-newsinfo
+---src---------------------------------项目主文件夹
|   +---assets--------------------------静态资源文件,包括img、css、js
|   |   +---css-------------------------样式文件
|   |   |   +---sign.css----------------登录注册页的样式
|   |   |   +---test.css----------------顶部导航样式
|   |   +---js--------------------------前端功能
|   |   |   +---cookie.js---------------定义cooki的相关操作,用于用户登录注册、退出时的cookie操作
|   +---components----------------------组件
|   |   +---bottomBar.vue---------------底部导航
|   |   +---hotLists.vue----------------热门页
|   |   +---Myself.vue------------------个人中心“我的”
|   |   +---NewsInfo.vue----------------新闻详情页
|   |   +---recLists.vue----------------推荐页
|   |   +---signIn.vue------------------登录页
|   |   +---signUp.vue------------------注册页
|   +---images--------------------------网站Logo图标,显示在浏览器地址栏或网页标签上
|   |   +---datawhale.png---------------Datawhale头像,用于“我的”页面
|   |   +---dw.png----------------------Datawhale二维码,用于“我的”页面
|   +---App.vue-------------------------根组件
|   +---index.html----------------------项目主页面
|   +---main.js-------------------------主脚本文件,用于定义全局变量、引入插件
|   +---router.js-----------------------路由脚本文件,用于配置路由url链接与页面组件的映射关系
|   +---store.js------------------------状态管理
+---.babelrc----------------------------ES6转码的配置文件
+---favicon.ico-------------------------浏览器小图标
+---package.json------------------------依赖包的配置文件,配置前端项目运行脚本
+---vue.config.js-----------------------vue项目的配置文件
+---webpack.config.js-------------------webpack的配置文件,用于项目打包

3.1.2 创建Vue项目的流程

  1. 安装Vue CLI:提供基于Vue.js快速开发的工具,可实现交互式的项目脚手架搭建
  2. 创建Vue项目:使用vue create命令,创建项目
  3. 路由配置:使用vue-router库,配置router.js
  4. 数据请求:使用axios封装数据请求
  5. 选择UI组件库:选择UI设计组件,用于保证界面一致、用户交互、设计简洁的操作流程

3.2 后端目录结构

news_rec_sys/
    conf/
    	dao_config.py
    controller/  
    dao/
    materials/
    	news_scrapy/
    	user_proccess/
    	material_proccess
    recpocess/
    	recall/
    	rank/
    	online.py
    	offline.py
    scheduler/
    server.py
  • conf/dao_config.py: 候选整体配置文件
  • controller/ : 项目中用于操作数据库的接口
  • dao/ : 项目的实体类,对应数据库表
  • materials/: 项目的物料部分,主要用户爬取物料以及处理用户画像和新闻画像
  • recpocess/: 项目的推荐模块,主要包含召回和排序,以及一些线上服务和线下处理部分
  • scheduler: 项目的定时任务的脚本部分,
  • server.py: 项目后端的入口部分,主要包含项目整体的后端接口部分。

在该项目中,前端主要使用的是Vue框架+mint-ui,后端主要使用的是Flask+Mysql+Mongodb+Redis来完成的,并且前后端采用分离的额方式,通过json的数据格式进行数据传递。其中该项目后端的主要逻辑在在server.py中,其中主要包含用户注册,登录,推荐列表,热门列表,获取新闻详情页以及用户的行为等功能。接下来将主要按照这几部分详细的介绍一下前后端是如何进行交互。

3.3 服务请求

3.3.1 用户注册请求

  • 注册流程:通过前端接收JSON数据(包括用户名、密码、年龄、性别、所在城市),并使用Flask提供用户注册请求服务/recsys/register
  • 代码逻辑:位于server.py中的register()方法,接收用户名、密码、年龄、性别、所在城市,根据用户名判断是否已经存在(调用user_action_controller中的user_is_exist()方法),如果有记录,则返回1,表示注册正常,否则返回0,表示注册失败;再将数据存入MySQL的userinfo库的register_user表中

3.3.2 用户登录请求

  • 登录流程:通过前端接收JSON数据(包括用户名、密码),并使用Flask提供用户登录请求服务/recsys/login
  • 代码逻辑:位于server.py中的login()方法,接收用户名、密码,根据用户名和密码判断是否有记录,如果有记录,则返回1,表示登录正常;如果仅用户名存在,返回2,表示密码错误;否则返回0,表示用户不存在

3.2.3 用户推荐页请求

  • 登录流程:通过前端接收json数据(包括用户名、年龄、性别),并使用Flask提供用户推荐页请求服务/recsys/rec_list
  • 代码逻辑:位于server.py中的rec_list()方法,接收用户名、年龄、性别,根据用户名得到用户ID,根据用户ID调用冷启动的推荐页列表方法(recprocess/online.py中的get_cold_start_rec_list_v2()方法),返回10条推荐新闻

3.3.4 用户热门页请求

  • 登录流程:通过前端接收json数据(包括用户名),并使用Flask提供用户热门页请求服务/recsys/hot_list
  • 代码逻辑:位于server.py中的hot_list()方法,接收用户名,根据用户名得到用户ID,根据用户ID调用热门页列表方法(recprocess/online.py中的get_hot_list_v2()方法),返回10条热门新闻

3.3.5 新闻详情请求

  • 登录流程:通过前端接收json数据(包括用户名,新闻ID),并使用Flask提供新闻详情请求服务/recsys/news_detail
  • 代码逻辑:位于server.py中的news_detail()方法,接收用户名,新闻ID,根据用户名得到用户ID,根据新闻ID得到新闻内容,通过查询user_likes表和user_collections表,得到新闻的用户行为(是否点赞、是否收藏),返回前端需要的新闻详情(新闻内容、用户是否点赞、用户是否收藏)

3.3.6 用户行为请求

  • 登录流程:通过前端接收json数据(包括用户名,新闻ID、用户行为),并使用Flask提供新闻详情请求服务/recsys/action
  • 代码逻辑:位于server.py中的actions()k方法,接收用户名,新闻ID、用户行为,根据用户名得到用户ID,根据用户行为(是否点赞、收藏),修改user_likes表和user_collections表中对应的记录

用户行为记录:

在前端传递过来的数据中存在一个字段 “action_type”:“like:ture” 或 “action_type”:“like:false”(收藏行为类似),对于action_type参数,其值会是一个组合字符串,冒号前面表示用户的具体行为,冒号后面表示用户当前的行为是点击喜欢还是取消喜欢(例如用户误触导致,用户再次点击则会取消)。

通过truefalse我们不仅可以知道当前用户是点击还是取消,其实还可以知道在数据库中是否存在该用户对该新闻的行为记录。原因是当传递来的是false时,表明like的状态是从true变为false,因此数据库中肯定会存在该记录,如果是true,表明like的状态是从false变为true,表明此时数据库中不存在该用户对该新闻的行为记录。通过这样的方式,我们可以比较简单的对数据库进行操作,记录用户的行为。

用户行为落日志:

在企业中,任何系统都会有日志的存在,其中最主要的作用是,日志相当于一个监控器,可以随时监测系统是否出现故障,通过日志可以及时定位系统中可能存在的问题。但是我们说的日志还有所区别,我们这里所说的日志主要是记录的一些线上信息,通过日志的方式进行记录,类似于我们这个系统,用户线上存在的行为,对于我们来说是十分具有意义的,我们需要通过分析这样的用户行为来更好的了解用户兴趣,从而进行更加个性化的推荐。因此我们可以借助日志的方式来记录有意义的用户数据,通过日志数据去分析数据,构建模型,这对于一个算法工程师来说是十分重要的内容。

当然在我们这个新闻推荐系统中,我们这么做的原因有一下几点:

  • 通过这样的方式让大家体会到日志的意义,我们可以直接通过日志获取一些线上有意义的用户数据。
  • 通过日志数据,可以帮助我们更新用户画像中的一些动态特征。
  • 在后面构建模型时,我们也能获取到用户的一些点击率,收藏率的建模,为后面的工作提供数据基础。

上诉代码中,我们通过 LogController() 的 save_one_log() 方法对数据进行了存储到了mysql中。

新闻动态数据更新

由于我们在展现时会显示该新闻的阅读人数、喜欢人数和收藏人数,因此用户的行为实际上会改变新闻这三个属性。因此我们需要更新redis中新闻的这些动态的数据。

主要是通过推荐服务里面的 update_news_dynamic_info()方法进行更新。

4 总结

本次任务,主要介绍了前后端交互相关内容:

  1. 前后端交互的基本流程:前后端使用的技术路线,具备用户注册、用户登录、用户推荐页列表、用户热门页列表、展示新闻详情、记录用户行为等功能
  2. 前端框架:前端项目结构(Vue框架),主要实现登录/注册、推荐/热门、新闻详情、个人中心等页面功能
  3. 后端交互请求:后端目录结构(Flask框架),主要实现用户注册、用户登录、用户推荐页列表、用户热门页列表、新闻详情、用户行为等服务请求
上一篇:1017 Queueing at Bank (25分) 思路详解+满分代码


下一篇:蓝桥杯基础题