作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

Web 基础

  1. HTTP 协议
    我们平时都会通过百度查询内容,在这个过程中,用户浏览器被称为客户端,而百度网站被称为服务器。这个过程实质上就是客户端向服务器发起请求,服务器接收请求后,将处理后的信息(也成为响应)传给客户端。这个过程就是通过 HTTP 协议实现的。
    HTTP(HyperText Transfer Protocol)超文本传输协议,是互联网上应用最为广泛的一种网络协议。HTTP 是利用 TCP 在两台计算机(通常是 Web 服务器和客户端)之间传输信息的协议。客户端使用 Web 浏览器发起 HTTP 请求给 Web 服务器,Web 服务器发送被请求的信息给客户端。

  2. Web 服务器
    当在浏览器输入 URL 后,浏览器会先请求 DNS 服务器,获得请求站点的 IP 地址(即根据 URL 地址 www.baidu.com 获取其对应的 IP 地址,如 104.193.88.123),然后发送一个 HTTP Request(请求)给拥有该 IP 的主机(百度的服务器在美国芝加哥),接着就会接收到服务器返回的 HTTP Response(响应),浏览器经过渲染后,以一种较好的效果呈现给用户。

我们重点来看一下 Web 服务器,Web 服务器的工作原理可以概括为以下 4 个步骤:

  • 建立连接:客户端通过 TCP/IP 协议建立到服务器的 TCP 连接;
  • 请求过程:客户端向服务器发送 HTTP 协议请求包,请求服务器里的资源文档;
  • 应答过程:服务器向客户端发送 HTTP 协议答应包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理 “动态内容”,并将处理后得到的数据返回给客户端。有客户端解释 HTML 文档,在客户端屏幕上渲染图形结果;
  • 关闭连接:客户端与服务器断开连接;

HTTP 协议的常用请求方法:

方法 描述
GET 请求指定的页面信息,并返回实体主体
POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件),数据被包含在请求体中
HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
PUT 从客户端向服务器传送的数据取代指定的文档的内容
DELETE 请求服务器删除指定的页面
OPTIONS 允许客户端查看服务器的性能

HTTP 状态码含义:

代码 含义
1** 信息,请求收到,继续处理
2** 成功,行为被成功地接收、理解和采纳
3** 重定向,为了完成请求,必须进一步执行的动作
4** 客户端错误,请求包含语法错误或者请求无法实现
5** 服务器错误,服务器不能实现一种明显无效的请求

具体每一项代表的含义,可以参考:HTTP状态码详解

  1. 前端基础
    对于 Web 开发,通常分为前端(Front-End)和后端(Back-End)。“前端” 是与用户直接交互的部分,包括 Web 页面的结构、Web 的外观视觉表现以及 Web 层面的交互实现。“后端” 更多的是与数据库进行交互,处理相应的业务逻辑。需要考虑的是如何实现功能、数据的存取、平台的稳定性与性能等。后端的编程语言包括 Python、Java、PHP、ASP.NET 等,而前端编程语言包括 HTML、CSS 和 JavaScript。

HTML 是用来描述网页的一种语言。HTML 指的是超文本标记语言(Hyper Text Markup Language),它不是一种编程语言,而是一种标记语言。标记语言是一套标记标签,这种标记标签通常被称为 HTML 标签,它们是由尖括号包围的关键词,比如 。HTML 标签通常是成对出现的,第一个标签是开始标签,第二个标签是结束标签。Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示它们。浏览器不会显示 HTML 标签,而是使用标签来解释页面的内容。

CSS 是 Cascading Style Sheets(层叠样式表)的缩写。CSS 是一种标记语言,用于为 HTML 文档中定义布局。例如,CSS 涉及字体、颜色、边距、高度、宽度、背景图像、高级定位等方面。运用 CSS 样式可以让页面变的美观,就像爱那个化妆前和化妆后的效果一样。

JavaScript 是一种可以嵌入在 HTML 代码中,由客户端浏览器运行的脚本语言。在网页中使用 JavaScript 代码,不仅可以实现网页特效,还可以响应用户请求,实现动态交互的功能。例如,在用户注册页面中,需要对用户输入信息的合法性进行验证,包括是否填写了 “邮箱” 和 “手机号”,填写的格式是否正确等。

作为 Python Web 初学者,只要掌握基本的前端知识即可。想了解更多关于前端的内容,可以参考以下两个网站:

  • w3school
  • 菜鸟教程

静态服务器

