个人选股

  • 一、数据准备
  • 二、使用字典完成路由功能
  • 三、用装饰器-字典完成路由功能
  • 四、添加伪静态
  • 五、添加mysql数据查询功能
  • 六、让路由支持正则-添加股票
  • 七、个人中心添加删除股票和修改备注
  • 八、url解码
  • 九、添加日志功能
  • 十、总结知识点

一、数据准备

  1. 效果:
    首页:

    个人中心:

  2. 目录结构:

    D:.
    │  log.txt
    │  mysql数据准备.sql
    │  README.md
    │  run.sh
    │  web-server.py
    │  web_server.conf
    │
    ├─dynamic
    │  │  mini_frame.py
    │  │  __init__.py
    │  │
    │  └─__pycache__
    │          mini_frame.cpython-37.pyc
    │          __init__.cpython-37.pyc
    │
    ├─static
    │  ├─css
    │  │      bootstrap-responsive.css
    │  │      bootstrap-responsive.min.css
    │  │      bootstrap.css
    │  │      bootstrap.min.css
    │  │
    │  ├─img
    │  │      glyphicons-halflings-white.png
    │  │      glyphicons-halflings.png
    │  │
    │  └─js
    │          bootstrap.js
    │          bootstrap.min.js
    │          jquery.js
    │          jquery.min.js
    │          jquery.min.map
    │
    ├─templates
    │      center.html
    │      index.html
    │      update.html
    
  3. center.html

    <!DOCTYPE html>
    <html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>个人中心 - 个人选股系统 V5.87</title><link href="/css/bootstrap.min.css" rel="stylesheet"></head><body>
    <div class="navbar navbar-inverse navbar-static-top "><div class="container"><div class="navbar-header"><button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="#" class="navbar-brand">选股系统</a></div><div class="collapse navbar-collapse" id="mymenu"><ul class="nav navbar-nav"><li ><a href="/index.html">股票信息</a></li><li class="active"><a href="/center.html">个人中心</a></li></ul></div></div>
    </div><div class="container"><div class="container-fluid"><table class="table table-hover" style="background-color: #f1fde1"><tr style="background-color:#a6e22b;"><th>股票代码</th><th>股票简称</th><th>涨跌幅</th><th>换手率</th><th>最新价(元)</th><th>前期高点</th><th style="color:red">备注信息</th><th>修改备注</th><th>删除</th></tr>                    </table>{%content%} </div></div><script  src="/js/jquery.js"></script><!-- <script src="/js/bootstrap.min.js"></script> --><script type="text/javascript">$(document).ready(function(){$("input[name='toDel']").each(function(){var currentAdd = $(this);var code = $(this).attr("systemIdVaule");          currentAdd.click(function(){code = $(this).attr("systemIdVaule");// alert("/del/" + code + ".html");$.get("/del/" + code + ".html", function(data, status){alert("数据: " + data + "\n状态: " + status);window.location.reload();});});});});</script></body>
    </html>
    
  4. index.html

    <!DOCTYPE html>
    <html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>首页 - 个人选股系统 V5.87</title><link href="/css/bootstrap.min.css" rel="stylesheet"></head>
    <body>
    <div class="navbar navbar-inverse navbar-static-top "><div class="container"><div class="navbar-header"><button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="#" class="navbar-brand">选股系统</a></div><div class="collapse navbar-collapse" id="mymenu"><ul class="nav navbar-nav"><li class="active"><a href="/index.html">股票信息</a></li><li><a href="/center.html">个人中心</a></li></ul></div></div>
    </div><div class="container"><div class="container-fluid"><table class="table table-hover" style="background-color: #f1fde1"><tr style="background-color:#a6e22b;"><th>序号</th><th>股票代码</th><th>股票简称</th><th>涨跌幅</th><th>换手率</th><th>最新价(元)</th><th>前期高点</th><th>前期高点日期</th><th>添加自选</th></tr>          </table>{%content%}</div></div><script  src="/js/jquery.js"></script><!-- <script src="/js/bootstrap.min.js"></script> --><script type="text/javascript">$(document).ready(function(){$("input[name='toAdd']").each(function(){var currentAdd = $(this);var code = $(this).attr("systemIdVaule");          currentAdd.click(function(){code = $(this).attr("systemIdVaule");// alert("/add/" + code + ".html");$.get("/add/" + code + ".html", function(data, status){alert("数据: " + data + "\n状态: " + status);window.location.reload();});});});});</script></body>
    </html>
    
  5. update.html

    <!DOCTYPE html>
    <html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>首页 - 个人选股系统 V5.87</title><link href="/css/bootstrap.css" rel="stylesheet"><script  src="/js/jquery.js"></script><!-- <script src="/js/bootstrap.js"></script> --><script>$(document).ready(function(){$("#update").click(function(){var item = $("#note_info").val();// alert("/update/{%code%}/" + item + ".html");$.get("/update/{%code%}/" + item + ".html", function(data, status){alert("数据: " + data + "\n状态: " + status);self.location='/center.html';});});});</script></head><body>
    <div class="navbar navbar-inverse navbar-static-top "><div class="container"><div class="navbar-header"><button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="#" class="navbar-brand">选股系统</a></div><div class="collapse navbar-collapse" id="mymenu"><ul class="nav navbar-nav"><li><a href="/index.html">股票信息</a></li><li><a href="/center.html">个人中心</a></li></ul></div></div>
    </div><div class="container"><div class="container-fluid"><div class="input-group"><span class="input-group-addon">正在修改:</span><span class="input-group-addon">{%code%}</span><input id="note_info" type="text" class="form-control" aria-label="Amount (to the nearest dollar)" value="{%note_info%}"><!-- <span id="update" class="input-group-addon" style="cursor: pointer">修改</span> --><a id = "update"type="button" class="btn btn-default btn-xs"> <span aria-hidden="true">⇋</span> 修改 </a></div></div></div></body>
    </html>
    

5.数据库的创建

-- 创建数据库create database stock_db charset=utf8;
-- 创建数据表-- info 表格结构-- mysql> desc info;-- +----------+---------------+------+-----+---------+----------------+-- | Field    | Type          | Null | Key | Default | Extra          |-- +----------+---------------+------+-----+---------+----------------+-- | id       | int unsigned  | NO   | PRI | NULL    | auto_increment |-- | code     | varchar(6)    | NO   |     | NULL    |                |-- | short    | varchar(10)   | NO   |     | NULL    |                |-- | chg      | varchar(10)   | NO   |     | NULL    |                |-- | turnuver | varchar(255)  | NO   |     | NULL    |                |-- | price    | decimal(10,2) | NO   |     | NULL    |                |-- | highs    | decimal(10,2) | NO   |     | NULL    |                |-- | time     | date          | YES  |     | NULL    |                |-- +----------+---------------+------+-----+---------+----------------+-- 8 rows in set (0.00 sec)create table info (id int(10) unsigned auto_increment not null primary key,code varchar(6) not null,short varchar(10) not null,chg varchar(10) not null,turnuver varchar(255) not null,price decimal(10, 2) not null,highs decimal(10, 2) not null,time date);-- focus 表格结构-- mysql> desc focus;-- +----------+--------------+------+-----+---------+----------------+-- | Field    | Type         | Null | Key | Default | Extra          |-- +----------+--------------+------+-----+---------+----------------+-- | id       | int unsigned | NO   | PRI | NULL    | auto_increment |-- | not_info | varchar(200) | YES  |     | NULL    |                |-- | info_id  | int unsigned | YES  | MUL | NULL    |                |-- +----------+--------------+------+-----+---------+----------------+-- 3 rows in set (0.00 sec)create table focus(id int(10) unsigned auto_increment not null primary key,not_info varchar(200),info_id int(10) unsigned);-- 添加外键alter table focus add foreign key (info_id) references info(id);-- 添加数据INSERT INTO `info` VALUES (1,'000007','全新好','10.01%','4.40%',16.05,14.60,'2019-03-18'),(2,'000036','华联控股','10.04%','10.80%',11.29,10.26,'2019-03-20'),(3,'000039','中集集团','1.35%','1.78%',18.07,18.06,'2019-02-28'),(4,'000050','深天马A','4.38%','4.65%',22.86,22.02,'2019-03-19'),(5,'000056','皇庭国际','0.39%','0.65%',12.96,12.91,'2019-03-20'),(6,'000059','华锦股份','3.37%','7.16%',12.26,12.24,'2018-12-11'),(7,'000060','中金岭南','1.34%','3.39%',12.08,11.92,'2019-03-20'),(8,'000426','兴业矿业','0.41%','2.17%',9.71,9.67,'2019-03-20'),(9,'000488','晨鸣纸业','6.30%','5.50%',16.37,15.59,'2019-03-10'),(10,'000528','柳工','1.84%','3.03%',9.42,9.33,'2019-03-19'),(11,'000540','中天金融','0.37%','5.46%',8.11,8.08,'2019-03-20'),(12,'000581','威孚高科','3.49%','3.72%',27.00,26.86,'2019-02-26'),(13,'000627','天茂集团','5.81%','12.51%',10.93,10.33,'2019-03-20'),(14,'000683','远兴能源','6.42%','21.27%',3.48,3.29,'2019-03-19'),(15,'000703','恒逸石化','0.24%','1.65%',16.92,16.88,'2019-03-20'),(16,'000822','山东海化','6.60%','8.54%',9.05,8.75,'2019-03-06'),(17,'000830','鲁西化工','1.38%','4.80%',7.36,7.26,'2019-03-20'),(18,'000878','云南铜业','1.26%','3.23%',14.50,14.47,'2019-03-19'),(19,'000905','厦门港务','5.44%','10.85%',15.90,15.60,'2018-12-20'),(20,'000990','诚志股份','0.53%','1.00%',16.99,16.90,'2019-03-20'),(21,'002019','亿帆医药','1.19%','2.81%',17.05,16.85,'2019-03-20'),(22,'002078','太阳纸业','2.05%','1.90%',8.45,8.29,'2019-03-19'),(23,'002092','中泰化学','7.25%','6.20%',15.53,14.48,'2019-03-20'),(24,'002145','中核钛白','2.43%','7.68%',6.75,6.61,'2019-03-19'),(25,'002285','世联行','8.59%','5.66%',9.23,8.50,'2019-03-20'),(26,'002311','海大集团','1.13%','0.24%',18.81,18.63,'2019-03-19'),(27,'002460','赣锋锂业','9.41%','9.00%',63.70,58.22,'2019-03-20'),(28,'002466','天齐锂业','3.62%','3.66%',68.44,66.05,'2019-03-20'),(29,'002470','金正大','2.30%','0.99%',8.00,7.82,'2019-03-20'),(30,'002496','辉丰股份','3.15%','4.29%',5.24,5.08,'2018-12-10'),(31,'002497','雅化集团','0.38%','12.36%',13.10,13.05,'2019-03-20'),(32,'002500','山西证券','0.44%','3.70%',11.49,11.44,'2019-03-20'),(33,'002636','金安国纪','2.70%','11.59%',19.80,19.42,'2019-03-19'),(34,'300032','金龙机电','0.66%','0.72%',15.28,15.18,'2019-03-20'),(35,'300115','长盈精密','0.60%','0.59%',33.50,33.41,'2019-03-19'),(36,'300268','万福生科','-10.00%','0.27%',31.77,13.57,'2018-12-10'),(37,'300280','南通锻压','3.31%','0.66%',32.20,32.00,'2018-12-11'),(38,'300320','海达股份','0.28%','0.82%',18.26,18.21,'2019-03-20'),(39,'300408','三环集团','1.69%','0.81%',23.42,23.17,'2019-03-19'),(40,'300477','合纵科技','2.84%','5.12%',22.10,22.00,'2019-03-12'),(41,'600020','中原高速','5.46%','4.48%',5.60,5.31,'2019-03-20'),(42,'600033','福建高速','1.01%','1.77%',4.00,3.99,'2019-02-26'),(43,'600066','宇通客车','4.15%','1.49%',23.08,23.05,'2019-02-13'),(44,'600067','冠城大通','0.40%','2.97%',7.56,7.53,'2019-03-20'),(45,'600110','诺德股份','2.08%','4.26%',16.16,15.83,'2019-03-20'),(46,'600133','东湖高新','9.65%','21.74%',13.64,12.44,'2019-03-20'),(47,'600153','建发股份','3.65%','2.03%',13.35,13.21,'2019-03-10'),(48,'600180','瑞茂通','2.20%','1.07%',14.86,14.54,'2019-03-20'),(49,'600183','生益科技','6.94%','4.06%',14.94,14.12,'2019-03-19'),(50,'600188','兖州煤业','1.53%','0.99%',14.56,14.43,'2019-03-19'),(51,'600191','华资实业','10.03%','11.72%',15.80,14.36,'2019-03-20'),(52,'600210','紫江企业','6.03%','10.90%',6.68,6.30,'2019-03-20'),(53,'600212','江泉实业','1.39%','1.78%',10.20,10.15,'2019-03-19'),(54,'600225','*ST松江','4.96%','2.47%',5.71,5.61,'2018-12-13'),(55,'600230','沧州大化','5.74%','13.54%',43.26,40.91,'2019-03-20'),(56,'600231','凌钢股份','2.79%','3.77%',3.68,3.60,'2019-03-19'),(57,'600291','西水股份','10.02%','9.23%',34.71,31.55,'2019-03-20'),(58,'600295','鄂尔多斯','4.96%','12.62%',16.51,15.73,'2019-03-20'),(59,'600303','曙光股份','8.37%','14.53%',11.53,10.64,'2019-03-20'),(60,'600308','华泰股份','1.12%','2.66%',6.30,6.26,'2019-03-19'),(61,'600309','万华化学','0.03%','1.78%',31.81,31.80,'2019-03-20'),(62,'600352','浙江龙盛','0.39%','1.85%',10.32,10.28,'2019-03-20'),(63,'600354','敦煌种业','7.89%','18.74%',9.44,8.75,'2019-03-20'),(64,'600408','安泰集团','1.98%','3.38%',4.13,4.12,'2018-12-13'),(65,'600409','三友化工','0.62%','3.78%',11.36,11.29,'2019-03-20'),(66,'600499','科达洁能','0.46%','3.94%',8.84,8.80,'2019-03-20'),(67,'600508','上海能源','3.26%','2.99%',13.32,13.01,'2019-03-19'),(68,'600563','法拉电子','0.32%','1.36%',53.67,53.50,'2019-03-20'),(69,'600567','山鹰纸业','0.76%','2.85%',3.98,3.96,'2019-03-19'),(70,'600585','海螺水泥','0.45%','0.61%',24.51,24.44,'2019-03-19'),(71,'600668','尖峰集团','4.35%','6.43%',18.70,18.36,'2018-12-13'),(72,'600688','上海石化','2.72%','0.91%',6.80,6.74,'2019-02-01'),(73,'600729','重庆百货','5.70%','3.34%',27.45,27.13,'2019-02-28'),(74,'600739','辽宁成大','3.30%','3.50%',19.74,19.11,'2019-03-20'),(75,'600779','水井坊','3.85%','2.77%',29.39,28.30,'2019-03-20'),(76,'600781','辅仁药业','8.61%','4.16%',23.46,21.89,'2019-01-02'),(77,'600801','华新水泥','4.00%','10.15%',12.99,12.49,'2019-03-20'),(78,'600846','同济科技','2.06%','17.41%',9.39,9.26,'2018-12-13'),(79,'600884','杉杉股份','1.08%','3.53%',20.67,20.45,'2019-03-20'),(80,'600966','博汇纸业','2.89%','5.54%',6.41,6.28,'2019-03-19'),(81,'600971','恒源煤电','2.36%','8.81%',12.16,11.88,'2019-03-20'),(82,'601012','隆基股份','0.76%','1.30%',19.93,19.78,'2019-03-20'),(83,'601100','恒立液压','4.78%','0.92%',19.31,18.97,'2019-03-13'),(84,'601101','昊华能源','4.03%','6.06%',11.10,10.80,'2019-03-19'),(85,'601216','君正集团','2.16%','2.26%',5.20,5.10,'2018-12-17'),(86,'601666','平煤股份','2.81%','6.14%',6.96,6.77,'2019-03-20'),(87,'601668','中国建筑','2.39%','1.42%',10.70,10.45,'2019-03-20'),(88,'601678','滨化股份','0.13%','2.47%',7.92,7.91,'2019-03-20'),(89,'601918','新集能源','1.23%','3.11%',4.93,4.92,'2019-03-19'),(90,'603167','渤海轮渡','2.77%','3.34%',11.87,11.61,'2018-12-13'),(91,'603369','今世缘','3.34%','2.13%',14.24,13.78,'2019-03-20'),(92,'603589','口子窖','3.99%','1.84%',39.37,39.04,'2019-02-26'),(93,'603799','华友钴业','2.38%','7.19%',67.46,65.89,'2019-03-20'),(94,'603993','洛阳钼业','2.94%','2.50%',7.36,7.16,'2019-03-19');INSERT INTO `focus` VALUES (1,'先试一试',30),(2,'非常稳',38),(3,'一般般',78),(12,'不咋地',80),(17,'',23);-- 查询select i.code, i.short, i.chg, i.turnuver, i.price, i.highs, f.not_info from info as i inner join focus as f on i.id=f.info_id;

二、使用字典完成路由功能

  1. web-server.py

    """使用面向对象的方法来做多进程的web server 继承了动态的解析功能
    当请求文件结尾以.py结尾的为动态网页"""import socket
    import re
    import multiprocessing
    import time
    # import dynamic.mini_frame
    import sys
    import reclass WSGIServer(object):"""服务器对象"""def __init__(self, port, app, static_path):# 创建套接字self.tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 绑定ip和portself.tcp_server.bind(("", port))# 设置成监听模式self.tcp_server.listen(128)self.app = appself.static_path = static_pathdef service_client(self, new_socket):# 接受数据data = new_socket.recv(1024).decode("utf-8")# print(data.decode("utf-8"))data_list = data.splitlines()# print(data_list[0])# 正则匹配出文件名   'GET /img/home/tour8.jpg HTTP/1.1',ret = re.match(r"[^/]+(/[^ ]*)",data_list[0])print(ret)file_name = ""if ret:file_name = ret.group(1)print(file_name)if file_name == "/":file_name = "/index.py"if not file_name.endswith('.py'):try:# 打开文件# f = open("./static/" + file_name, "rb")f = open(self.static_path + file_name, "rb")except:response = "HTTP/1.1 404 NOT FOUND\r\n"response += "\r\n"response += "Not Found"# 发送文件 headernew_socket.send(response.encode("utf-8"))else:# 传递数据response = "HTTP:/1.1 200 OK\r\n"response += "\r\n"data_contend = f.read()f.close()# 发送文件 headernew_socket.send(response.encode("utf-8"))# 发送文件bodynew_socket.send(data_contend)else:# 以.py结尾的则为动态的获取的页面# body = "nihao : %s" % time.ctime()envs = dict()envs["PATH_INFO"] = file_name# print(envs)# 传递一个字典{"PATH_INFO":file_name}# body = dynamic.mini_frame.application(envs, self.set_response_header)body = self.app(envs, self.set_response_header)header = "HTTP:/1.1 %s\r\n" % self.statusfor temp in self.hearers:header += "%s:%s\r\n" % (temp[0], temp[1])header += "\r\n"response = header + body# 发送消息new_socket.send(response.encode("utf-8"))# 关闭套接字new_socket.close()def set_response_header(self, status, headers):self.status = statusself.hearers = [("server:","mini_server v8.8")]self.hearers += headersdef run_forerver(self):"""使程序一直运行"""while True:# 等待客户端连接new_client, addr = self.tcp_server.accept()p = multiprocessing.Process(target=self.service_client, args=(new_client, ))# 接受客户端的消息  回复客户端的消息# service_client(new_client)p.start()new_client.close()  # 多进程中会复制一份这个变量,所以要在主进程中也要关闭self.tcp_server.close()def main():"""控制整体流程 --> 创建一个对象 --> 调用这个对象的run_forerver方法"""# 执行代码的操作  python server.py 7780 mini_frame:application   -->端口名和框架中的函数if len(sys.argv) == 3:try:port = int(sys.argv[1])  # 7780frame_app_name = sys.argv[2]  # mini_frame:applicationexcept Exception as ret:print("端口错误")returnelse:print("请用以下方式执行程序:")print("python m8-server.py 7780 mini_frame:application   -->  程序后加入端口号和框架中的main函数名")return  # 结束函数# mini_frame:applicationret = re.match(r"([^:]+):(.*)", frame_app_name)if ret:frame_name = ret.group(1)  # mini_frameapp_name = ret.group(2)  # applicationelse:print("请用以下方式执行程序:")print("python m8-server.py 7780 mini_frame:application   -->  程序后加入端口号和框架中的main函数名")return  # 结束函数# 读取配置文件中的信息# {#     "static_path":"./static",#     "dynamic_path":"./dynamic"# }with open("./web_server.conf") as f:conf_info = eval(f.read())# print(conf_info)sys.path.append(conf_info["dynamic_path"])# import frame_name  -->  找的是 frame_name.pyframe = __import__(frame_name)  # 导入函数  以变量名的函数  返回值标记了这个导入的模板app = getattr(frame, app_name)  # 此时app指向了./dynamic/mini_frame.applicationwsgi_server = WSGIServer(port, app, conf_info["static_path"])wsgi_server.run_forerver()if __name__ == "__main__":main()
    
  2. mini_frame.py

    # 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 比最初的版本好的是  -->  不用很多的if语句
    import timedef index():with open("./templates/index.html", encoding='utf-8') as f:return f.read()def center():with open("./templates/center.html", encoding='utf-8') as f:return f.read()URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }def application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]"""if file_name == "/index.py":return index()elif file_name == "/center.py":return center()else:return ' 中国 hello word time: %s' % time.ctime()"""func = URL_FUNC_DICT[file_name]return func()

三、用装饰器-字典完成路由功能

  1. 这里只需要修改mini_frame的代码

  2. mini_frame.py

    # 版本2. 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 版本1. 比最初的版本好的是  -->  不用很多的if语句
    # 版本3. 用装饰器 + 字典完成  -->  比只用字典好在不用手动王字典中添加
    import time"""
    URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }
    """
    URL_FUNC_DICT = dict()def route(url):def set_func(func):URL_FUNC_DICT[url] = funcdef call_func(*args, **kwargs):return func(*args, **kwargs)return call_funcreturn set_func@route("/index.py")
    def index():with open("./templates/index.html", encoding='utf-8') as f:return f.read()@route("/center.py")
    def center():with open("./templates/center.html", encoding='utf-8') as f:return f.read()def application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]"""if file_name == "/index.py":return index()elif file_name == "/center.py":return center()else:return ' 中国 hello word time: %s' % time.ctime()"""try:# func = URL_FUNC_DICT[file_name]# return func()return URL_FUNC_DICT[file_name]()except Exception as ret:return "出现异常: %s" % str(ret)

四、添加伪静态

  1. 将webserver.py文件中的判断.py文件改成判断是否以,html结尾

  2. 修改mini-frame.py文件

  3. web-server.py ----- 后面就不变了

    """使用面向对象的方法来做多进程的web server 继承了动态的解析功能
    当请求文件结尾以.html结尾的为动态网页"""import socket
    import re
    import multiprocessing
    import time
    # import dynamic.mini_frame
    import sys
    import reclass WSGIServer(object):"""服务器对象"""def __init__(self, port, app, static_path):# 创建套接字self.tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 绑定ip和portself.tcp_server.bind(("", port))# 设置成监听模式self.tcp_server.listen(128)self.app = appself.static_path = static_pathdef service_client(self, new_socket):# 接受数据data = new_socket.recv(1024).decode("utf-8")# print(data.decode("utf-8"))data_list = data.splitlines()# print(data_list[0])# 正则匹配出文件名   'GET /img/home/tour8.jpg HTTP/1.1',ret = re.match(r"[^/]+(/[^ ]*)",data_list[0])print(ret)file_name = ""if ret:file_name = ret.group(1)print(file_name)if file_name == "/":file_name = "/index.html"if not file_name.endswith('.html'):try:# 打开文件# f = open("./static/" + file_name, "rb")f = open(self.static_path + file_name, "rb")except:response = "HTTP/1.1 404 NOT FOUND\r\n"response += "\r\n"response += "Not Found"# 发送文件 headernew_socket.send(response.encode("utf-8"))else:# 传递数据response = "HTTP:/1.1 200 OK\r\n"response += "\r\n"data_contend = f.read()f.close()# 发送文件 headernew_socket.send(response.encode("utf-8"))# 发送文件bodynew_socket.send(data_contend)else:# 以.py结尾的则为动态的获取的页面# body = "nihao : %s" % time.ctime()envs = dict()envs["PATH_INFO"] = file_name# print(envs)# 传递一个字典{"PATH_INFO":file_name}# body = dynamic.mini_frame.application(envs, self.set_response_header)body = self.app(envs, self.set_response_header)header = "HTTP:/1.1 %s\r\n" % self.statusfor temp in self.hearers:header += "%s:%s\r\n" % (temp[0], temp[1])header += "\r\n"response = header + body# 发送消息new_socket.send(response.encode("utf-8"))# 关闭套接字new_socket.close()def set_response_header(self, status, headers):self.status = statusself.hearers = [("server:","mini_server v8.8")]self.hearers += headersdef run_forerver(self):"""使程序一直运行"""while True:# 等待客户端连接new_client, addr = self.tcp_server.accept()p = multiprocessing.Process(target=self.service_client, args=(new_client, ))# 接受客户端的消息  回复客户端的消息# service_client(new_client)p.start()new_client.close()  # 多进程中会复制一份这个变量,所以要在主进程中也要关闭self.tcp_server.close()def main():"""控制整体流程 --> 创建一个对象 --> 调用这个对象的run_forerver方法"""# 执行代码的操作  python server.py 7780 mini_frame:application   -->端口名和框架中的函数if len(sys.argv) == 3:try:port = int(sys.argv[1])  # 7780frame_app_name = sys.argv[2]  # mini_frame:applicationexcept Exception as ret:print("端口错误")returnelse:print("请用以下方式执行程序:")print("python m8-server.py 7780 mini_frame:application   -->  程序后加入端口号和框架中的main函数名")return  # 结束函数# mini_frame:applicationret = re.match(r"([^:]+):(.*)", frame_app_name)if ret:frame_name = ret.group(1)  # mini_frameapp_name = ret.group(2)  # applicationelse:print("请用以下方式执行程序:")print("python m8-server.py 7780 mini_frame:application   -->  程序后加入端口号和框架中的main函数名")return  # 结束函数# 读取配置文件中的信息# {#     "static_path":"./static",#     "dynamic_path":"./dynamic"# }with open("./web_server.conf") as f:conf_info = eval(f.read())# print(conf_info)sys.path.append(conf_info["dynamic_path"])# import frame_name  -->  找的是 frame_name.pyframe = __import__(frame_name)  # 导入函数  以变量名的函数  返回值标记了这个导入的模板app = getattr(frame, app_name)  # 此时app指向了./dynamic/mini_frame.applicationwsgi_server = WSGIServer(port, app, conf_info["static_path"])wsgi_server.run_forerver()if __name__ == "__main__":main()
    
  4. mini_frame.py

    # 版本2. 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 版本1. 比最初的版本好的是  -->  不用很多的if语句
    # 版本3. 用装饰器 + 字典完成  -->  比只用字典好在不用手动王字典中添加
    import time"""
    URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }
    """
    URL_FUNC_DICT = dict()def route(url):def set_func(func):URL_FUNC_DICT[url] = funcdef call_func(*args, **kwargs):return func(*args, **kwargs)return call_funcreturn set_func@route("/index.html")
    def index():with open("./templates/index.html", encoding='utf-8') as f:return f.read()@route("/center.html")
    def center():with open("./templates/center.html", encoding='utf-8') as f:return f.read()def application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]"""if file_name == "/index.py":return index()elif file_name == "/center.py":return center()else:return ' 中国 hello word time: %s' % time.ctime()"""try:# func = URL_FUNC_DICT[file_name]# return func()return URL_FUNC_DICT[file_name]()except Exception as ret:return "出现异常: %s" % str(ret)

五、添加mysql数据查询功能

  1. 修改mini_frame.py

    # 版本2. 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 版本1. 比最初的版本好的是  -->  不用很多的if语句
    # 版本3. 用装饰器 + 字典完成  -->  比只用字典好在不用手动王字典中添加
    import time
    from pymysql import *
    import re"""
    URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }
    """
    URL_FUNC_DICT = dict()def route(url):def set_func(func):URL_FUNC_DICT[url] = funcdef call_func(*args, **kwargs):return func(*args, **kwargs)return call_funcreturn set_func@route(r"/index.html")
    def index():with open("./templates/index.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="socket_db", charset='utf8')# 获取游标对象cs = conn.cursor()cs.execute("select * from info;")info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7], temp[1])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content@route(r"/center.html")
    def center():with open("./templates/center.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="socket_db", charset='utf8')# 获取游标对象cs = conn.cursor()cs.execute("select i.code, i.short, i.chg, i.turnuver, i.price, i.highs, f.not_info from info as i inner join focus as f on i.id=f.info_id;")info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span aria-hidden="true">⇋</span> 修改 </a></td><td><input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[1], temp[1])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content@route(r"/add/(\d+)\.html")
    def add_focus(page_num, ret):passdef application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]"""if file_name == "/index.py":return index()elif file_name == "/center.py":return center()else:return ' 中国 hello word time: %s' % time.ctime()"""try:# func = URL_FUNC_DICT[file_name]# return func()return URL_FUNC_DICT[file_name]()except Exception as ret:return "出现异常: %s" % str(ret)

六、让路由支持正则-添加股票

  1. 修改mini_frame框架

    # 版本2. 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 版本1. 比最初的版本好的是  -->  不用很多的if语句
    # 版本3. 用装饰器 + 字典完成  -->  比只用字典好在不用手动王字典中添加
    import time
    from pymysql import *
    import re"""
    URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }
    """
    URL_FUNC_DICT = dict()def route(url):def set_func(func):URL_FUNC_DICT[url] = funcdef call_func(*args, **kwargs):return func(*args, **kwargs)return call_funcreturn set_func@route(r"/index.html")
    def index(ret):with open("./templates/index.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()cs.execute("select * from info;")info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7], temp[1])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content@route(r"/center.html")
    def center(ret):with open("./templates/center.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()sql = """select i.code, i.short, i.chg, i.turnuver, i.price, i.highs, f.not_info from info as i inner join focus as f on i.id=f.info_id;"""cs.execute(sql)info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span aria-hidden="true">⇋</span> 修改 </a></td><td><input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[1], temp[1])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content# 给路由添加正则表达式的原因: 在实际开发时, url 中往往会带有很多的参数,例如: /add/000007.html中的000007就是参数
    # 如果没有正则的话, 那么就需要编写N次@route来进行添加 url对应的函数到字典中, 此时字典中的键值对有N个浪费空间
    # 而采用正则的话, 那么只需要编写1次@route就可以完成多个 url 例如: /add/000007.html /add/000036.html对应同一个函数,
    # 此时字典中的键值对个数会减少很多
    #
    @route(r"/add/(\d+)\.html")
    def add_focus(ret):stock_code = ret.group(1)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, stock_code)# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果已经关注了,则:if cs.fetchone():cs.close()conn.close()return "亲, 您已经关注这只股票了"sql = """ insert into focus (info_id) select id from info where code=%s;"""cs.execute(sql, stock_code)conn.commit()cs.close()conn.close()return "亲,关注成功"def application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]"""if file_name == "/index.py":return index()elif file_name == "/center.py":return center()else:return ' 中国 hello word time: %s' % time.ctime()"""try:for url, func in URL_FUNC_DICT.items():print(url)ret = re.match(url, file_name)if ret:# print(ret.group(1))return func(ret)breakelse:return "没有访问的页面--->%s" % file_nameexcept Exception as ret:return "出现异常: %s" % str(ret)else:return str(environ) + '-----404--->%s\n'

七、个人中心添加删除股票和修改备注

  1. 修改mini_frame框架

    # 版本2. 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 版本1. 比最初的版本好的是  -->  不用很多的if语句
    # 版本3. 用装饰器 + 字典完成  -->  比只用字典好在不用手动王字典中添加
    import time
    from pymysql import *
    import re"""
    URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }
    """
    URL_FUNC_DICT = dict()def route(url):def set_func(func):URL_FUNC_DICT[url] = funcdef call_func(*args, **kwargs):return func(*args, **kwargs)return call_funcreturn set_func@route(r"/index.html")
    def index(ret):with open("./templates/index.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()cs.execute("select * from info;")info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7], temp[1])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content@route(r"/center.html")
    def center(ret):with open("./templates/center.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()sql = """select i.code, i.short, i.chg, i.turnuver, i.price, i.highs, f.not_info from info as i inner join focus as f on i.id=f.info_id;"""cs.execute(sql)info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span aria-hidden="true">⇋</span> 修改 </a></td><td><input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[0], temp[0])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content# 给路由添加正则表达式的原因: 在实际开发时, url 中往往会带有很多的参数,例如: /add/000007.html中的000007就是参数
    # 如果没有正则的话, 那么就需要编写N次@route来进行添加 url对应的函数到字典中, 此时字典中的键值对有N个浪费空间
    # 而采用正则的话, 那么只需要编写1次@route就可以完成多个 url 例如: /add/000007.html /add/000036.html对应同一个函数,
    # 此时字典中的键值对个数会减少很多
    #
    @route(r"/add/(\d+)\.html")
    def add_focus(ret):stock_code = ret.group(1)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果已经关注了,则:if cs.fetchone():cs.close()conn.close()return "亲, 您已经关注这只股票了"sql = """ insert into focus (info_id) select id from info where code=%s;"""cs.execute(sql, stock_code)conn.commit()cs.close()conn.close()return "亲,关注成功"@route(r"/del/(\d+)\.html")
    def add_focus(ret):stock_code = ret.group(1)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"sql = """  delete from focus as f where f.info_id = (select i.id from info as i where i.code=%s);;"""cs.execute(sql, stock_code)conn.commit()cs.close()conn.close()return "亲,取消关注成功"# 修改
    @route(r"/update/(\d+).html")
    def update(ret):"""查询出修改数据的信息,并跳转页面"""stock_code = ret.group(1)with open("./templates/update.html", encoding="utf8") as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"sql = """ select f.not_info from focus as f inner join info as i on i.id=f.info_id where i.code=%s;"""cs.execute(sql, (stock_code, ))info_data = cs.fetchone()cs.close()conn.close()content = re.sub(r"\{%code%\}", stock_code, content)# content = re.sub(r"\{%code%\}", stock_code, content)content = re.sub(r"\{%note_info%\}", str(info_data[0]), content)# for temp in info_data:#     return content % (stock_code, info_data[0])return content # 添加修改内容
    @route(r"/update/(\d*)/(.*)\.html")
    def update_not_info(ret):stock_code = ret.group(1)stock_comment = ret.group(2)# print(stock_code)# print(not_inf0)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"# sql = """ update focus as f set f.not_info=%s where f.info_id = (select id from info as i where i.code=%s); """sql = """ update focus inner join info on focus.info_id=info.id set focus.not_info=%s where info.code=%s;"""print(sql)cs.execute(sql, (stock_comment, stock_code))# cs.execute(sql, (stock_comment, stock_code))print("--"*50)# cs.execute(sql, [stock_comment, stock_code])conn.commit()print(stock_comment, stock_code)print(cs.fetchall())  cs.close()conn.close()return "亲,修改备注成功"def application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]"""if file_name == "/index.py":return index()elif file_name == "/center.py":return center()else:return ' 中国 hello word time: %s' % time.ctime()"""try:for url, func in URL_FUNC_DICT.items():# print(url)ret = re.match(url, file_name)if ret:# print(ret.group(1))return func(ret)breakelse:return "没有访问的页面--->%s" % file_nameexcept Exception as ret:return "出现异常: %s" % str(ret)else:return str(environ) + '-----404--->%s\n'

八、url解码

  1. 在修改备注的时候回出现编码的问题这里用到了url 解码:

  2. 用的是urllib.parse库中的unquote来解码的

    import urllib.parse
    解码:urllib.parse.unquote(stock_comment) 编码: urllib.parse.quote()
    
  3. 修改mini_frame框架

    # 版本2. 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 版本1. 比最初的版本好的是  -->  不用很多的if语句
    # 版本3. 用装饰器 + 字典完成  -->  比只用字典好在不用手动王字典中添加
    import time
    from pymysql import *
    import re
    import urllib.parse"""
    URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }
    """
    URL_FUNC_DICT = dict()def route(url):def set_func(func):URL_FUNC_DICT[url] = funcdef call_func(*args, **kwargs):return func(*args, **kwargs)return call_funcreturn set_func@route(r"/index.html")
    def index(ret):with open("./templates/index.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()cs.execute("select * from info;")info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7], temp[1])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content@route(r"/center.html")
    def center(ret):with open("./templates/center.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()sql = """select i.code, i.short, i.chg, i.turnuver, i.price, i.highs, f.not_info from info as i inner join focus as f on i.id=f.info_id;"""cs.execute(sql)info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span aria-hidden="true">⇋</span> 修改 </a></td><td><input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[0], temp[0])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content# 给路由添加正则表达式的原因: 在实际开发时, url 中往往会带有很多的参数,例如: /add/000007.html中的000007就是参数
    # 如果没有正则的话, 那么就需要编写N次@route来进行添加 url对应的函数到字典中, 此时字典中的键值对有N个浪费空间
    # 而采用正则的话, 那么只需要编写1次@route就可以完成多个 url 例如: /add/000007.html /add/000036.html对应同一个函数,
    # 此时字典中的键值对个数会减少很多
    #
    @route(r"/add/(\d+)\.html")
    def add_focus(ret):stock_code = ret.group(1)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果已经关注了,则:if cs.fetchone():cs.close()conn.close()return "亲, 您已经关注这只股票了"sql = """ insert into focus (info_id) select id from info where code=%s;"""cs.execute(sql, stock_code)conn.commit()cs.close()conn.close()return "亲,关注成功"# 删除关注
    @route(r"/del/(\d+)\.html")
    def add_focus(ret):stock_code = ret.group(1)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"sql = """  delete from focus as f where f.info_id = (select i.id from info as i where i.code=%s);;"""cs.execute(sql, stock_code)conn.commit()cs.close()conn.close()return "亲,取消关注成功"# 修改备注
    @route(r"/update/(\d+).html")
    def update(ret):"""查询出修改数据的信息,并跳转页面"""stock_code = ret.group(1)with open("./templates/update.html", encoding="utf8") as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"sql = """ select f.not_info from focus as f inner join info as i on i.id=f.info_id where i.code=%s;"""cs.execute(sql, (stock_code, ))info_data = cs.fetchone()cs.close()conn.close()content = re.sub(r"\{%code%\}", stock_code, content)# content = re.sub(r"\{%code%\}", stock_code, content)content = re.sub(r"\{%note_info%\}", str(info_data[0]), content)# for temp in info_data:#     return content % (stock_code, info_data[0])return content # 添加修改内容
    # @route(r"/update/(\d+)/(.*)\.html")
    @route(r"/update/(\d*)/(.*)\.html")
    def update_not_info(ret):stock_code = ret.group(1)stock_comment = ret.group(2)# 编码: urllib.parse.quote()stock_comment = urllib.parse.unquote(stock_comment)  # 解码# print(stock_code)# print(not_inf0)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"# sql = """ update focus as f set f.not_info=%s where f.info_id = (select id from info as i where i.code=%s); """sql = """ update focus inner join info on focus.info_id=info.id set focus.not_info=%s where info.code=%s;"""print(sql)cs.execute(sql, (stock_comment, stock_code))# cs.execute(sql, (stock_comment, stock_code))print("--"*50)# cs.execute(sql, [stock_comment, stock_code])conn.commit()print(stock_comment, stock_code)print(cs.fetchall())  cs.close()conn.close()return "亲,修改备注成功"def application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]"""if file_name == "/index.py":return index()elif file_name == "/center.py":return center()else:return ' 中国 hello word time: %s' % time.ctime()"""try:for url, func in URL_FUNC_DICT.items():# print(url)ret = re.match(url, file_name)if ret:# print(ret.group(1))return func(ret)breakelse:return "没有访问的页面--->%s" % file_nameexcept Exception as ret:return "出现异常: %s" % str(ret)else:return str(environ) + '-----404--->%s\n'

九、添加日志功能

  1. 在mini_frame框架中添加

    # 版本2. 用字典的方式实现路由功能  -- > 缺点是每都要在字典中添加
    # 版本1. 比最初的版本好的是  -->  不用很多的if语句
    # 版本3. 用装饰器 + 字典完成  -->  比只用字典好在不用手动王字典中添加
    import time
    from pymysql import *
    import re
    import urllib.parse
    import logging"""
    URL_FUNC_DICT={"/index.py" : index,"/center.py" : center
    }
    """
    URL_FUNC_DICT = dict()def route(url):def set_func(func):URL_FUNC_DICT[url] = funcdef call_func(*args, **kwargs):return func(*args, **kwargs)return call_funcreturn set_func@route(r"/index.html")
    def index(ret):with open("./templates/index.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()cs.execute("select * from info;")info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7], temp[1])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content@route(r"/center.html")
    def center(ret):with open("./templates/center.html", encoding='utf-8') as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()sql = """select i.code, i.short, i.chg, i.turnuver, i.price, i.highs, f.not_info from info as i inner join focus as f on i.id=f.info_id;"""cs.execute(sql)info_data = cs.fetchall()cs.close()conn.close()tr_template = """<div><table border="1"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td><a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span aria-hidden="true">⇋</span> 修改 </a></td><td><input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s"></td></table></div>"""html = ""for temp in info_data:html += tr_template % (temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[0], temp[0])# print(html)content = re.sub(r"\{%content%\}", html, content)# print(content)return content# 给路由添加正则表达式的原因: 在实际开发时, url 中往往会带有很多的参数,例如: /add/000007.html中的000007就是参数
    # 如果没有正则的话, 那么就需要编写N次@route来进行添加 url对应的函数到字典中, 此时字典中的键值对有N个浪费空间
    # 而采用正则的话, 那么只需要编写1次@route就可以完成多个 url 例如: /add/000007.html /add/000036.html对应同一个函数,
    # 此时字典中的键值对个数会减少很多
    #
    @route(r"/add/(\d+)\.html")
    def add_focus(ret):stock_code = ret.group(1)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果已经关注了,则:if cs.fetchone():cs.close()conn.close()return "亲, 您已经关注这只股票了"sql = """ insert into focus (info_id) select id from info where code=%s;"""cs.execute(sql, stock_code)conn.commit()cs.close()conn.close()return "亲,关注成功"# 删除关注
    @route(r"/del/(\d+)\.html")
    def add_focus(ret):stock_code = ret.group(1)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"sql = """  delete from focus as f where f.info_id = (select i.id from info as i where i.code=%s);;"""cs.execute(sql, stock_code)conn.commit()cs.close()conn.close()return "亲,取消关注成功"# 修改备注
    @route(r"/update/(\d+).html")
    def update(ret):"""查询出修改数据的信息,并跳转页面"""stock_code = ret.group(1)with open("./templates/update.html", encoding="utf8") as f:content = f.read()# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"sql = """ select f.not_info from focus as f inner join info as i on i.id=f.info_id where i.code=%s;"""cs.execute(sql, (stock_code, ))info_data = cs.fetchone()cs.close()conn.close()content = re.sub(r"\{%code%\}", stock_code, content)# content = re.sub(r"\{%code%\}", stock_code, content)content = re.sub(r"\{%note_info%\}", str(info_data[0]), content)# for temp in info_data:#     return content % (stock_code, info_data[0])return content # 添加修改内容
    # @route(r"/update/(\d+)/(.*)\.html")
    @route(r"/update/(\d*)/(.*)\.html")
    def update_not_info(ret):stock_code = ret.group(1)stock_comment = ret.group(2)# 编码: urllib.parse.quote()stock_comment = urllib.parse.unquote(stock_comment)  # 解码# print(stock_code)# print(not_inf0)# 连接数据库conn = connect(host="localhost", port=3306, user="root", password="chd123..", database="stock_db", charset='utf8')# 获取游标对象cs = conn.cursor()# 查询这只股票是否存在sql = """select * from info where code=%s;"""cs.execute(sql, (stock_code,))# 如果没有这只股票,则:if not cs.fetchone():cs.close()conn.close()return "没有这只股票,请收下留情"# 查看是否已经关注了这只股票sql = """ select i.id from info as i inner join focus as f on i.id=f.info_id where i.code=%s;"""cs.execute(sql, stock_code)# 如果没有关注了,则:if not cs.fetchone():cs.close()conn.close()return "亲, 您没有关注这只股票了"# sql = """ update focus as f set f.not_info=%s where f.info_id = (select id from info as i where i.code=%s); """sql = """ update focus inner join info on focus.info_id=info.id set focus.not_info=%s where info.code=%s;"""print(sql)cs.execute(sql, (stock_comment, stock_code))# cs.execute(sql, (stock_comment, stock_code))print("--"*50)# cs.execute(sql, [stock_comment, stock_code])conn.commit()print(stock_comment, stock_code)print(cs.fetchall())  cs.close()conn.close()return "亲,修改备注成功"def application(environ, start_response):start_response("200 OK", [('Content-Type', 'text/html;charset=utf-8')])# print(environ)file_name = environ["PATH_INFO"]logging.basicConfig(level=logging.INFO,  filename='./log.txt',  filemode='a',  # 可以写a追加format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')  logging.info("访问的是: %s" % urllib.parse.unquote(file_name))try:for url, func in URL_FUNC_DICT.items():# print(url)ret = re.match(url, file_name)if ret:# print(ret.group(1))return func(ret)breakelse:logging.warning("没有这个页面: %s" % urllib.parse.unquote(file_name))return "没有访问的页面--->%s" % file_nameexcept Exception as ret:# logging.ERROR("出现异常错误: %s" % str(ret))return "出现异常: %s" % str(ret)else:logging.critical("出现严重错误导致404")return str(environ) + '-----404--->%s\n'

十、总结知识点

  1. mysql
    python中数据库的增删改
  2. 装饰器
    装饰器可以在开发中添加新功能的时候,用的比较多
  3. log日志

mini-web框架-个人选股制作相关推荐

  1. mini web框架-2-显示页面

    dynamic/my_web.py (更新) import time import ostemplate_root = "./templates"def index(file_na ...

  2. web框架总结(django、flask)

    1.MVC解读 M:Model,模型,和数据库进行交互 V:View,视图,负责产生Html页面 C:Controller,控制器,接收请求,进行处理,与M和V进行交互,返回应答. 1.用户点击注 2 ...

  3. python web框架介绍对比

    Django Python框架虽然说是百花齐放,但仍然有那么一家是最大的,它就是Django.要说Django是Python框架里最好的,有人同意也有人 坚决反对,但说Django的文档最完善.市场占 ...

  4. php web框架 symfony简介

    Symfony是基于MVC架构的PHP框架 Symfony是一个用于快速开发现代Web应用程序的开源MVC框架. Symfony是一个完整的Web框架.它包含一组可重用的PHP组件.您可以在应用程序中 ...

  5. python微型web框架flask介绍

    Flask是一个基于python的,微型web框架.之所以被称为微型是因为其核心非常简单,同时具有很强的扩展能力.它几乎不给使用者做任何技术决定. 安装flask时应该注意其必须的几个支持包比如Jin ...

  6. django 业务逻辑写在view里吗?_Python Web框架Django简介

    引言 我们都知道,Django是一种基于Python的Web开发框架. 那么,什么是Web开发?Web开发指的是开发基于B/S架构,通过前后端的配合,将后台服务器的数据在浏览器上展现给前台用户的应用. ...

  7. 新一代Spring Web框架WebFlux!

    Spring WebFlux 教程:如何构建反应式 Web 应用程序 反应式系统提供了我们在高数据流世界中所需的无与伦比的响应能力和可扩展性.然而,反应式系统需要经过专门培训的工具和开发人员来实现这些 ...

  8. 一文读懂Python web框架和web服务器之间的关系

    我们都知道 Python 作为一门强大的语言,能够适应快速原型和较大项目的制作,因此被广泛用于 web 应用程序的开发中. 在面试的过程中,大家或多或少都被问到过这样一个问题:一个请求从浏览器发出到数 ...

  9. 还在学Django! FastAPI Web 框架教程来了!

    点击上方"菜鸟学Python",选择"星标"公众号 超级无敌干货,第一时间送达!!! 大家好,我是菜鸟哥! 都说学Python web开发有三驾马车,其中Dja ...

最新文章

  1. 分布式概念-去中心化副本控制实现
  2. 关于ping telnet
  3. CoolPad backdoor CoolReaper
  4. 七、linux驱动注册
  5. 注释数据库介绍之GO、KEGG数据库
  6. 交叉熵(cross_entropy)作为损失函数在神经网络中的作用
  7. SQL常用语句|创建表,设置主键......
  8. .net winform panel 不刷新_【扫盲篇】visual studio2019(C#/.NET)安装教程
  9. Codeforces Round #429 Div. 1
  10. 荒芜的周六-PHP之面向对象(三)
  11. redis 实战系列(一)
  12. Notepad++汉化教程
  13. ps里面的css,今天来为大家介绍PS中的图层样式
  14. PCBA加工组装需要的设备有哪些呢?
  15. cdr怎么新建和删除图层
  16. 设备管理的常见问题和解决方案
  17. 技嘉 RTX 4090 已在香港发售,距正式上市两周
  18. 源代码和目标代码之间的区别
  19. 国家2020年区划数据爬取
  20. oracle 委外发料,委外发料管理

热门文章

  1. 单据点击套打设置报错,显示可用的套打单据列表时发生错误处理方法
  2. SIKI学院:MySQL数据库从零到精通:三:课时 4 : 03-服务器端运行通信原理图+课时 5 : 04-游戏服务器端简介
  3. linux云服务器空间爆满
  4. SCTP协议详解与实例
  5. 校园点餐系统:点餐、食堂管理、商户管理和菜品管理(Java和MySQL)
  6. 《世嘉新人培训教材——游戏开发》踩到的坑2、读取图片文件
  7. 汤不热真香,教练我要学这个动作
  8. 10kw全固态中波dam广播发射机的计算机监控系统分析与设计[,【中波发射机】关于DAM10kW中波广播发射机欠激励故障维修总结...
  9. Jmeter组件-线程组(Thread Group)
  10. Surf描述子形成步骤