一、介绍

HTTP(HyperText Transfer Protocol)是一个客户端和服务器端请求和应答的标准。
客户端是终端用户,服务器端是网站。客户端发起一个到服务器上指定端口的HTTP请求,服务器向客户端发会一个状态行和响应的信息。

二、socketserver模块

2.1 介绍

官方文档:https://docs.python.org/3/library/socketserver.html
参考:https://www.cnblogs.com/caesar-id/p/12094529.html
socketserver模块提供了一个架构来简化网络包括服务器的编写工作,用户不需要使用低级的socket模块。

2.2 四个基本服务器类

2.2.1 介绍

有四个基本的具体服务器类:

说明
class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True) TCP数据流服务器
class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True) UDP数据流服务器
class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True) 仅限于Unix系统的socket支持串流导向协议(stream-oriented protocol )的服务器
Unix套接字流
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True) 仅限于Unix系统的socket支持数据通信协议(datagram-oriented-protocol)的服务器
Unix数据报

参数说明:
server_address:服务器的地址,是一个元组包含地址和端口,eg:(‘192.168.1.1’,9000),
RequestHandlerClass:我们自定义的类,类中必须重写handle()方法。用于处理所有socket请求。
bind_and_activate:如果为True,将自动调用server_bind()和server_activate()

这四个基本的具体服务器类处理同步的请求** ,每一个请求都必须在下一个请求开始之前完成。如果客户端需要长时间计算,这些类就不适合。
可以通过线程处理不同步的请求,使用
ThreadingTCPServer类、ThreadingUDPServer类、ForkingTCPServer类及ForkingUDPServer类。**

2.2.2 类的类变量

类变量 说明
request_queue_size 存储要求队列的大小,该队列用于传给socket的listen()方法
socket_type 返回服务器使用的socket类型,可以是socket.SOCK_STREAM或
socket.SOCK_DGRAM

2.2.3 类的属性和方法