对于 Web 开发,我们需要让用户在浏览器中看到完整的 Web 页面(也就是 HTML),在 Web 中,纯粹的 HTML 格式的页面通常被称为 “静态页面”,早期的网站通常都是由静态页面组成的。例如马云早期的创业项目 “中国黄页” 网站就是由静态页面组成的静态网站。下面通过实例结合 Python 网络编程和 Web 编程,创建一个静态服务器。

  1. 创建 views 文件夹,在 views 文件夹下创建 index.html 页面作为首页,index.html 的代码如下:
<!DOCTYPE html>
<html lang="UTF-8">
<head><title>我的博客</title>>
</head>>
<body class="bs-docs-home"><!--Docs master nav-->
<header class="navbar navbar-static-top bs-docs-nav" id="top">
<div class="container"><div class="navbar-header"><a href="/" class="navbar-brand">我的博客</a>></div><nav id="bs-navbar" class="collapse navbar-collapse"><ul class="nav navbar-nav"><li><a href="https://blog.csdn.net/qq_34139994/article/details/107725117">Python 进阶之路</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/97393033">Qt 进阶之路</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/104144719">我的网址收藏</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/93847054">设计模式</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/105390364">请善待90后</a></li><li><a href="/contact.html">联系博主</a></li></ul></nav>
</div>
</header>><!--Page content of coursel-->
<main class="bs-docs-masthead" id="content" tabindex="-1"><div class="container"><span class="bs-docs-booticon bs-docs-booticon-lg bs-docs-booticon-outline">自我介绍</span><p class="lead">博主主要从事于客户端、嵌入式、移动端的开发工作,酷爱研发,热于分享!</p><p class="lead"><a href="/contact.html" class="btn btn-outline-inverse btn-lg">联系博主</a></p></div>
</main>
</body>>
</html>>
  1. 在 views 文件夹下创建 contact.html 文件,作为跳转页面,contact.html 的代码如下:
<!DOCTYPE html>
<html lang="UTF-8">
<head><title>我的博客</title>>
</head>>
<body class="bs-docs-home"><!--Docs master nav-->
<header class="navbar navbar-static-top bs-docs-nav" id="top"><div class="bs-docs-header" id="content" tabindex="-1"><br class="container"><h1>联系博主</h1><div class="lead"><address><br>电子邮件: <strong>123456789@qq.com</strong></br><br>地址: 上海市嘉定区安亭镇紫金大别墅区36号</br><br>邮政编码: 201711</br><br><abbr title="Phone">联系电话: </abbr>021-12345678</address></div></div>
</header>
  1. 在 views 同级目录下创建 web_server.py 文件,用于实现客户端和服务器的 http 通信,具体代码如下:
import socket
import re
from multiprocessing import Process# 设置静态文件根目录
HTML_ROOT_DIR = "./views"    class HTTPServer(object):def __init__(self):# 创建 Socket 对象self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  def start(self):# 设置最多连接数self.server_socket.listen(128)  print("服务器等待客户端连接...")# 执行死循环while True:# 建立客户端连接client_socket, client_address = self.server_socket.accept() print("[%s, %s]用户连接上了" % client_address)# 实例化进程类handle_client_process = Process(target=self.handle_client, args=(client_socket,))handle_client_process.start()client_socket.close()# 处理客户端请求def handle_client(self, client_socket):# 获取客户端请求数据request_data = client_socket.recv(1024) print("request data: ", request_data)# 按照行 ('\r', '\r\n', '\n') 分隔requset_lines = request_data.splitlines()   for line in requset_lines:print(line)# 解析请求报文request_start_line = requset_lines[0]   print("*" * 10)print(request_start_line.decode("gbk"))# 使用正则表达式,提取用户请求的文件名file_name = re.match(r"\w+ +(/[^ ]*)", request_start_line.decode("utf-8")).group(1)# 如果文件名是根目录,设置文件名为 file_nameif "/" == file_name:file_name = "/index.html"# 打开文件,读取内容try:file = open(HTML_ROOT_DIR + file_name, "rb")except IOError:response_start_line = "HTTP/1.1 404 Not Found\r\n"response_headers = "Server: My server\r\n"response_body = "The file is not found !"else:# 读取文件内容file_data = file.read()file.close()response_start_line = "HTTP/1.1 200 OK\r\n"response_headers = "Server: My server\r\n"response_body = file_data.decode("utf-8")# 拼接返回数据response = response_start_line + response_headers + "\r\n" + response_bodyprint("response data: ", response)# 向客户端返回响应数据client_socket.send(bytes(response, "gbk"))    client_socket.close() def bind(self, port):# 绑定端口self.server_socket.bind(("", port)) def main():http_server = HTTPServer()http_server.bind(8000)http_server.start()if __name__ == "__main__":main()

