miniweb开发
#web界面
# 1、导入模块
import socket
import threading
import framework
# 2、定义一个HTTPWebServer类
class HttpWebServer(object):
# 3、定义__init__初始化方法
def __init__(self):
# 4、创建套接字对象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 5、绑定端口(前端要求必须是8000)
tcp_server_socket.bind(('', 8000))
# 6、设置监听
tcp_server_socket.listen(128)
# 7、把tcp_server_socket赋值给自身属性
self.tcp_server_socket = tcp_server_socket
@staticmethod
def handle_client_request(conn_socket):
# 10、接收客户端发送过来的数据(HTTP数据)
client_request_data = conn_socket.recv(1024).decode('utf-8')
if len(client_request_data) > 0:
print(client_request_data)
# 获取Ajax发送过来的所有HTTP请求数据
request_data = client_request_data.split('\r\n')
# print(request_data)
# pop()方法,主要功能,弹出列表中的最后一个元素,但是如果给定一个索引,其就只弹出指定索引的那个元素
request_line = request_data.pop(0)
request_line_data = request_line.split(' ') # ['GET','/index','HTTP/1.1']
# print(request_data)
# 11、把请求头信息,都放入字典中{'Host':'127.0.0.1:8000'}
request_header = {}
# ['Host: 127.0.0.1:8000', '']
for header in request_data:
if header == '':
continue
# request_header[key] = value
request_header[header.split(": ")[0]] = header.split(": ")[1]
# 12、获取请求资源路径
request_path = request_line_data[1]
# print(request_path)
# 13、获取用户请求的参数,如/detail?id=100
request_query = request_path.split('?')
if len(request_query) > 1:
request_path = request_query[0] # /detail
query_str = request_query[1] # id=100
else:
query_str = None
# 14、把获取的请求路径、请求参数以及请求头组装成字典格式
requests = {
'path': request_path,
'query_str': query_str,
'header': request_header
}
# 15、编写符合wsgi协议的数据包(等待发送给Web应用程序 => 爱读书实际代码)
env = {
'request_path': request_path,
'requests': requests
}
# env = {
# 'request_path': '/index或/detail',
# 'requests': {
# 'path': '/index或/detail',
# 'query_str': 'id=100',
# 'header': {'Host':'127.0.0.1:8000', 'User-Agent':'Chrome/92'}
# }
# }
# 16、响应数据给浏览器客户端
response_line = 'HTTP/1.1 200 OK\r\n'
# 响应头
response_header = 'Server:pwb\r\nAccess-Control-Allow-Credentials:true\r\nAccess-Control-Allow-Origin:*\r\nAccess-Control-Allow-Methods:GET, POST, PUT\r\nAccess-Control-Allow-Headers:X-Custom-Header\r\n'
# 响应体(关键:到底应该返回什么内容给前端 => JSON格式的数据包)
response_body = framework.handle_request(env)
# 响应数据
response_data = (response_line + response_header + '\r\n' + response_body).encode('utf-8')
# 16、返回数据给客户端
conn_socket.send(response_data)
# 17、关闭客户端连接
conn_socket.close()
def start(self):
while True:
# 8、接收客户端连接请求
conn_socket,ip_port = self.tcp_server_socket.accept()
# 9、创建子线程
sub_thread = threading.Thread(target=self.handle_client_request, args=(conn_socket, ))
sub_thread.setDaemon(True)
sub_thread.start()
if __name__ == '__main__':
web_server = HttpWebServer() # 得到套接字对象
web_server.start() # 开始工作,准备接收客户端请求(HTTP)
#framework界面
# 导入pymysql模块
import pymysql
import json
import logging
def index(env):
# 创建连接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='root', database='book', charset='utf8')
# 获取游标
cursor = conn.cursor()
# 执行SQL语句
sql = "select * from bookinfo;"
cursor.execute(sql)
# print(cursor.fetchall()) => ((), (), ()) => [{}, {}, {}] => json.dumps => json_str
stock_data = cursor.fetchall()
center_data_list = []
for data in stock_data:
center_data_list.append({
"id": data[0],
"name": data[1],
"auth": data[2],
"img_url": data[3],
"rank": data[4]
})
# 把以上得到的图书信息转换为JSON格式的字符串
json_str = json.dumps(center_data_list, ensure_ascii=False)
# 关闭游标与连接
cursor.close()
conn.close()
# 返回数据给web.py
return json_str
def detail(env):
# 返回客户端请求的图书id编号(如id=100)
query_str = env['requests']['query_str']
# 创建连接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='root', database='book', charset='utf8')
# 获取游标
cursor = conn.cursor()
# 执行SQL语句
sql = "select * from bookinfo where %s;" % query_str
cursor.execute(sql)
row = cursor.fetchone()
data_dict = {
"id": row[0],
"name": row[1],
"auth": row[2],
"img_url": row[3],
"read": row[5],
"comment": row[6],
"score": row[8],
"content": row[7],
"synopsis": row[9]
}
# json.dumps只能转换列表和字典
json_str = json.dumps(data_dict, ensure_ascii=False)
# 把图书的阅读量进行+1操作
sql = "update bookinfo set bread=bread+1 where %s" % query_str
cursor.execute(sql)
conn.commit()
# 进行数据埋点
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
stream=open('log.txt', 'a', encoding='utf-8'))
logging.info({
# 记录用户行为
'bookClick': {
# 获取用户设备信息
"identification": env['requests']['header']['User-Agent'].split(' ')[-2],
# 获取客户端IP
# 获取用户跳转路径
"entrance": env['requests']['header']['Referer'],
# 获取图书名称与阅读量
"bookname": data_dict['name'],
"read": data_dict["read"]
}
})
# 关闭游标与连接
cursor.close()
conn.close()
# 返回JSON格式数据给客户端浏览器
return json_str
# 定义路由列表(Django框架)
route_list = [
('/index', index),
('/detail', detail)
]
def handle_request(env):
request_path = env['request_path']
# request_path = '/detail'
for path,func in route_list:
if request_path == path:
return func(env)
else:
return '404 Not Found'
2021-08-27
最新推荐文章于 2025-04-11 12:05:25 发布