属性 说明
address_family 服务器套接字所属的协议系列。
可以是socket.AF_INET或socket.AF_UNTX
fileno() 返回服务器正在侦听的套接字的整数文件描述符
handle_requset() 处理单个请求。这个函数调用下面的方法依次是:get_request(),verify_request(),和 process_request()。
RequestHandleClass 用户提供的请求处理程序类;将为每个请求创建此类的实例。
server_address 服务器正在监听的地址。地址的格式取决于协议系列;
对于Internet协议,这是一个元组,IP + PORT ,eg:
(‘127.0.0.1’, 80)
serve_forever(poll_interval = 0.5 处理请求,直到明确请求为止shutdown()
每poll_interval秒关闭一次轮询。

三、server模块

http模块的子模块server,定义用于实现HTTP服务器(Web服务器)的类,主要包括BaseHTTPServer类、CGIHTTPServer类及SimpleHTTPServer类。
http.server不建议用于生产。它仅实现基本的安全检查。

3.1 BaseHTTPServer类

server模块定义两个基类来操作基本的HTTP服务器(网站服务器),以socketserver模块为基础,很少直接使用。
HTTPServer
class http.server.HTTPServer(server_address, RequestHandlerClass)
HTTPServer类是socketserver.TCPServer类的派生类。这个类先创建一个HTTPServer对象并监听(hostname,port),然后使用RequestHandlerClass类来处理请求。
BaseHTTPRequestHandler
class http.server.BaseHTTPRequestHandler(request, client_address, server)
用户必须创建一个BaseHTTPRequestHandle类的子类来处理HTTP请求。如果要处理GET请求,就必须创建定义do_GET() 方法,如果要处理POST请求,就必须重新定义do_POST() 方法。

BaseHTTPRequestHandle类的属性

属性 说明
server_version 服务器软件版本
sys_version Python系统版本
protocol_version 指定响应中使用的HTTP协议版本
error_message_format 指定一种格式字符串,send_error()方法应使用该格式字符串来构建对客户端的错误响应。
error_content_type 指定发送到客户端的错误响应的Content-Type HTTP表头
MessageClass 指定一个email.message.Message类似的类来解析HTTP表头
responses 此属性包含错误代码整数到包含短消息和长消息的两个元素的元组的映射。

BaseHTTPRequestHandler 具有以下实例变量

变量 说明
client_address (host, port),客户端的地址
server 服务器实例
close_connection handle_one_request()返回之前应设置的布尔值,指示是否可能期望另一个请求,或者是否应该关闭连接。
requestline 包含HTTP请求行的字符串表示形式,终止CRLF。
如果未处理有效的请求行,则应将其设置为空字符串。
command 请求类型,eg:GET、POST等
path 请求的路径
request_version 返回请求的HTTP版本字符串,eg:’HTTP/1.0’
headers 返回一个HTTP表头
rfile 一个io.BufferedIOBase输入流,准备从可选输入数据的开头读取。
wfile 包含用于将响应写回到客户端的输出流。

每一个BaseHTTPRequestHandler类的实例变量的方法

方法 说明
handle() 请求分派器,调用以“do_”开头的方法,eg:
do_GET()、do_POST()
调用handle_one_request()一次(或者,如果启用了持久连接,则调用多次)以处理传入的HTTP请求。
handle_one_request() 将解析请求并将其分派到适当的 do_*()方法
handle_expect_100() 当符合HTTP / 1.1的服务器接收到请求表头时,它会在响应标头后跟一个表头
send_error(code, message=None, explain=None) 发送完整的错误回复并将其记录到客户端。
send_response(code, message=None) 将响应表头添加到表头缓冲区,并记录接受的请求。
send_header(keyword, value) 将HTTP标表头添加到内部缓冲区,当end_headers()或flush_headers()调用时,该缓冲区将被写入输出流。
send_response_only(code, message=None) 仅发送响应头,用于服务器将响应发送到客户端时的目的。
end_headers() 将缓冲的表头写入输出流。
flush_headers() 将表头发送到输出流并刷新内部标头缓冲区。

3.2 SimpleHTTPRequestHandler 类

SimpleHTTPRequestHandler类用于处理HTTP server的请求,也可以处理所在目录的文件,即HTML文件。
class http.server.SimpleHTTPRequestHandler(request, client_address, server, directory=None)
SimpleHTTPRequestHandler类的属性

属性 说明
server_version 服务器版本
extensions_map 一个字典,字典映射后缀为MIME类型
directory 如果未指定,则要服务的目录是当前工作目录。

SimpleHTTPRequestHandler类的方法

方法 说明
do_HEAD() 用于’HEAD’请求类型:它发送将为等效GET请求发送的表头。
do_GET() 通过将请求解释为相对于当前工作目录的路径,将请求映射到本地文件。

3.3 CGIHTTPRequestHandler类

CGIHTTPRequestHandler类除了可以处理所在目录的HTML文件外,还可以运行客户端执行CHI(Common Gateway Interface)脚本。
语法格式:
class http.server.CGIHTTPRequestHandler(request, client_address, server)
CGIHTTPRequestHandler类的属性

属性 说明
cgi_directories 默认目录并描述了包含CGI脚本的目录。[‘/cgi-bin’, ‘/htbin’]

CGIHTTPRequestHandler类的方法

方法 说明
do_POST() 此方法提供’POST’请求类型,仅允许CGI脚本使用。
尝试POST到非CGI URL时,输出错误501“只能POST到CGI脚本”

3.4 -m 参数

http.server也可以使用-m 带参数的解释器开关直接调用。

  1. python -m http.server 8000 #端口
  2. python -m http.server 8000 --bind 127.0.0.1 #绑定主机
  3. python -m http.server --directory /tmp/ #指定目录
  4. python -m http.server --cgi 8000 #指定CGI

四、client模块

Client模块定义了实现HTTP和HTTPS协议客户端的类(ps:仅当Python使用SSL支持(通过ssl模块)编译时,HTTPS支持才可用)
语法格式
class http.client.HTTPConnection(host, port=None, [timeout, ]source_address=None, blocksize=8192)
如果没有指定端口,使用默认的HTTP端口(80)
如果给出了可选的超时参数,那么阻塞操作(如连接尝试)将在几秒钟后超时(如果未给出,则使用全局默认超时设置)
可选的source_address参数可以是(主机,端口)的元组,用作创建HTTP连接的源地址
可选的blocksize参数以字节为单位设置缓冲区大小,用于发送类似文件的消息正文

  1. ###以下调用全部创建在相同主机和端口上连接到服务器的实例
  2. import http.client
  3. h1 = http.client.HTTPConnection('www.python.org')
  4. h2 = http.client.HTTPConnection('www.python.org:80')
  5. h3 = http.client.HTTPConnection('www.python.org', 80)
  6. h4 = http.client.HTTPConnection('www.python.org', 80, timeout=10)

4.1 HttpConnection的对象

HttpConnection类的对象的方法

方法 说明
HTTPConnection.request() 向服务器发送请求
HTTPConnection.getresponse() 返回服务器的状态
HTTPConnection.set_debuglevel() 设置调试级别。缺省调试级别为0,表示不打印任何调试输出。大于任何值0将导致所有当前定义的调试输出打印到stdout
HTTPConnection.set_tunnel(host,port = None,headers = None ) 设置HTTP连接隧道的主机和端口,允许代理服务器连接
host和port参数指定隧道连接的端点(即CONNECT请求中包含的地址,而不是代理服务器的地址)。
headers参数应该是要与CONNECT请求一起发送的额外HTTP标头的映射。
HTTPConnection.connect() 连接到创建对象时指定的服务器
HTTPConnection.close() 关闭与服务器的连接
HTTPConnection.blocksize() 用于发送类似文件的消息正文的缓冲区大小(以字节为单位)
HTTPConnection.putrequest(method,url,skip_host = False,skip_accept_encoding = False ) 写入客户端请求表头的第一行
HTTPConnection.putheader(header, argument[, …]) 写入客户端请求表头的表头行
每一行:header、冒号(:)、一个空白及argument
HTTPConnection.endheaders(message_body=None, *, encode_chunked=False) 将空白行发送到服务器,以指示标头结尾。
message_body参数可用于传递与请求关联的消息正文
HTTPConnection.send(data) 调用endheaders()后将数据发送到服务器

4.2 HTTPResponse的对象

一个HTTPResponse实例包含从服务器的HTTP响应,它提供对请求表头和实体主体的访问。
HTTPResponse类的对象的方法

方法 说明
HTTPResponse.read([ amt ] ) 读取并返回响应正文,或直至下一个amt字节
HTTPResponse.readinto(b ) 将响应主体的下一个len(b)字节读取到缓冲区b中,返回读取的字节数。
HTTPResponse.getheader(name,default = None ) 返回标题名称的值
HTTPResponse.getheaders() 返回(头,值)元组的列表
HTTPResponse.fileno() 返回fileno基础套接字的
HTTPResponse.version 服务器使用的HTTP协议版本
HTTP / 1.0为10,HTTP / 1.1为11
HTTPResponse.url 检索到的资源的URL,通常用于确定是否遵循了重定向
HTTPResponse.headers email.message.EmailMessage实例形式的响应头
HTTPResponse.status 服务器返回的状态码
HTTPResponse.reason 服务器返回的原因短语
HTTPResponse.debuglevel 调试钩子
如果debuglevel大于零,则在读取和解析响应时,消息将被打印到stdout。
HTTPResponse.closed 为True,则流是关闭的
  1. import http.client
  2. conn = http.client.HTTPConnection("www.baidu.com")
  3. conn.request("GET", "/")
  4. r1 = conn.getresponse() #返回(头,值)元组的列表
  5. print("状态码: ",r1.status)
  6. print("原因:",r1.reason)
  7. # while chunk := r1.read(200):
  8. # print(repr(chunk))
  9. date1 = r1.read(200) #读取并返回响应正文,
  10. print("响应正文200个字符",repr(date1)) #将会输出读取到的全部内容
  11. #repr() 函数将对象转化为供解释器读取的形式
  12. conn = http.client.HTTPConnection("docs.python.org")
  13. conn.request("GET", "/parrot.spam")
  14. r2 = conn.getresponse()
  15. print("状态码: ",r2.status)
  16. print("原因:",r2.reason)
  17. date2 = r2.read(200)
  18. print("响应正文200个字符",repr(date2))
  19. conn.close()
  20. ##结果
  21. 状态码: 200
  22. 原因: OK
  23. 响应正文200个字符 b'<!DOCTYPE html><!--STATUS OK-->\r\n<html>\r\n<head>\r\n\t<meta http-equiv="content-type" content="text/html;charset=utf-8">\r\n\t<meta http-equiv="X-UA-Compatible" content="IE=Edge">\r\n\t<link rel="dns-prefetch" '
  24. 状态码: 301
  25. 原因: Moved Permanently
  26. 响应正文200个字符 b''
  1. import http.client
  2. ##指定主机名称
  3. url = 'news.baidu.com/'
  4. ##连接到主机
  5. host = http.client.HTTPConnection(url)
  6. ##写入客户端要求表头的第一行
  7. host.request("GET",'/')
  8. ##获取服务器的响应
  9. r1 = host.getresponse()
  10. ##打印服务器返回的状态
  11. print(r1.status,r1.reason)
  12. ##将file对象的内容保存在新文件中
  13. file = open("E:\\pythonstduy\\1_6.html","w")
  14. ##读取网页内容,以utf-8方式保存
  15. str = r1.read().decode("utf-8")
  16. ##寻找文本
  17. print(str.find("mlive"))
  18. ##写入文件并替换”\xbb“为空字符
  19. file.write(str.replace('\xbb',' '))
  20. ##关闭文件
  21. file.close()
  22. host.close()
  23. ##结果
  24. 200 OK
  25. -1

image.png