运行 web_server.py 文件,然后使用谷歌浏览器访问 “127.0.0.1:8000/”,得到以下结果:

服务器等待客户端连接...
[127.0.0.1, 55459]用户连接上了
request data:  b'GET / HTTP/1.1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: zh-Hans-CN,zh-Hans;q=0.5\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363\r\nAccept-Encoding: gzip, deflate\r\nHost: 127.0.0.1:8000\r\nConnection: Keep-Alive\r\n\r\n'
b'GET / HTTP/1.1'
b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
b'Accept-Language: zh-Hans-CN,zh-Hans;q=0.5'
b'Upgrade-Insecure-Requests: 1'
b'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363'
b'Accept-Encoding: gzip, deflate'
b'Host: 127.0.0.1:8000'
b'Connection: Keep-Alive'
b''
**********
GET / HTTP/1.1
response data:  HTTP/1.1 200 OK
Server: My server<!DOCTYPE html>
<html lang="UTF-8">
<head><title>我的博客</title>>
</head>>
<body class="bs-docs-home"><!--Docs master nav-->
<header class="navbar navbar-static-top bs-docs-nav" id="top">
<div class="container"><div class="navbar-header"><a href="/" class="navbar-brand">我的博客</a>></div><nav id="bs-navbar" class="collapse navbar-collapse"><ul class="nav navbar-nav"><li><a href="https://blog.csdn.net/qq_34139994/article/details/107725117">Python 进阶之路</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/97393033">Qt 进阶之路</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/104144719">我的网址收藏</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/93847054">设计模式</a></li><li><a href="https://blog.csdn.net/qq_34139994/article/details/105390364">请善待90后</a></li><li><a href="/contact.html">联系博主</a></li></ul></nav>
</div>
</header>><!--Page content of coursel-->
<main class="bs-docs-masthead" id="content" tabindex="-1"><div class="container"><span class="bs-docs-booticon bs-docs-booticon-lg bs-docs-booticon-outline">自我介绍</span><p class="lead">博主主要从事于客户端、嵌入式、移动端的开发工作,酷爱研发,热于分享!</p><p class="lead"><a href="/contact.html" class="btn btn-outline-inverse btn-lg">联系博主</a></p></div>
</main>
</body>>
</html>>[127.0.0.1, 55527]用户连接上了
request data:  b'GET /contact.html HTTP/1.1\r\nReferer: http://127.0.0.1:8000/\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: zh-Hans-CN,zh-Hans;q=0.5\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363\r\nAccept-Encoding: gzip, deflate\r\nHost: 127.0.0.1:8000\r\nConnection: Keep-Alive\r\n\r\n'
b'GET /contact.html HTTP/1.1'
b'Referer: http://127.0.0.1:8000/'
b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
b'Accept-Language: zh-Hans-CN,zh-Hans;q=0.5'
b'Upgrade-Insecure-Requests: 1'
b'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363'
b'Accept-Encoding: gzip, deflate'
b'Host: 127.0.0.1:8000'
b'Connection: Keep-Alive'
b''
**********
GET /contact.html HTTP/1.1
response data:  HTTP/1.1 200 OK
Server: My server<!DOCTYPE html>
<html lang="UTF-8">
<head><title>我的博客</title>>
</head>>
<body class="bs-docs-home"><!--Docs master nav-->
<header class="navbar navbar-static-top bs-docs-nav" id="top"><div class="bs-docs-header" id="content" tabindex="-1"><br class="container"><h1>联系博主</h1><div class="lead"><address><br>电子邮件: <strong>123456789@qq.com</strong></br><br>地址: 上海市嘉定区安亭镇紫金大别墅区36号</br><br>邮政编码: 201711</br><br><abbr title="Phone">联系电话: </abbr>021-12345678</address></div></div>
</header>


WSGI 接口

WSGI(Web Server Gateway Interface)服务器网端接口,是 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。WSGI 中存在两种角色:接受请求的的 Server(服务器)和处理请求的 Application(应用),它们底层是通过 FastCGI 沟通的。当 Server 收到一个请求后,可以通过 Socket 把环境变量和一个 Callback 回调函数传给后端 Application,Application 在完成页面组装后通过 Callback 把内容返回给 Server,最后 Server 再将响应返回给 Client。

使用 Python 的 wsgiref 模块可以不用考虑服务器和客户端的连接、数据的发送和接收等问题,而专注以业务逻辑的实现。下面通过实例应用 wsgiref 创建页面。

使用上个例子中 views 文件夹下的 index.html 作为主页
在 views 文件夹同级目录下创建 application.py 文件,用于实现 Web 应用程序的 WSGI 处理函数,具体代码如下:

