股票查询

def gp_search(code):
    url="http://qt.gtimg.cn/q="+code
    mm.header=["User-Agent: MyCustomAgent/1.0","mam: i am hera"]
    c=mm.get(url)
    print(c)
    return c


from machine import UART
import time

class ML307(object):
    def __init__(self,rx,tx,u_num=1):
        self.uart=UART(u_num,115200,rx=rx,tx=tx,rxbuf=4096,txbuf=4096)
        self.header=[]
        time.sleep(3)
    def command(self,cmd,t=1):
        self.uart.write(cmd+'\r\n')
        time.sleep(t*0.1)
        return self.uart.read()
    def get_response(self,info):
        nx=info.split(b'MHTTPURC: "content"')
        rep_1=nx[1].split(b",")
        rep=b"".join(rep_1[5:])
        return rep
    def get_url(self,url_1,url_2,t=15):
        self.command('AT+MHTTPCREATE="'+url_1+'"')
        self.header_def()
        info=self.command('AT+MHTTPREQUEST=0,1,0,"'+url_2+'"',t)
        self.command('AT+MHTTPHEADER=0')
        return self.get_response(info)
    def get_url_ssl(self,url_1,url_2,t=15):
        self.command('AT+MHTTPCREATE="'+url_1+'"')
        self.command('AT+MHTTPCFG="ssl",0,1,1')
        self.header_def()
        info=self.command('AT+MHTTPREQUEST=0,1,0,"'+url_2+'"',t)
        self.command('AT+MHTTPHEADER=0')
        return self.get_response(info)
    def make_url(self,url):
        url_1="/".join(url.split("/")[0:3])
        url_2="/"+"/".join(url.split("/")[3:])
        return [url_1,url_2]
    def get(self,url):
        ua=self.make_url(url)
        try:
            if "https" in ua[0]:
                ba=self.get_url_ssl(ua[0],ua[1])
            else:
                ba=self.get_url(ua[0],ua[1])
            return ba
        except Exception as e:
            return False
    def post_form(self,info):
        form=""
        for key in info:
            form=form+key+"="+str(info[key])+"&"
        return form
    def post_url(self,url_1,url_2,form_str,t=15):
        self.command('AT+MHTTPCREATE="'+url_1+'"')
        self.header_def()
        self.command('AT+MHTTPHEADER=0,0,0,"Content-Type: application/x-www-form-urlencoded"')
        self.command('AT+MHTTPCONTENT=0,0,0,"'+form_str+'"')
        info=self.command('AT+MHTTPREQUEST=0,2,0,"'+url_2+'"',t)
        self.command('AT+MHTTPHEADER=0')
        return self.get_response(info)
    def post_url_ssl(self,url_1,url_2,form_str,t=15):
        self.command('AT+MHTTPCREATE="'+url_1+'"')
        self.command('AT+MHTTPCFG="ssl",0,1,1')
        self.header_def()
        self.command('AT+MHTTPHEADER=0,0,0,"Content-Type: application/x-www-form-urlencoded"')
        self.command('AT+MHTTPCONTENT=0,0,0,"'+form_str+'"')
        info=self.command('AT+MHTTPREQUEST=0,2,0,"'+url_2+'"',t)
        self.command('AT+MHTTPHEADER=0')
        return self.get_response(info)
    def post(self,url,dic_info):
        form_str=self.post_form(dic_info)
        ua=self.make_url(url)
        try:
            if "https" in ua[0]:
                ba=self.post_url_ssl(ua[0],ua[1],form_str)
            else:
                ba=self.post_url(ua[0],ua[1],form_str)
            return ba
        except Exception as e:
            return False
    def header_def(self):
        lh=len(self.header)
        if lh>1:
            for i in range(lh):
                if i <lh-1:
                    self.command('AT+MHTTPHEADER=0,1,0,"'+self.header[i]+'"')
                else:
                    self.command('AT+MHTTPHEADER=0,0,0,"'+self.header[i]+'"')
        elif lh==1:
            self.command('AT+MHTTPHEADER=0,0,0,"'+self.header[0]+'"')
        else:
            pass
