Python Web 编程

作者: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 初学者,只要掌握基本的前端知识即可。想了解更多关于前端的内容,可以参考以下两个网站:

静态服务器

对于 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_name
        if "/" == 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_body
        print("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 !"			# 如果异常,返回 404
    else:
        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,所以它的运行速度非常快;

更多请参考

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值