def app(environ, start_response):start_response('200 OK', [('Content-Type', 'text/html')])   # 响应信息file_name = environ['PATH_INFO'][1:] or '/index.html'  # 获取 url 参数HTML_ROOT_DIR = "./views"                 # 设置 HTML 文件目录try:file = open(HTML_ROOT_DIR + file_name, "rb")      # 打开文件except IOError:response = "The file is not found !"            # 如果异常,返回 404else:file_data = file.read()                   # 读取文件内容file.close()                        # 关闭文件response = file_data.decode("utf-8")           # 构造响应数据    return [response.encode("utf-8")]             # 返回数据

在 views 文件夹同级目录下创建 web_server.py 文件,用于启动 WSGI 服务器,加载 application() 函数,具体代码如下:

from wsgiref.simple_server import make_server            # 从 wsgiref 模块导入
from application import app                 # 导入编写的 application 函数httpd = make_server("", 8000, app)             # 创建一个服务器,IP 地址为空,端口为 8000,处理函数是 app
print("Serving HTTP on port 8000...")httpd.serve_forever()                        # 开始监听 HTTP 请求

运行 web_server.py 文件,当显示 “Serving HTTP on port 8000…” 时,在浏览器地址栏输入 “127.0.0.1:8000”,就能访问 index.html 首页啦!

Web 框架

如果你要从零开始建立一些网站,可能会注意到你不得不一次又一次地解决一些相同的问题。这样做是非常麻烦的,并且违反了良好编程的核心原则之一 - DRY(不要重复自己)。

有经验的 Web 开发人员在创建新站点时也会遇到类似的问题。当然,总会有一些特殊情况会因网站而异,但在大多数情况下,开发人员通常需要处理四项任务 - 数据的创建、读取、更新和删除,也称为 CURD。幸运的是,开发人员通过使用 Web 框架解决了这些问题。

Web 框架是用来简化 Web 开发的软件框架。框架的存在是为了避免用户重新发明轮子,并且在创建一个新的网站时帮助减少一些开销。典型的框架提供了如下常用功能:

  • 管理路由;
  • 访问数据库;
  • 管理会话和 Cookies;
  • 创建摸版来显示 HTML;
  • 促进代码的重用;

事实上,框架根本就不是什么新的东西,它只是一些能够实现常用功能的 Python 文件。我们可以把框架看作是工具的集合,而不是特定的东西。框架的存在使得建立网站更快、更容易。

前面我们学习了 WSGI(服务器网关接口),它是 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。也就是说,只要遵循 WSGI 接口规则,就可以自主开发 Web 框架。所以,各种开源 Web 框架至少有上百个,关于 Python 框架优劣的讨论页仍在继续。

作为初学者,应该选择一些主流的框架来学习,因为主流的框架文档齐全,技术积累较多,社区繁盛,并且能得到更好的支持。下面介绍几种 Python 的主流 Web 框架:

  1. Django
    这可能是最广为人知和使用最广泛的 Python Web 框架了。Django 有世界上最大的社区和最多的包。它的文档非常完善,并且提供了一站式的解决方案,包括缓存、ORM、管理后台、验证、表单处理等,使得开发复杂的数据库驱动的网站变得简单。但是,Django 系统耦合度较高,替换掉内置的功能比较麻烦,所以学习曲线也相当崎岖;

  2. Flask
    Flask 是一个轻量级 Web 应用框架。它的名字暗示了它的含义,他基本上就是一个微型的胶水框架。Flask 把 Werkzeug 和 Jinja 粘和在一起,所以它很容易被扩展。Flask 也有许多的扩展可以供用户使用,Flask 也有一群忠诚的粉丝和不断增加的用户群。它有一份很完善的文档,甚至还有一份唾手可得的常见范例。Flask 很容易使用,用户只需要几行代码就可以写出来 “Hello World”;

  3. Bottle
    这个框架相对来说比较新。Bottle 才是名副其实的微框架 - 它只有大约 4500 行代码。它除了 Python 标准库以外,没有任何其他的依赖,甚至还有自己独特的一点儿模板语言。Bottle 的文档很详细并且抓住了事物的实质。它很像 Flask,也使用了装饰器来定义路径;

  4. Tornado
    Tornado 不单单是个框架,还是个 Web 服务器。它一开始视为 FriendFeed 开发的,后来在 2009 年的时候也给 Facebook 使用。它是为了解决实时服务而诞生的。为了做到这一点,Tornado 使用了异步非阻塞 IO,所以它的运行速度非常快;

更多请参考

  • Python 进阶之路