def gp_data(raw_data, target_stocks=None):
    """
    解析股票数据,支持目标股票列表兜底,避免漏股
    :param raw_data: ML307返回的原始字节数据
    :param target_stocks: 目标股票列表(如["sz000858","sh600519"...]),防止漏股
    :return: 完整股票字典(5只全保留)
    """
    # 步骤1:数据有效性校验+初始化结果(兜底目标股票,防止漏股)
    stock_result = {}
    if target_stocks:
        for code in target_stocks:
            stock_result[code] = {
                'code': code,
                'current_price': '0.00',
                'open_price': '0.00',
                'turnover_rate': '0.00'
            }
    
    if not raw_data or len(raw_data) == 0:
        return stock_result
    
    # 步骤2:清洗无效字节(\r\n+ 全去掉,兼容接口截断)
    clean_data = raw_data.replace(b'\r', b'').replace(b'\n', b'').replace(b'+', b'')
    
    # 步骤3:拆分多只股票(按;分割,兼容末尾残缺记录)
    stock_records = clean_data.split(b';')
    
    # 步骤4:逐只解析(按你的原始数据,换手率精准索引38!)
    for record in stock_records:
        if not record or b'v_' not in record or b'=' not in record:
            continue
        
        # 拆分股票代码和字段串(字节操作,无编码报错)
        code_part, field_part = record.split(b'=', 1)
        stock_code = code_part.replace(b'v_', b'').decode('ascii')
        
        # 清洗字段串+按~拆分
        field_str = field_part.strip(b'"')
        fields = field_str.split(b'~')
        
        # 步骤5:精准提取(逐字节核对你的原始数据,索引固定!)
        # 核心:换手率=索引38,当前价=3,开盘价=4,字段够39个才取,否则用默认值
        current_price = fields[3].decode('ascii') if len(fields)>=4 else '0.00'
        open_price = fields[4].decode('ascii') if len(fields)>=5 else '0.00'
        turnover_rate = fields[38].decode('ascii') if len(fields)>=39 else '0.00'
        
        # 更新结果(覆盖兜底默认值)
        stock_result[stock_code] = {
            'code': stock_code,
            'current_price': current_price,
            'open_price': open_price,
            'turnover_rate': turnover_rate
        }
    
    return stock_result

HTML页面处理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="/static/jquery.js"></script>    
    <link rel="stylesheet" href="/static/bootstrap.css" crossorigin="anonymous">
<title>股票监控管理页面</title>
</head>
<body>


    
    <div class="container ">
        <div class="row">
            <div class="jumbotron">
                <h1>股票监控管理页面</h1>
                <p>最大显示股票信息为10条。</p>
              </div>
        </div>
        <br/>
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="input-group input-group-lg">
                    <div class="input-group-addon">
                        <span>
                            输入代码
                        </span>
                    </div>
                    <input type="number" id="code" class="form-control">
                    <div class="input-group-btn">
                        <button class="btn btn-info" id="btn_gp">查询</button>
                    </div>
                </div>
            </div>
        </div>
        <br/>
        <div class="row">
            <div class="col-md-4">
                <h2 class="text-info">查询到的股票:</h2>
            </div>
            <div class="show-info col-md-8">

            </div>
        </div>
        <hr/>
        <div class="row">
            <div class="col-md-4">
                <h2 class="text-success">已保存的股票代码:</h2>
            </div>
            <ol class="added col-md-8">

            </ol>
        </div>
    </div>




    <script>


function add_one(mx){
    var div=$("<li><h3>"+mx[2]+" <small> 代码"+mx[1]+"</small>  </h3></li>");
    var button=$("<button class='btn btn-danger' onclick=del_code('"+mx[0]+"','"+mx[1]+"','"+mx[2]+"')>删除</button>");
    div.append(button);
    $(".added").append(div);
    // ty code name
}

// AJAX 1
function add_code(ty,code,name){
    // 添加股票
    console.log(ty,code,name);
    url="/add";
    // 添加网址 一个回调传入信息
    $.ajax({
        type:"POST",
        url:url,
        async:false,
        data:{
            ty:ty,
            code:code,
            name:name

        },
        success:function(data){
            if(data.status){
                console.log("添加完成");
                get_all();//刷新
                $(".show-info").html("");
            }
        }
    })
}
// AJAX 2
function del_code(ty,code,name){
    // 删除股票
    console.log(ty,code,name);
    url="/del";
    // 添加网址 一个回调传入信息
    $.ajax({
        type:"POST",
        url:url,
        async:false,
        data:{
            ty:ty,
            code:code,
            name:name

        },
        success:function(data){
            if(data.status){
                console.log("删除完成");
                get_all();//刷新
            }

        }
    })
}

// AJAX 3
function get_all(){
    $(".added").html("")
    // 现有股票 URL
    url="/all";
    $.ajax({
        type:"POST",
        url:url,
        async:false,
        success:function(data){
            console.log("查询完成");
            if(data.status){
                for (const key in data.info) {
                    add_one(data.info[key])
                }
            }
        }
    })

}

// AJAX 4
function fgp(cod='600111',ty='sz'){
    var url="/gp?code="+ty+cod
    var name=''
    var price=''
    var code=''
    $.ajax({
        type:"GET",
        url:url,
        async:false,
        success:function(data){
            e=data.split("~");
            if(e[1]){
                name=e[1];
                code=e[2];
                price=e[3];
            }
            
        }
    })
    if(name){
        var mk=[name,ty,code,price]
        return mk
    }else{
        return []
    }
}

function add_btn(mx){
    var div=$("<h3>"+mx[0]+" <small> 代码"+mx[2]+"股价:"+mx[3]+" </small>  </h3>");
    var button=$("<button class='btn btn-primary' onclick=add_code('"+mx[1]+"','"+mx[2]+"','"+mx[0]+"')>添加</button>");
    div.append(button);
    $(".show-info").append(div);
}

$("#btn_gp").click(function(){
    var code=$("#code").val();
    if(code.length==6){
        $(".show-info").html("");
        var jugg=code[0];
        if(jugg==0 || jugg==2|| jugg==3){
           var sz=fgp(code,"sz");
            if(sz.length>1){
                add_btn(sz);
            }else{
                alert("未查询到相关信息");
            }
        }else if(jugg==6 || jugg==9){
            var sh=fgp(code,"sh");
            if(sh.length>1){
                add_btn(sh);
            }else{
                alert("未查询到相关信息");
            }
        }else if(jugg==4 || jugg==8){
            var bj=fgp(code,"bj");
            if(bj.length>1){
                add_btn(bj);
            }else{
                alert("未查询到相关信息");
            }
        }else{
            alert("未查询到相关信息");
        }
        $("#code").val("");
    }else{
        alert("股票代码为6位");
    }
})




get_all();
// 执行查询
    </script>

    
</body>
</html>
发表在 None | 留下评论

microdot micropython下web框架快速手册

主要使用异步+装饰器的方式

from microdot import Microdot, send_file

创建服务app=Microdot()

启动服务app.run(debug=True)

创建一个网页链接需要使用 装饰器 @app.route(‘/’)

再创建对应函数

async def index(request):
return send_file(‘g.html’)

创建static目录下静态资源访问需要<path:path>
@app.route(‘/static/<path:path>’)
async def static(request, path):
if ‘..’ in path:
# directory traversal is not allowed
return ‘Not found’, 404
return send_file(‘static/’ + path)

GET 和POST 访问需要
@app.route(‘/gp’, methods=[‘GET’,’POST’])
其中get抓取 req.args.get ();post抓取 req.form.get()
async def gp_index(req):
code = req.form.get(‘code’)

回传return
return 1 ,2,3
1可以直接信息,或者send_file发文件,
2是代码 200 302 404 500
3为响应头字典{‘Content-Type’: ‘text/plain; charset=gb2312’}

就是为了简单 所以其他可以暂时不用