Python Web 编程相关推荐

  1. [Python]WEB编程--个人日记网站搭建(一)

    用Python+Tornado 编写一个个人日记网站(一) 讲道理,用惯了Flask感觉还是不熟悉Djongo,所以先来看一下Tornado(滑稽),记住这是一个最简单的最暴力的网页,毫无细节. 'F ...

  2. Python Web 编程框架

    目前Python的网络编程框架已经多达几十个,逐个学习它们显然不现实.但这些框架在系统架构和运行环境中有很多共通之处,本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Pytho ...

  3. python编程基础人邮版答案_《Python Web 编程》(人邮出版社)作业答案下载

    全部作业答案: 链接:https://pan.baidu.com/s/1bm73IFUUfkBl0HHhYovehQ  提取码:bus6 01 Django 基础 链接:https://pan.bai ...

  4. Python安全编程

    目录 一.Python黑客领域的现状 二.Python正则表达式 2.1  正则表达式的介绍 2.2  正则表达式使用方法 2.3  贪婪模式和非贪婪模式 三.Python Web编程 3.1 url ...

  5. Python Web中REST API使用示例——基于云平台+云服务打造自己的在线翻译工具

    做为一个程序员可能在学习技术,了解行业新动态,解决问题时经常需要阅读英文的内容:而像我这样的英文小白就只能借助翻译工具才能理解个大概:不禁经常感慨,英文对学习计算机相关知识太重要了!最近发现IBM的云 ...

  6. python安全编程教程_[ichunqiu笔记] python安全应用编程入门

    01 python正则表达式 02 Python Web编程 03 Python多线程编程 04 Python网络编程 05 Python数据库编程 ------------------------- ...

  7. web编程 模块1 html,PYcore python programming笔记C20 Web编程

     C20 Web编程 20.1介绍 C/S架构  服务端永远运行 HTTP协议 :无状态协议,不跟踪一个客户端到另一个客户端的请求,但会被处理为独立的服务请求 使用URL和cookie保存信息 U ...

  8. python web开发 网络编程 TCP/IP UDP协议

    文章目录 1. TCP/IP协议 1.1 IP协议 1.2 TCP协议 2. UDP协议 3. Socket 4. TCP编程 4.1 创建TCP服务器 4.2 创建TCP客户端 4.3 简易聊天工具 ...

  9. Python 四大主流 Web 编程框架

    目前Python的网络编程框架已经多达几十个,逐个学习它们显然不现实.但这些框架在系统架构和运行环境中有很多共通之处,本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Pytho ...

  10. python视频网站项目_价值2400元的python全栈开发系列Flask Python Web 网站编程视频

    2 e/ b4 F1 c' H$ D! X 价值2400元的python全栈开发系列Flask Python Web 网站编程视频-优品课堂' z3 _1 Y7 ]6 j4 z # p# r# g* ...

最新文章

  1. 3D MinkowskiEngine稀疏模式重建
  2. 从30岁到35岁:为你的生命多积累一些厚度(转)
  3. 超长整数相加 c语言类,二个超长正整数的相加
  4. 苹果怎样运行低版本php,Mac如何安装多个php版本
  5. C/C++ 如何快速解构一个系统的源码(如何看懂大型工程项目的源码)
  6. CTF工具(1)--- ARCHPR--含安装/使用过程
  7. 问题 1052: [编程入门]链表合并
  8. 毫秒值转换为日期工具_为机器学习准备数据
  9. 浏览器拦截跨域请求处理方法(已阻止跨源请求:同源策略禁止读取远程资源)
  10. 数组转集合集合转数组 split方法
  11. 浏览器输入一个url会发生什么
  12. CF11D A Simple Task(状压DP)
  13. 电脑浏览器下载速度很慢怎么办
  14. MySQL例题一 综合案例(多条件组合查询)
  15. linux卸载致远oa,致远oa(seeyon)文件上传漏洞重现及分析
  16. 顺序表 —— Java附加代码
  17. Aliyun-OSS海量存储
  18. MEC与C-V2X融合应用场景白皮书
  19. cannot import name ‘gcd’ from ‘fractions’
  20. 应广单片机003烧录器自定义封装使用技巧

热门文章

  1. Java关键字protected详解
  2. HTTP缓存机制在iOS中的应用和体现
  3. Apache Jemeter 参数化
  4. jQuery节点创建与属性的处理 创建节点
  5. 登陆界面输入框内加入小图标的样式
  6. 前端开发面试题-JavaScript(一)
  7. makefile:425: *** 遗漏分隔符
  8. JAVA视频全套在线学习
  9. Predict user model based on genus
  10. ubuntu 添加删除源