app = Microdot()


@app.route('/')
async def index(request):
    return send_file('g.html')


@app.route('/static/<path:path>')
async def static(request, path):
    if '..' in path:
        # directory traversal is not allowed
        return 'Not found', 404
    return send_file('static/' + path)

@app.route('/gp', methods=['GET'])
async def gp_index(req):
    code = req.args.get('code')
    print(code)
    bk=gp_search(code)
    return bk,200, {'Content-Type': 'text/plain; charset=gb2312'}

@app.route('/gpx', methods=['POST'])
async def gp_index(req):
    code = req.form.get('code')
    print(code)
    bk=gp_search(code)
    return bk,200, {'Content-Type': 'text/plain; charset=gb2312'}
    
app.run(debug=True)

创建AP热点
import network
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid=ssid, password=password)

发表在 None | 留下评论

页面 添加简要查询 实现输入后查询修改

HTML页面

<style>
    /* 固定定位的搜索框容器 */
 .fixed-top-search {
      position: fixed; /* 固定定位,悬浮不随滚动移动 */
      top: 0;          /* 锁定到页面顶部 */
      right: 20px;     /* 水平靠右 20px,可改 left: 20px 靠左,或 left: 50%; transform: translateX(-50%) 居中 */
      z-index: 9999;   /* 最高层级,避免被遮挡 */
      padding: 10px 0; /* 上下内边距,让搜索框更美观 */
      width: 320px;    /* 搜索框宽度,可调整 */
    }
</style>


<!-- 悬浮搜索框 -->
    <div class="fixed-top-search">
        <div class="input-group">
            <input type="text" class="form-control search" placeholder="请输入搜索内容" aria-label="搜索">
            <span class="input-group-addon">
                输入名称
            </span>
        </div>
    </div>

JS处理

function clearHighlight() {
  // 找到所有高亮的span,直接替换为文本内容,避免unwrap的转义问题
  $('span.bg-danger').each(function() {
    var $this = $(this);
    // console.log($this.text());
    // 替换span为其文本内容(纯文本,无HTML解析)
    // $this.replaceWith($this.text());
    $this.parent().text($this.parent().text())
  });
}

// 搜索字符串并添加 bg-danger 类
function searchAndHighlight(keyword) {

  if (!keyword.trim()) return;

  // 遍历所有文本节点(排除 script、style 标签)
  $('body :not(script, style)').contents().each(function() {
    // 只处理文本节点
    if (this.nodeType === Node.TEXT_NODE) {
      var text = $(this).text();
    //   text=text.replace(/"/g,"");
      const regex = new RegExp(`(${keyword})`, 'gi');
      
      // 匹配到关键词时,用 span 包裹
      if (regex.test(text)) {
        
        const newHtml = text.replace(regex, '<span class="bg-danger">$1</span>');
        $(this).replaceWith(newHtml);
        // $(this).addClass('bg-danger')
      }
    }
  });
}

$(".search").on("input", function(){
  var se = $(this).val().trim(); // 去除首尾空格,避免无效查询
  if (se) {
    clearHighlight();
    searchAndHighlight(se); // 有内容则高亮
  }
});
发表在 None | 留下评论

Thinkphp 前端页面获取get值

{:request()->get(‘id/d’)}
调用上面的函数可以获得 get类型的id并初始化为数字形式

发表在 None | 留下评论

python打包 pyinstaller PIL

带logo 无黑框打包

pyinstaller -F -w -i logo.ico x.py

无logo 无黑框

pyinstaller -F -w x.py

普通打包 一个 单文件exe 有黑框

pyinstaller -F x.py

普通打包 非单文件exe有黑框

pyinstaller x.py

PIL 打包坑点 需要指定 字体

#否则会失败

options = {
    'module_width': 0.24,
    'module_height':6.0,
    'font_size': 8,
    'text_distance': 3,
    'quiet_zone':4,
    'font_path': r'C:\Windows\Fonts\arial.ttf',  # Arial字体(纯数字/英文)
}
发表在 None | 留下评论