• [其他] 浅谈python使用SAX解析xml
    python使用SAX解析xmlSAX是一种基于事件驱动的 API。利用SAX解析XML文档牵涉到两个部分: 解析器和事件处理器。解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件。而事件处理器则负责对事件作出响应,对传递的XML数据进行处理。<psax适于处理下面的问题:< p="">1、对大型文件进行处理;2、只需要文件的部分内容,或者只需从文件中得到特定信息。3、想建立自己的对象模型的时候。在python中使用sax方式处理xml要先引入xml.sax中的parse函数,还有xml.sax.handler中的ContentHandler。ContentHandler类方法介绍characters(content)方法调用时机:从行开始,遇到标签之前,存在字符,content 的值为这些字符串。从一个标签,遇到下一个标签之前, 存在字符,content 的值为这些字符串。从一个标签,遇到行结束符之前,存在字符,content 的值为这些字符串。标签可以是开始标签,也可以是结束标签。startDocument() 方法文档启动的时候调用。endDocument() 方法解析器到达文档结尾时调用。startElement(name, attrs)方法遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。endElement(name) 方法遇到XML结束标签时调用。</psax适于处理下面的问题:<>
  • [其他] 浅谈Python 特点
    Python 是由 Guido van Rossum 在八十年代末和九十年代初,在荷兰国家数学和计算机科学研究所设计出来的。Python 本身也是由诸多其他语言发展而来的,这包括 ABC、Modula-3、C、C++、Algol-68、SmallTalk、Unix shell 和其他的脚本语言等等。像 Perl 语言一样,Python 源代码同样遵循 GPL(GNU General Public License)协议。现在 Python 是由一个核心开发团队在维护,Guido van Rossum 仍然占据着至关重要的作用,指导其进展。Python 2.7 被确定为最后一个 Python 2.x 版本,它除了支持 Python 2.x 语法外,还支持部分 Python 3.1 语法。Python 特点    1.易于学习:Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单。    2.易于阅读:Python代码定义的更清晰。    3.易于维护:Python的成功在于它的源代码是相当容易维护的。    4.一个广泛的标准库:Python的最大的优势之一是丰富的库,跨平台的,在UNIX,Windows和Macintosh兼容很好。    5.互动模式:互动模式的支持,您可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片断。    6.可移植:基于其开放源代码的特性,Python已经被移植(也就是使其工作)到许多平台。    7.可扩展:如果你需要一段运行很快的关键代码,或者是想要编写一些不愿开放的算法,你可以使用C或C++完成那部分程序,然后从你的Python程序中调用。    8.数据库:Python提供所有主要的商业数据库的接口。    9.GUI编程:Python支持GUI可以创建和移植到许多系统调用。    10.可嵌入: 你可以将Python嵌入到C/C++程序,让你的程序的用户获得"脚本化"的能力。
  • [其他] 浅学Python 变量类型
    Python 变量类型变量是存储在内存中的值,这就意味着在创建变量时会在内存中开辟一个空间。基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中。因此,变量可以指定不同的数据类型,这些变量可以存储整数,小数或字符。Python 中的变量赋值不需要类型声明。每个变量在内存中创建,都包括变量的标识,名称和数据这些信息。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。等号 = 用来给变量赋值。等号 = 运算符左边是一个变量名,等号 = 运算符右边是存储在变量中的值。例如:#!/usr/bin/python# -*- coding: UTF-8 -*- counter = 100 # 赋值整型变量miles = 1000.0 # 浮点型name = "John" # 字符串 print counterprint milesprint name多个变量赋值Python允许你同时为多个变量赋值a = b = c = 1标准数据类型Python 定义了一些标准类型,用于存储各种类型的数据。Python有五个标准的数据类型:    Numbers(数字)    String(字符串)    List(列表)    Tuple(元组)    Dictionary(字典)Python 数字数字数据类型用于存储数值。他们是不可改变的数据类型,这意味着改变数字数据类型会分配一个新的对象。当你指定一个值时,Number 对象就会被创建
  • [执行问题] mindspore实现GAN网络训练报错:Fatal Python error: GC already track
    在GPU上训练网络报错如下:训练代码如下:其中输入原始图像[3,3,512,512]记为real=image,输入掩膜图像[1,1,512,512]记为mask,x=real*(1-mask)实现对输入原始图像进行掩膜处理得到孔洞图像,孔洞图像输入生成器实现图像恢复效果。from mindspore import nn,Tensorfrom mindspore.common import dtype as mstypefrom mindspore import context,save_checkpointimport mindspore.ops.operations as Pimport mindspore.ops.functional as Fimport mindspore.ops.composite as Cfrom mindspore.parallel._utils import (_get_device_num,_get_gradients_mean,_get_parallel_mode)from mindspore.context import ParallelModefrom mindspore.nn.wrap.grad_reducer import DistributedGradReducerimport osimport numpy as npimport matplotlib.pyplot as pltimport mindspore.dataset as dsfrom ops_mindspore import random_maskfrom trainer_mindspore import *from dataset_mindspore import *from inpainting_network_mindspore import *class GenWithLossCell(nn.Cell):    def __init__(self,netG,netD,args,auto_prefix=True):        super(GenWithLossCell,self).__init__(auto_prefix=auto_prefix)        self.netG = netG        self.netD = netD        self.args = args    def construct(self,real,x,mask):           x1,x2,match = self.netG(x,mask)        print('Gen ok')        fake = x2        losses = {}        fake_patched = fake * mask + real * (1-mask)        coarse_alpha = self.args.COARSE_ALPHA        losses['l1_loss'] = coarse_alpha * ops.ReduceMean(False)(ops.Abs()(real - x1) * mask)        losses['l1_loss'] = losses['l1_loss'] + ops.ReduceMean(False)(ops.Abs()(real - x2) * mask)        losses['ae_loss'] = coarse_alpha * ops.ReduceMean(False)(ops.Abs()(real - x1) * (1-mask))        losses['ae_loss'] = losses['ae_loss'] + ops.ReduceMean(False)(ops.Abs()(real - x2) * (1-mask))        losses['ae_loss'] = losses['ae_loss'] / ops.ReduceMean(False)(1 - mask)                real_fake = ops.Concat(0)([real,fake_patched])        if self.args.GAN_WITH_MASK:            real_fake = ops.Concat(3)([real_fake,ops.Tile()(mask,(self.args.BATCH_SIZE*2, 1, 1, 1))])        D_real_fake = self.netD(real_fake)        D_real,D_fake = ops.Split(0,2)(D_real_fake)        g_loss,d_loss = gan_wgan_loss(D_real,D_fake)        losses['g_loss'] = g_loss        losses['g_loss'] = self.args.GAN_LOSS_ALPHA * losses['g_loss']        losses['g_loss'] = losses['g_loss'] + self.args.L1_LOSS_ALPHA * losses['l1_loss']        losses['g_loss'] = losses['g_loss'] + self.args.AE_LOSS_ALPHA * losses['ae_loss']        loss_G = losses['g_loss']        return loss_G        class DisWithLossCell(nn.Cell):    def __init__(self,netG,netD,args,auto_prefix=True):        super(DisWithLossCell,self).__init__(auto_prefix=auto_prefix)        self.netG = netG        self.netD = netD        self.args = args    def construct(self,real,x,mask):        x1,x2,match = self.netG(x,mask)        fake = x2        losses = {}        fake_patched = fake * mask + real * (1-mask)        real_fake = ops.Concat(0)([real,fake_patched])        if self.args.GAN_WITH_MASK:            real_fake = ops.Concat(3)([real_fake,ops.Tile()(mask,(self.args.BATCH_SIZE*2, 1, 1, 1))])        D_real_fake = self.netD(real_fake)        D_real,D_fake = ops.Split(0,2)(D_real_fake)        g_loss,d_loss = gan_wgan_loss(D_real,D_fake)        losses['d_loss'] = d_loss        interps = random_interpolates(real,fake_patched)        D_interps = self.netD(interps)        #gp_loss = gradients_penalty(interps, D_interps, mask=mask)        #losses['gp_loss'] = self.args.WGAN_GP_LAMBDA * gp_loss        #losses['d_loss'] = losses['d_loss'] + losses['gp_loss']        loss_D = losses['d_loss']        return loss_Dclass TrainOneStepCell(nn.Cell):    def __init__(self,netG,netD,optimizerG,optimizerD,args,sens=1.0,auto_prefix=True):        super(TrainOneStepCell,self).__init__(auto_prefix=auto_prefix)        self.args = args        self.netG = netG        self.netG.set_grad()        self.netG.add_flags(defer_inline=True)        self.netD = netD        self.netD.set_grad()        self.netD.add_flags(defer_inline=True)        self.weights_G = optimizerG.parameters        self.optimizerG = optimizerG        self.weights_D = optimizerD.parameters        self.optimizerD = optimizerD        self.grad = C.GradOperation(get_by_list=True,sens_param=True)        self.sens = sens        self.reducer_flag = False        self.grad_reducer_G = F.identity        self.grad_reducer_D = F.identity        self.parallel_mode = _get_parallel_mode()        if self.parallel_mode in (ParallelMode.DATA_PARALLEL,ParallelMode.HYBRID_PARALLEL):            self.reducer_flag = True        if self.reducer_flag:            mean = _get_gradients_mean()            degree = _get_device_num()            self.grad_reducer_G = DistributedGradReducer(self.weights_G,mean,degree)            self.grad_reducer_D = DistributedGradReducer(self.weights_D,mean,degree)    def trainD(self,real,x,mask,loss,loss_net,grad,optimizer,weights,grad_reducer):        sens = P.Fill()(P.DType()(loss),P.Shape()(loss),self.sens)        grads = grad(loss_net,weights)(real,x,mask,sens)  #以real,x,sens为输入构建损失函数,计算loss_net网络中weights的梯度        grads = grad_reducer(grads)        return F.depend(loss,optimizer(grads))    def trainG(self,real,x,mask,loss,loss_net,grad,optimizer,weights,grad_reducer):        sens = P.Fill()(P.DType()(loss),P.Shape()(loss),self.sens)        grads = grad(loss_net,weights)(real,x,mask,sens)        grads = grad_reducer(grads)        return F.depend(loss,optimizer(grads))    def construct(self,real,x,mask):        loss_D = self.netD(real,x,mask)        print('lossD ok ')        loss_G = self.netG(real,x,mask)        print('lossG ok ')        d_out = self.trainD(real,x,mask,loss_D,self.netD,self.grad,self.optimizerD,self.weights_D,self.grad_reducer_D)        g_out = self.trainG(real,x,mask,loss_G,self.netG,self.grad,self.optimizerG,self.weights_G,self.grad_reducer_G)        return d_out,g_outdef GAN_trainer(args):    context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target)    netG = GatedGenerator(args)    netD = Discriminator(args)        netG_with_loss = GenWithLossCell(netG,netD,args)    netD_with_loss = DisWithLossCell(netG,netD,args)        lr = 1e-4    #lr = nn.ExponentialDecayLR(lr,args.lr_decrease_factor,args.lr_decrease_epoch)    #学习率更新    optimizer_G = nn.Adam(netG.get_parameters(),lr,0.5,0.9)      optimizer_D = nn.Adam(netD.get_parameters(),lr,0.5,0.9)        net_train = TrainOneStepCell(netG_with_loss,netD_with_loss,optimizer_G,optimizer_D,args)        net_train.set_train()        dataset_generator = InpaintDataset(args)    dataset = ds.GeneratorDataset(dataset_generator,['image'],num_parallel_workers=args.workers)    dataset = dataset.batch(args.train_batchsize)        for epoch in range(args.Epochs):        mask = random_mask(args)        for image in dataset.create_dict_iterator():            real = image['image']            x = real*(1-mask)                       dout,gout = net_train(real,x,mask)            print('epoch{}batch{},d_loss is {:.4f},g_loss is {:.4f}'.format(epoch+1,batch_idx+1,dout.asnumpy(),gout.asnumpy()))        gen_name = 'generator_epoch%d_batch%d.ckpt' % (epoch + 1, batch)        dis_name = 'discriminator_epoch%d_batch%d.ckpt' % (epoch + 1, batch)        model_name = 'contextual_epoch%d_batch%d.ckpt' % (epoch + 1, batch)        gen_name = os.path.join(args.save_folder, gen_name)         dis_name = os.path.join(args.save_folder, dis_name)         model_name = os.path.join(args.save_folder, model_name)         save_checkpoint(netG,gen_name)        save_checkpoint(netD,dis_name)        save_checkpoint(net_train,model_name)
  • [热门活动] Python编程创造营“瓶瓶罐罐”小结实验任务(1)
    当前有以下需求: 实现一个用于计算(包括加减乘除)的小程序:  接受用户输入的计算式(如:3*4+1.1);  计算值;  将计算过程中涉及到的符号存储在元组中;  将计算中涉及到的值去重后存在列表里面(由大到小排列); 最后将计算过程存在字典里面(如 {"3*4+1.1":13.1} ) 本小白的代码是:numbers_count = input("请输入计算式:")print("您的结果为:", eval(numbers_count))symbol = {"+", "-", "*", "/", "%", "//", "**"}symbol_count = set({})for i in numbers_count:    if i in symbol:        symbol_count.add(i)symbol_tuple = tuple(symbol_count)print(symbol_tuple)numbers_all = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}numbers = set({})for i in numbers_count:    if i in numbers_all:        numbers.add(i)numbers_list = list(numbers)numbers_list.sort(reverse=True)print(numbers_list)numbers_dic = {numbers_count : eval(numbers_count)}print(numbers_dic)输入:5*3+3/4-3-4-5输出结果:请输入计算式:5*3+3/4-3-4-5您的结果为: 3.75('/', '*', '+', '-')['5', '4', '3']{'5*3+3/4-3-4-5': 3.75}本小白的思路是:1.为达成接受用户输入的计算式,需使用input函数2.为计算用户输入值,需使用eval 函数3.为计算过程中涉及到的符号存储在元组中,先创建一个包含所有符号的集合和一个空的集合。通过for和if,遍历用户输入的计算式的每个元素,并判断其是否在包含所有符号的集合中4.为计算中涉及到的值去重后存在列表里面(由大到小排列),与上面的方法类似。但是需额外使用numbers_list.sort(reverse=True),对数字进行排序&为了实现去重,可以将出现的数字放入集合中,最后再将集合转为列表。5为计算过程存在字典里面,需创建字典。作者使用的是x = {'a':'A','b':"B",'c':3}方法,除此之外课上还教了X = dict(a='A',b="B", c=3)和x = dict([("a", "A"),("b", "B"),("c",3)])方法。代码说明:numbers_count = input("请输入计算式:")#获得用户输入值print("您的结果为:", eval(numbers_count))#通过eval函数直接算出结果symbol = {"+", "-", "*", "/", "%", "//", "**"}#创建包含所有符号的集合symbol_count = set({})for i in numbers_count:    if i in symbol:        symbol_count.add(i)#以上为遍历+判断symbol_tuple = tuple(symbol_count)#转为元组类型print(symbol_tuple)numbers_all = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}numbers = set({})for i in numbers_count:    if i in numbers_all:        numbers.add(i)numbers_list = list(numbers)numbers_list.sort(reverse=True)#使用sort函数进行排序print(numbers_list)numbers_dic = {numbers_count : eval(numbers_count)}print(numbers_dic)写在最后,作者本科商科,从未碰过代码。因,研究生专业为区块链技术,不得已开始自学编程。以上帖子仅为作者对该任务的一些粗浅认识,如果其中文字或者代码有误,希望各位大神/大佬/前辈不吝赐教,谢谢!!!
  • [技术干货] python 正则表达式如何实现重叠匹配【转】
    正则表达式实现重叠匹配正则表达式与正则匹配正则表达式正则匹配正则表达式实现重叠匹配1234import regexstring = '100101010001'str_re = '101'print(regex.findall(str_re, string, overlapped=True))普通的re库匹配,只能匹配一个’101’。正则表达式与正则匹配正则表达式正则表达式可理解为对数据筛选的表达式,是有限个原子和元字符组成。原子:基本组成单位,每个表达式至少有一个原子普通字符组成原子 非打印字符组成原子(不打印在输出台的字符)\n:换行\t:tab退格符通用字符组成原子\w:匹配任意字母、数字、下划线\W:与\w相反\d:匹配任意十进制数\D:与\d相反\s:匹配任意空白字符,如空格、换行、缩进\S:与\s相反原子表组成原子一组原子组成一个表,由[]声明表内原子优先级相等,但内容只出现依次若原子表以 ^ 开头,则表示取反12345678910111213141516#普通字符组成原子pat1 = "abcd"  #非打印字符组成原子pat2 = "\n"  #通用字符做原子pat3 = "\w"  #原子表组成原子pat4 = "py[abc]"#可以匹配pya,pyb,pyc,但匹配pyab等原子表重复出现的情况失败  #原子表开头带 ^ 表示取反pat5 = "py[^abc]"#第三个位置匹配除了a,b,c外的任意一个字符元字符:正则表达式中具有特殊含义的字符.匹配任意字符,除了换行符^匹配字符串开始的位置$匹配字符串结束的位置,当出现多组符合的匹配时,返回字符串最后的那组匹配*匹配 0,1,n 次前面的原子【贪婪模式:尽可能多的匹配】?匹配 0,1 次前面的原子【懒惰模式:精确匹配】+匹配 1,n 次前面的原子{ j }前面的原子出现 j 次{ j , }前面的原子至少出现 j 次{ j , k }前面的原子至少出现 j 次,至多出现 k 次i | j匹配 i 或 j ,若 i 与 j 同时出现,匹配 i( )组,限制这组数据的组合如()内所描述一样,只返回符合括号内描述的内容模式修正符即函数中 flag 位置的参数,在不改变正则表达式的情况下改变其含义,调整匹配结果。re.I匹配时忽略大小写re.M多行匹配re.L本地化识别匹配re.U根据unicon字符匹配,影响\w \Wre.S匹配包括换行符正则匹配正则表达式是对字符串进行模糊匹配,其中一个应用为正则匹配。正则匹配是python爬虫的一个使用技术,用于在爬取的文本信息中提取目标信息。正则匹配常用的函数:(调用正则表达式模块re)re.search(pat, str[, flag]):扫描字符串str,返回pat的位置(第一次成功匹配的),flag用于控制正则表达式的匹配方式1234import restr = 'python'pat = 'pytho[a-n]'print(re.search(pat, str))re.match(pat, str[, flag]):扫描字符串str开始的位置,返回pat的位置(第一次成功匹配的),flag用于控制正则表达式的匹配方式【若开始就不符合则结束,返回none】123456import restr_1 = 'hello world'str_2 = 'world hello'pat = 'world'print(re.match(pat, str_1))print(re.match(pat, str_2))re.complie(pat[, flag]):编译正则表达式pat,返回正则表达式对象findall(str[, pos[, endpos]]):匹配所有,用列表返回string中所有匹配到的子串【不止第一次】,pos和endpos可指定在string中的起始位置re.complie(pat).findall(str):全局匹配函数,匹配str中所有符合pat的子串,装入一个列表返回结果12345import restr = "hello world hello world hello world"pat = "hello"print(re.complie(pat).findall(str))print(re.complie(pat).findall(str, 5, 15))re.sub(pat, repl, str[, count[, flag]]):替换字符串中的匹配项【清洗数据】,可用count指定最大替换次数12345import restr = "400-823-823"pat = "-"#短横改空格,最大替换次数2str_new = re.sub(pat, " ", str, count=2)
  • [技术干货] 利用Python和C语言分别实现哈夫曼编码【转】
    目录1.C语言实现1.1代码说明1.2运行结果2.Python实现2.1代码说明2.2运行结果1.C语言实现1.1代码说明a  创建双向链表:在创建哈夫曼树的过程中,需要不断对结点进行更改和删除,所以选用双向链表的结构更容易123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102'''C#include <stdlib.h>#include <stdio.h>#include <windows.h>    //哈夫曼树结构体,数据域存储字符及其权重typedef struct node{    char c;    int weight;    struct node *lchild, *rchild;}Huffman, *Tree;    //双向链表结构体,数据域存储哈夫曼树结点typedef struct list{    Tree root;    struct list *pre;    struct list *next;}List, *pList;    //创建双向链表,返回头结点指针pList creatList(){    pList head = (pList)malloc(sizeof(List));      pList temp1 = head;    pList temp2 = (pList)malloc(sizeof(List));    temp1->pre = NULL;    temp1->next = temp2;    temp1->root = (Tree)malloc(sizeof(Huffman));    temp1->root->c = 'a';    temp1->root->weight = 22;    temp1->root->lchild = NULL;    temp1->root->rchild = NULL;           temp2->pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1->next = temp2;    temp1->root = (Tree)malloc(sizeof(Huffman));    temp1->root->c = 'b';    temp1->root->weight = 5;    temp1->root->lchild = NULL;    temp1->root->rchild = NULL;           temp2->pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1->next = temp2;    temp1->root = (Tree)malloc(sizeof(Huffman));    temp1->root->c = 'c';    temp1->root->weight = 38;    temp1->root->lchild = NULL;    temp1->root->rchild = NULL;      temp2->pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1->next = temp2;    temp1->root = (Tree)malloc(sizeof(Huffman));    temp1->root->c = 'd';    temp1->root->weight = 9;    temp1->root->lchild = NULL;    temp1->root->rchild = NULL;      temp2->pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1->next = temp2;    temp1->root = (Tree)malloc(sizeof(Huffman));    temp1->root->c = 'e';    temp1->root->weight = 44;    temp1->root->lchild = NULL;    temp1->root->rchild = NULL;      temp2->pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1->next = temp2;    temp1->root = (Tree)malloc(sizeof(Huffman));    temp1->root->c = 'f';    temp1->root->weight = 12;    temp1->root->lchild = NULL;    temp1->root->rchild = NULL;      temp2->pre = temp1;    temp1 = temp2;    temp1->next = NULL;    temp1->root = (Tree)malloc(sizeof(Huffman));    temp1->root->c = 'g';    temp1->root->weight = 65;    temp1->root->lchild = NULL;    temp1->root->rchild = NULL;      return head;                          }b创建栈结构:解码过程需要用到两个栈,一个用来存放树结点,一个用来存放码0和1123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115'''C#define STACK_INIT_SIZE 100   //栈初始开辟空间大小#define STACK_INCREMENT 10    //栈追加空间大小  //字符栈结构体,存放编码'0'和'1'typedef struct {    char *base;    char *top;    int size;}charStack;    //栈初始化charStack charStackInit(){    charStack s;    s.base = (char *)malloc(sizeof(char)*STACK_INIT_SIZE);    s.top = s.base;    s.size = STACK_INIT_SIZE;    return s;}  //入栈void charPush(charStack *s, char e){    if(s->top - s->base >= s->size)    {        s->size += STACK_INCREMENT;        s->base = realloc(s->base, sizeof(char)*s->size);    }    *s->top = e;    s->top++;}  //出栈char charPop(charStack *s){    if(s->top != s->base)    {        s->top--;        return *s->top;    }    return -1;}  //得到栈顶元素,但不出栈char charGetTop(charStack *s){    s->top--;    char temp = *s->top;    s->top++;    return temp;}  //栈结构体,存放哈夫曼树结点typedef struct{    Huffman *base;    Huffman *top;    int size;}BiStack;  //栈初始化BiStack stackInit(){    BiStack s;    s.base = (Huffman *)malloc(sizeof(Huffman)*STACK_INIT_SIZE);    s.top = s.base;    s.size =STACK_INIT_SIZE;    return s;}  //入栈void push(BiStack *s, Huffman e){    if(s->top - s->base >= s->size)    {        s->size += STACK_INCREMENT;        s->base = (Huffman *)realloc(s->base, sizeof(Huffman)*s->size);    }    *s->top = e;    s->top++;}  //出栈Huffman pop(BiStack *s){    Huffman temp;    s->top--;    temp = *s->top;    return temp;}  //得到栈顶元素,但不出栈Huffman getTop(BiStack s){    Huffman temp;    s.top--;    temp = *s.top;    return temp;}  char stack[7][10];             //记录a~g的编码//遍历栈,得到字符c的编码void traverseStack(charStack s, char c){    int index = c - 'a';     int i = 0;    while(s.base != s.top)    {        stack[index][i] = *s.base;        i++;        s.base++;    }}c 创建哈夫曼树:123456789101112131415161718192021222324252627282930313233343536373839404142434445'''C//通过双向链表创建哈夫曼树,返回根结点指针Tree creatHuffman(pList head){    pList list1 = NULL;    pList list2 = NULL;    pList index = NULL;    Tree root = NULL;    while(head->next != NULL)   //链表只剩一个结点时循环结束,此结点数据域即为哈夫曼树的根结点    {        list1 = head;        list2 = head->next;        index = list2->next;        root = (Tree)malloc(sizeof(Huffman));        while(index != NULL)    //找到链表中权重最小的两个结点list1,list2        {            if(list1->root->weight > index->root->weight || list2->root->weight > index->root->weight)            {                if(list1->root->weight > list2->root->weight) list1 = index;                else list2 = index;            }            index = index->next;        }        //list1和list2设为新结点的左右孩子        if(list2->root->weight > list1->root->weight)        {            root->lchild = list1->root;            root->rchild = list2->root;        }        else        {            root->lchild = list2->root;            root->rchild = list1->root;        }        //新结点字符统一设为空格,权重设为list1与list2权重之和        root->c = ' ';        root->weight = list1->root->weight + list2->root->weight;        //list1数据域替换成新结点,并删除list2        list1->root = root;        list2->pre->next = list2->next;        if(list2->next != NULL)            list2->next->pre = list2->pre;        }    return head->root;}d编码:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869'''Cchar stack[7][10];             //记录a~g的编码//遍历栈,得到字符c的编码void traverseStack(charStack s, char c){    int index = c - 'a';     int i = 0;    while(s.base != s.top)    {        stack[index][i] = *s.base;        i++;        s.base++;    }}    //通过哈夫曼树编码void encodeHuffman(Tree T){      BiStack bs = stackInit();    charStack cs = charStackInit();    Huffman root = *T;      Tree temp = NULL;    push(&bs, root);      //根结点入栈    while(bs.top != bs.base)      //栈空表示遍历结束    {        root = getTop(bs);        temp = root.lchild;       //先访问左孩子        while(temp != NULL)       //左孩子不为空        {            //将结点左孩子设为空,代表已访问其左孩子            root.lchild = NULL;            pop(&bs);                        push(&bs, root);            //左孩子入栈            root = *temp;            temp = root.lchild;            push(&bs, root);            //'0'入字符栈            charPush(&cs, '0');        }        temp = root.rchild;     //后访问右孩子             while(temp == NULL)     //右孩子为空,代表左右孩子均已访问,结点可以出栈         {            //结点出栈            root = pop(&bs);            //寻到叶子结点,可以得到结点中字符的编码            if(root.c != ' ')                traverseStack(cs, root.c);            charPop(&cs);       //字符栈出栈            if(bs.top == bs.base) break;    //根结点出栈,遍历结束            //查看上一级结点是否访问完左右孩子              root = getTop(bs);            temp = root.rchild;                   }        if(bs.top != bs.base)        {            //将结点右孩子设为空,代表已访问其右孩子            root.rchild = NULL;                   pop(&bs);            push(&bs, root);            //右孩子入栈            root = *temp;                  push(&bs, root);            //'1'入字符栈            charPush(&cs, '1');        }        }}e解码:1234567891011121314151617181920212223242526'''Cchar decode[100];   //记录解码得到的字符串//通过哈夫曼树解码void decodeHuffman(Tree T, char *code){    int cnt = 0;    Tree root;    while(*code != '\0')                  //01编码字符串读完,解码结束    {        root = T;        while(root->lchild != NULL)       //找到叶子结点        {            if(*code != '\0')            {                if(*code == '0')                    root = root->lchild;                else                    root = root->rchild;                code++;            }            else break;        }        decode[cnt] = root->c;             //叶子结点存放的字符即为解码得到的字符        cnt++;    }}f主函数:123456789101112131415161718192021222324'''Cvoid main(){    pList pl = creatList();    printf("字符的权重如下\n");    for(pList l = pl; l->next != NULL; l = l->next)        printf("字符%c的权重是 %d\n", l->root->c, l->root->weight);    Tree T = creatHuffman(pl);    encodeHuffman(T);    printf("\n\n字符编码结果如下\n");    for(int i = 0; i < 7; i++)        printf("%c : %s\n", i+'a', stack[i]);    char code[100];    printf("\n\n请输入编码:\n");    scanf("%s", code);    printf("解码结果如下:\n");    decodeHuffman(T, code);    printf("%s\n", decode);    printf("\n\n");    system("date /T");    system("TIME /T");    system("pause");    exit(0); }2.Python实现2.1代码说明a创建哈夫曼树:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253#coding=gbk  import datetimeimport timefrom pip._vendor.distlib.compat import raw_input  #哈夫曼树结点类class Huffman:    def __init__(self, c, weight):        self.c = c        self.weight = weight        self.lchild = None        self.rchild = None         #创建结点左右孩子        def creat(self, lchild, rchild):        self.lchild = lchild        self.rchild = rchild  #创建列表        def creatList():    list = []    list.append(Huffman('a', 22))    list.append(Huffman('b', 5))    list.append(Huffman('c', 38))    list.append(Huffman('d', 9))    list.append(Huffman('e', 44))    list.append(Huffman('f', 12))    list.append(Huffman('g', 65))    return list  #通过列表创建哈夫曼树,返回树的根结点def creatHuffman(list):    while len(list) > 1:               #列表只剩一个结点时循环结束,此结点即为哈夫曼树的根结点        i = 0        j = 1        k = 2        while k < len(list):           #找到列表中权重最小的两个结点list1,list2                      if list[i].weight > list[k].weight or list[j].weight > list[k].weight:                if list[i].weight > list[j].weight:                    i = k                else:                    j = k            k += 1              root = Huffman(' ', list[i].weight + list[j].weight) #新结点字符统一设为空格,权重设为list1与list2权重之和           if list[i].weight < list[j].weight:                  #list1和list2设为新结点的左右孩子            root.creat(list[i], list[j])        else:            root.creat(list[j], list[i])        #list1数据域替换成新结点,并删除list2        list[i] = root        list.remove(list[j])    return list[0]b编码:12345678910111213141516171819202122232425262728293031323334353637#通过哈夫曼树编码def encodeHuffman(T):    code = [[], [], [], [], [], [], []]    #列表实现栈结构    treeStack = []    codeStack = []    treeStack.append(T)    while treeStack != []:        #栈空代表遍历结束        root = treeStack[-1]        temp = root.lchild        while temp != None:            #将结点左孩子设为空,代表已访问其左孩子            root.lchild = None                   #左孩子入栈                      treeStack.append(temp)                     root = temp            temp = root.lchild            #0入编码栈            codeStack.append(0)        temp = root.rchild            #后访问右孩子        while temp == None:           #右孩子为空,代表左右孩子均已访问,结点可以出栈            root = treeStack.pop()           #结点出栈            #寻到叶子结点,可以得到结点中字符的编码            if root.c != ' ':                codeTemp = codeStack.copy()                code[ord(root.c) - 97] = codeTemp                 if treeStack == []:    #根结点出栈,遍历结束                break            codeStack.pop()        #编码栈出栈            #查看上一级结点是否访问完左右孩子            root = treeStack[-1]            temp = root.rchild        if treeStack != []:            treeStack.append(temp)     #右孩子入栈            root.rchild = None         #将结点右孩子设为空,代表已访问其右孩子            codeStack.append(1)        #1入编码栈    return code c解码:1234567891011121314151617#通过哈夫曼树解码def decodeHuffman(T, strCode):    decode = []    index = 0    while index < len(strCode):        #01编码字符串读完,解码结束        root = T        while root.lchild != None:     #找到叶子结点            if index < len(strCode):                if strCode[index] == '0':                    root = root.lchild                else:                    root = root.rchild                index += 1            else:                break        decode.append(root.c)           #叶子结点存放的字符即为解码得到的字符    return decoded主函数:12345678910111213141516171819202122232425if __name__ == '__main__':    list = creatList()    print("字符的权重如下")    for i in range(len(list)):        print("字符{}的权重为: {}".format(chr(i+97), list[i].weight))    T = creatHuffman(list)    code = encodeHuffman(T)    print("\n字符编码结果如下")    for i in range(len(code)):        print(chr(i+97), end=' : ')        for j in range(len(code[i])):            print(code[i][j], end='')        print("")    strCode = input("\n请输入编码:\n")    #哈夫曼树在编码时被破坏,必须重建哈夫曼树    list = creatList()    T = creatHuffman(list)    decode = decodeHuffman(T, strCode)    print("解码结果如下:")    for i in range(len(decode)):        print(decode[i], end='')    print("\n\n")    datetime = datetime.datetime.now()    print(datetime.strftime("%Y-%m-%d\n%H:%M:%S"))    input("Press Enter to exit…")
  • [技术干货] Python中闭包与lambda的作用域解析【转】
    目录Python闭包与lambda的作用域python当中的坑(闭包与lambda)先来看一个栗子Python闭包与lambda的作用域lambda写法123456def fun():    for i in range(3):        yield lambda x : x * i f0, f1, f2 = fun()print(f0(1), f1(2), f2(3))闭包的写法123456789def fun():    result = []    for i in range(3):        def demo(x):            return x * i        result.append(demo)    return resultf0, f1, f2 = fun()print(f0(1), f1(2), f2(3))上面两种写法的结果都是2,4,6,按最初的想法结果应该是0,2,6。问题原因:问题的本事在python的变量查找规则,LEGB(local,enclousing,global,bulitin),上面的例子中,i就是在闭包作用域(enclousing),而Python的闭包是迟绑定,闭包中用到的变量i的值,是在内部函数被调用时查找到的。解决办法将闭包作用域变为局部作用域lambda写法123456def fun():    for i in range(3):        yield lambda x, i = i: x * i f0, f1, f2 = fun()print(f0(1), f1(2), f2(3))闭包写法123456789def fun():    result = []    for i in range(3):        def demo(x, i=i):            return x * i        result.append(demo)    return resultf0, f1, f2 = fun()print(f0(1), f1(2), f2(3))以上输出结果0,2,6另一种情况:12345def fun():    for i in range(3):        yield lambda x : x * if0, f1, f2 = fun()print(f0(1), f1(2), f2(3))输出结果还是2,4,6问题原因fun()方法返回的生成器(或迭代器),并没有真正的执行,而是在每次调用的时候进行执行。在遍历后执行打印时,i这个变量使用的是最后调用的值。将lambda看作闭包方法的话,变量i值还是闭包作用域(no local)python当中的坑(闭包与lambda)先来看一个栗子12345def create():    return [lambda x:i*x for i in range(5)]  for i in create():    print(i(2))结果:88888create函数的返回值时一个列表,列表的每一个元素都是一个函数 -- 将输入参数x乘以一个倍数i的函数。预期的结果时0,2,4,6,8. 但结果是5个8,意外不意外。由于出现这个陷阱的时候经常使用了lambda,所以可能会认为是lambda的问题,但lambda表示不愿意背这个锅。问题的本质在与python中的属性查找规则,LEGB(local,enclousing,global,bulitin),在上面的例子中,i就是在闭包作用域(enclousing),而Python的闭包是 迟绑定 , 这意味着闭包中用到的变量的值,是在内部函数被调用时查询得到的解决办法也很简单,那就是变闭包作用域为局部作用域。12345def create():    return [lambda x, i=i:i*x for i in range(5)]  for i in create():    print(i(2))换种写法:12345678910def create():    a = []    for i in range(5):        def demo(x, i=i):            return x*i        a.append(demo)    return a  for i in create():    print(i(2))以上两种写法是一样的结果:02468再来一个问题相似的栗子代码很简单:(声明:python3问题)1234nums = range(2,20)for i in nums:    nums = filter(lambda x: x==i or x%i, nums)print(list(nums))结果:[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]同样按照正常的逻辑结果应该为:[2, 3, 5, 7, 11, 13, 17, 19]问题产生的原因:在python3当中filter()函数返回的是一个迭代器,因此并没有做真正的执行,而是在每次调用的时候执行(python2中filter()返回的值列表,无此现象)在遍历后执行打印时,现在执行循环当中的函数,同上面一个栗子的问题,i这个变量使用的是最后调用时的值,与以上栗子不同的是以上栗子用的是内嵌作用域的值,而这个栗子用的是全局i的值修改代码:1234nums = range(2,20)for i in nums:    nums = filter(lambda x,i=i: x==i or x%i, nums)print(list(nums))结果:[2, 3, 5, 7, 11, 13, 17, 19]
  • [技术干货] Python实现读取HTML表格 pd.read_html()【转】
    目录Python读取HTML表格pd.read_html读取数据不完整问题解决办法Python读取HTML表格数据部门提供的数据是xls格式的文件,但是执行读取xls文件的脚本报错。xlrd报错:xlrd.biffh.XLRDError: Unsupported format, or corrupt file: Expected BOF record; found b'<html xm'读取xlrd的脚本123456789101112131415161718data_lines = read_excel_file(self.file_path) def read_excel_file(file_path):    """    读取excel文件    """    import xlrd    print('[Info] excel file: {}'.format(file_path))    book = xlrd.open_workbook(file_path)    sheet = book.sheet_by_index(0)    data_lines = []    for row in range(0, sheet.nrows):        line_data = []        for column in range(0, sheet.ncols):            val = sheet.cell(row, column).value            line_data.append(val)        data_lines.append(line_data)    return data_lines  # 二维数组原因是文件格式是HTML表格,参考python xlrd unsupported format, or corrupt file.使用pandas的read_html读取文件,同时替换nan为空字符,数据格式保持一致。1234567891011121314151617def read_html_table(file_path):    """    读取html表格    """    import pandas as pd    pd_table = pd.read_html(file_path)    df = pd_table[0]    # num_col = df.shape[1]    # num_row = df.shape[0]    df_data = df.values.tolist()    df_data = df_data[1:]    for r_idx, row in enumerate(df_data):        for c_idx, value in enumerate(row):            # 判断nan,参考https://stackoverflow.com/questions/944700/how-can-i-check-for-nan-values            if value != value:                df_data[r_idx][c_idx] = ""    return df_data读取问题解决。pd.read_html读取数据不完整问题问题:有一个较大的表格数据存在了html中,打算用read_html直接取出来这部分数据,但后来发现read_html读取的数据不完整,后来检查html的table都没有任何问题解决办法pd.read_html的默认解析器为 'lxml' ,添加参数flavor='bs4'便可解决
  • [技术干货] Python轻量级搜索工具Whoosh的使用教程【转】
    目录Whoosh简介Index & query示例代码数据字段创建索引文件查询本文将简单介绍Python中的一个轻量级搜索工具Whoosh,并给出相应的使用示例代码。Whoosh简介Whoosh由Matt Chaput创建,它一开始是一个为Houdini 3D动画软件包的在线文档提供简单、快速的搜索服务工具,之后便慢慢成为一个成熟的搜索解决工具并已开源。Whoosh纯由Python编写而成,是一个灵活的,方便的,轻量级的搜索引擎工具,现在同时支持Python2、3,其优点如下:Whoosh纯由Python编写而成,但很快,只需要Python环境即可,不需要编译器;默认使用 Okapi BM25F排序算法,也支持其他排序算法;相比于其他搜索引擎,Whoosh会创建更小的index文件;Whoosh中的index文件编码必须是unicode;Whoosh可以储存任意的Python对象。Whoosh的官方介绍网站为:https://whoosh.readthedocs.io/en/latest/intro.html。相比于ElasticSearch或者Solr等成熟的搜索引擎工具,Whoosh显得更轻便,操作更简单,可以考虑在小型的搜索项目中使用。Index & query对于熟悉ES的人来说,搜索的两个重要的方面为mapping和query,也就是索引的构建以及查询,背后是复杂的索引储存、query解析以及排序算法等。如果你有ES方面的经验,那么,对于Whoosh是十分容易上手的。按照笔者的理解以及Whoosh的官方文档,Whoosh的入门使用主要是index以及query。搜索引擎的强大功能之一在于它能够提供全文检索,这依赖于排序算法,比如BM25,也依赖于我们怎样储存字段。因此,index作为名词时,是指字段的索引,index作为动词时,是指建立字段的索引。而query会将我们需要查询的语句,通过排序算法,给出合理的搜索结果。关于Whoosh的使用,在官文文档中已经给出了详细的说明,笔者在这里只给出一个简单的例子,来说明Whoosh如何能方便地提升我们的搜索体验。示例代码数据本项目的示例数据为poem.csv,下图为该数据集的前十行:poem.csv字段根据数据集的特征,我们创建四个字段(fields):title, dynasty, poet, content。创建的代码如下:12345678910111213# -*- coding: utf-8 -*-import osfrom whoosh.index import create_infrom whoosh.fields import *from jieba.analyse import ChineseAnalyzerimport json # 创建schema, stored为True表示能够被检索schema = Schema(title=TEXT(stored=True, analyzer=ChineseAnalyzer()),                dynasty=ID(stored=True),                poet=ID(stored=True),                content=TEXT(stored=True, analyzer=ChineseAnalyzer())                )其中,ID只能为一个单元值,不能分割为若干个词,常用于文件路径、URL、日期、分类;TEXT文件的文本内容,建立文本的索引并存储,支持词汇搜索;Analyzer选择结巴中文分词器。创建索引文件接着,我们需要创建索引文件。我们利用程序先解析poem.csv文件,并将它转化为index,写入到indexdir目录下。Python代码如下:12345678910111213141516# 解析poem.csv文件with open('poem.csv', 'r', encoding='utf-8') as f:    texts = [_.strip().split(',') for _ in f.readlines() if len(_.strip().split(',')) == 4] # 存储schema信息至indexdir目录indexdir = 'indexdir/'if not os.path.exists(indexdir):    os.mkdir(indexdir)ix = create_in(indexdir, schema) # 按照schema定义信息,增加需要建立索引的文档writer = ix.writer()for i in range(1, len(texts)):    title, dynasty, poet, content = texts[i]    writer.add_document(title=title, dynasty=dynasty, poet=poet, content=content)writer.commit()index创建成功后,会生成indexdir目录,里面含有上述poem.csv数据的各个字段的索引文件。查询index创建成功后,我们就利用进行查询。比如我们想要查询content中含有明月的诗句,可以输入以下代码:12345678# 创建一个检索器searcher = ix.searcher() # 检索content中出现'明月'的文档results = searcher.find("content", "明月")print('一共发现%d份文档。' % len(results))for i in range(min(10, len(results))):    print(json.dumps(results[i].fields(), ensure_ascii=False))输出结果如下:一共发现44份文档。前10份文档如下:{"content": "床前明月光,疑是地上霜。举头望明月,低头思故乡。", "dynasty": "唐代", "poet": "李白 ", "title": "静夜思"}{"content": "边草,边草,边草尽来兵老。山南山北雪晴,千里万里月明。明月,明月,胡笳一声愁绝。", "dynasty": "唐代", "poet": "戴叔伦 ", "title": "调笑令·边草"}{"content": "独坐幽篁里,弹琴复长啸。深林人不知,明月来相照。", "dynasty": "唐代", "poet": "王维 ", "title": "竹里馆"}{"content": "汉江明月照归人,万里秋风一叶身。休把客衣轻浣濯,此中犹有帝京尘。", "dynasty": "明代", "poet": "边贡 ", "title": "重赠吴国宾"}{"content": "秦时明月汉时关,万里长征人未还。但使龙城飞将在,不教胡马度阴山。", "dynasty": "唐代", "poet": "王昌龄 ", "title": "出塞二首·其一"}{"content": "京口瓜洲一水间,钟山只隔数重山。春风又绿江南岸,明月何时照我还?", "dynasty": "宋代", "poet": "王安石 ", "title": "泊船瓜洲"}{"content": "四顾山光接水光,凭栏十里芰荷香。清风明月无人管,并作南楼一味凉。", "dynasty": "宋代", "poet": "黄庭坚 ", "title": "鄂州南楼书事"}{"content": "青山隐隐水迢迢,秋尽江南草未凋。二十四桥明月夜,玉人何处教吹箫?", "dynasty": "唐代", "poet": "杜牧 ", "title": "寄扬州韩绰判官"}{"content": "露气寒光集,微阳下楚丘。猿啼洞庭树,人在木兰舟。广泽生明月,苍山夹乱流。云中君不见,竟夕自悲秋。", "dynasty": "唐代", "poet": "马戴 ", "title": "楚江怀古三首·其一"}{"content": "海上生明月,天涯共此时。情人怨遥夜,竟夕起相思。灭烛怜光满,披衣觉露滋。不堪盈手赠,还寝梦佳期。", "dynasty": "唐代", "poet": "张九龄 ", "title": "望月怀远 / 望月怀古"}
  • [技术干货] Python实现邮件自动下载的示例详解【转】
    开始码代码之前,我们先来了解一下三种邮件服务协议:1、SMTP协议SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议。相当于中转站,将邮件发送到客户端。2、POP3协议POP3(Post Office Protocol 3),即邮局协议的第3个版本,是电子邮件的第一个离线协议标准。该协议把邮件下载到本地计算机,不与服务器同步,缺点是更易丢失邮件或多次下载相同的邮件。3、IMAP协议IMAP(Internet Mail Access Protocol),即交互式邮件存取协议。该协议连接远程邮箱直接操作,与服务器内容同步。然后介绍一下email包这个包的中心组件是代表电子邮件消息的“对象模型”。 应用程序主要通过在 message 子模块中定义的对象模型接口与这个包进行交互。 应用程序可以使用此 API 来询问有关现有电子邮件的问题、构造新的电子邮件,或者添加或移除自身也使用相同对象模型接口的电子邮件子组件。 也就是说,遵循电子邮件消息及其 MIME 子组件的性质,电子邮件对象模型是所有提供 EmailMessage API 的对象所构成的树状结构。接下来我们通过具体的代码实现一个登录邮箱客户端,下载邮件,解析邮件附件内容的功能。首先我们需要定义一个邮件解析的类,该类需要三个变量:1、邮箱所属的imap服务地址;2、邮箱账号;3、邮箱密码【注:不同邮箱需要不同的安全策略,例如qq邮箱需要短信验证,获取登录授权码,而不是明文密码去登录远程客户端】123456789class Email_parse:     def __init__(self,remote_server_url,email_url,password):        # imap服务地址        self.remote_server_url = remote_server_url        # 邮箱账号        self.email_url = email_url        # 邮箱密码        self.password = password然后定义类中入口函数,登录远程,默认获取第一页所有的邮件。我们获取邮件的主题,并打印出来【不同邮件主题的编码可能不同,二进制需要转码才能正确显示】12345678910111213141516171819202122def main_parse_Email(self):    """入口函数,登录imap服务"""    server = imaplib.IMAP4_SSL(self.remote_server_url, 993)    server.login(self.email_url, self.password)    server.select('INBOX')    status,data = server.search(None,"ALL")    if status != 'OK':        raise Exception('read email error')    emailids = data[0].split()    mail_counts = len(emailids)    print("count:",mail_counts)    # 邮件的遍历是按时间从后往前,这里我们选择最新的一封邮件    for i in range(mail_counts - 1, mail_counts - 2, -1):        status, edata = server.fetch(emailids[i], '(RFC822)')        msg = email.message_from_bytes(edata[0][1])        #获取邮件主题title        subject = email.header.decode_header(msg.get('subject'))        if type(subject[-1][0]) == bytes:            title = subject[-1][0].decode(str(subject[-1][1]))        elif type(subject[-1][0]) == str:            title = subject[-1][0]        print("title:", title)其中,msg变量保存的就是邮件的主体,接下来因为会重复用到msg和tilte,我们将构造一个类函数返回msg和title。12345678def get_email_title(msg):    subject = email.header.decode_header(msg.get('subject'))    if type(subject[-1][0]) == bytes:        title = subject[-1][0].decode(str(subject[-1][1]))    elif type(subject[-1][0]) == str:        title = subject[-1][0]    print("title:", title)    return title解析邮件,我们分为两部分,邮件正文【HTML】和附件【xlsx等】,判断有附件,我们就保存到固定的路径下。表格的解析不再赘述了,pandas之类的包足以搞定。12345678910111213def get_att(msg):    """获取附件并下载"""    filename = Email_parse.get_email_name(msg)    for part in msg.walk():        file_name = part.get_param("name")        if file_name:            data = part.get_payload(decode=True)            if data != None:                att_file = open('./src/' + filename, 'wb')                att_file.write(data)                att_file.close()            else:                pass邮件正文内容,我们直接解析html,将文本内容直接保存到.txt文件中,方便读取。12345678910111213def get_text_from_HTML(msg):    """获取邮件中的html"""    filename = Email_parse.get_email_name(msg)    current_title = Email_parse.get_email_title(msg)    print("filename:",filename,type(filename))    for part in msg.walk():        if not part.is_multipart():            result = part.get_payload(decode=True)            result = result.decode('gbk')            f = open(f'./src/{current_title}.txt','w')            f.write(result)            f.close()            return result完整代码如下:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293import emailimport imaplibfrom email.header import decode_headerimport pandas as pdimport datetime  class Email_parse:    def __init__(self,remote_server_url,email_url,password):        self.remote_server_url = remote_server_url        self.email_url = email_url        self.password = password     def get_att(msg):        filename = Email_parse.get_email_name(msg)        for part in msg.walk():            file_name = part.get_param("name")            if file_name:                data = part.get_payload(decode=True)                if data != None:                    att_file = open('./src/' + filename, 'wb')                    att_file.write(data)                    att_file.close()                else:                    pass     def get_email_title(msg):        subject = email.header.decode_header(msg.get('subject'))        if type(subject[-1][0]) == bytes:            title = subject[-1][0].decode(str(subject[-1][1]))        elif type(subject[-1][0]) == str:            title = subject[-1][0]        print("title:", title)        return title      def get_email_name(msg):        for part in msg.walk():            file_name = part.get_param("name")            if file_name:                h = email.header.Header(file_name)                dh = email.header.decode_header(h)                filename = dh[0][0]                if dh[0][1]:                    value, charset = decode_header(str(filename, dh[0][1]))[0]                    if charset:                        filename = value.decode(charset)                        print("附件名称:", filename)                        return filename      def main_parse_Email(self):        server = imaplib.IMAP4_SSL(self.remote_server_url, 993)        server.login(self.email_url, self.password)        server.select('INBOX')        status,data = server.search(None,"ALL")        if status != 'OK':            raise Exception('read email error')        emailids = data[0].split()        mail_counts = len(emailids)        print("count:",mail_counts)        for i in range(mail_counts - 1, mail_counts - 2, -1):            status, edata = server.fetch(emailids[i], '(RFC822)')            msg = email.message_from_bytes(edata[0][1])            subject = email.header.decode_header(msg.get('subject'))            if type(subject[-1][0]) == bytes:                title = subject[-1][0].decode(str(subject[-1][1]))            elif type(subject[-1][0]) == str:                title = subject[-1][0]            print("title:", title)            Email_parse.get_att(msg)            Email_parse.get_text_from_HTML(msg)      def get_text_from_HTML(msg):        filename = Email_parse.get_email_name(msg)        current_title = Email_parse.get_email_title(msg)        print("filename:",filename,type(filename))        for part in msg.walk():            if not part.is_multipart():                result = part.get_payload(decode=True)                result = result.decode('gbk')                f = open(f'./src/{current_title}.txt','w')                f.write(result)                f.close()                return result if __name__ == "__main__":    remote_server_url = 'imap.qq.com'    email_url = "*********@qq.com"    password = "**********"    demo = Email_parse(remote_server_url,email_url,password)    demo.main_parse_Email()
  • [技术干货] python+selenium 实现扫码免密登录示例代码【转】
    目录一、需求描述二、首先扫码登录获取cookies保存到本地未后面免密登录做准备三、初始化浏览器四、获取本地保存的cookies实现登录一、需求描述web 自动化测试/python爬虫往往会遇到扫码登录的情况,不是所有的网站都支持用户密码登录,遇到这种扫码登录的情况会阻碍我们自动化测试/爬虫的进行,所有为了可以顺畅的进行我们的需求,在进行自动化或者爬虫前我们首先要解决扫码登录的问题,下面讲解如何实现扫码免密登录。二、首先扫码登录获取cookies保存到本地未后面免密登录做准备具体实现代码如下:12345678910111213141516def get_cookies():    # 首先获取cookies保存至本地    driver = webdriver.Chrome('/Users/xxx/Documents/python/pack/chromedriver/chromedriver')    page_url = 'https:/xxx/38268919/bugtrace/buglists/query/1/created/desc?query_token=20220706291334df28c613a85aa589f04376d034'    driver.get(page_url)    driver.maximize_window()    # 进行扫码登录    time.sleep(20)    # 获取列表形式的cookies    cookies = driver.get_cookies()    # 转换成字符串保存    jsonCookie = json.dumps(cookies)    # 保存到txt文件    with open('cookies.txt','w') as f:        f.write(jsonCookie)    print('cookies保存成功!')三、初始化浏览器123456def browser_initial():    driver = webdriver.Chrome('/Users/xxx/Documents/python/pack/chromedriver/chromedriver')    page_url = 'https://xxx/38268919/bugtrace/buglists/query/1/created/desc?query_token=20220706291334df28c613a85aa589f04376d034'    driver.get(page_url)    driver.maximize_window()    return driver四、获取本地保存的cookies实现登录代码实现如下123456789101112131415161718def login(driver):    with open('cookies.txt','r',encoding='utf8') as f:        cookies = json.loads(f.read())    # 给浏览器添加cookies    for cookie in cookies:        cookie_dict = {            'domain': '.tapd.cn',            'name': cookie.get('name'),            'value': cookie.get('value'),            "expiry": 1658386136,            'path': '/',            'httpOnly': True,            'Secure': True        }        # print(cookie_dict)        driver.add_cookie(cookie_dict)    # 刷新网页,cookies才会成功    driver.refresh()12345if __name__ =='__main__': driver=browser_initial() login(driver)
  • [技术干货] 利用Python自动生成PPT的示例详解【转】
    在日常工作中,PPT制作是常见的工作,如果制作创意类PPT,则无法通过自动化的形式生成,因为创意本身具有随机性,而自动化解决的是重复性工作,两者有所冲突。python-pptx是python处理PPT的一个库,注重的是读和写,无法导出,没有渲染功能。废话不多说,第一步,安装python-pptx库:1pip3 install -i https://pypi.doubanio.com/simple/ python-pptxppt里面处理的主要对象一般为文本框,表格,图片。每一页的ppt为一个slide123456from pptx import Presentation, utilfrom pptx.util import Pt,Cmfrom pptx.shapes.picture import Picture#实例化一个ppt对象ppt = Presentation("./test.pptx")slide = ppt.slides[0] #第几页然后遍历查看这一页ppt中都包含哪些对象:123456789101112131415161718192021222324252627282930313233def rander_template(slide):    for shape in slide.shapes:        if shape.has_text_frame == True:            print("==========================文本框=============================")            print("段落长度:",len(shape.text_frame.paragraphs))            for paragraph in shape.text_frame.paragraphs:                # 拼接文字                print("段落包含字段:",len(paragraph.runs))                print(''.join(run.text for run in paragraph.runs))                for i in range(len(paragraph.runs)):                    print("run"+str(i)+":"+paragraph.runs[i].text)            print(shape.text_frame.paragraphs[0].runs[0].text)            shape.text_frame.paragraphs[0].runs[0].text = "规则是自由的第一要义"        elif shape.has_table == True:            print("==========================表格==============================")            one_table_data = []            for row in shape.table.rows:  # 读每行                row_data = []                for cell in row.cells:  # 读一行中的所有单元格                    cell.text = cell.text if cell.text != "" else "未填写"                    c = cell.text                    row_data.append(c)                one_table_data.append(row_data)  # 把每一行存入表            # 用二维列表输出表格行和列的数据            print(one_table_data)            print("第一个单元格内容:",shape.table.rows[0].cells[0].text)         elif isinstance(shape,Picture):            print("==========================图片==============================")            index = 0            with open(f'{index}.jpg','wb') as f:                f.write(shape.image.blob)                index += 1文本框对象【text_frame】:shape.has_text_frame查看是否有文本框对象,有的话查看具体有几个段落【len(shape.text_frame.paragraphs)】,每个段落又有多少个run对象【len(paragraph.runs)】注意:修改run对象的时候,修改run[0],后面的值都会被覆盖。表格对象【table】:table对象还是按照行列值来定位划分的,eg:table.rows[2]cells[3].text代表第三行第四列的值图片对象【Picture】:插入图片需要固定图片的位置,比如:def insert_pic(slide):    #需要用到pptx库的util方法    img_path = './blue.png'  # 图片路径    # 设置图片的位置和大小    left = util.Cm(8.04)    top = util.Cm(9.93)    width = util.Cm(15.07)    height = util.Cm(4.06)    # 在页面中插入图片    slide.shapes.add_picture(img_path, left, top, width, height)全部代码:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354from pptx import Presentation, utilfrom pptx.util import Pt,Cmfrom pptx.shapes.picture import Pictureppt = Presentation("./test.pptx") def rander_template(slide):    for shape in slide.shapes:        if shape.has_text_frame == True:            print("==========================文本框=============================")            print("段落长度:",len(shape.text_frame.paragraphs))            for paragraph in shape.text_frame.paragraphs:                # 拼接文字                print("段落包含字段:",len(paragraph.runs))                print(''.join(run.text for run in paragraph.runs))                for i in range(len(paragraph.runs)):                    print("run"+str(i)+":"+paragraph.runs[i].text)            print(shape.text_frame.paragraphs[0].runs[0].text)            shape.text_frame.paragraphs[0].runs[0].text = "规则是自由的第一要义"        elif shape.has_table == True:            print("==========================表格==============================")            one_table_data = []            for row in shape.table.rows:  # 读每行                row_data = []                for cell in row.cells:  # 读一行中的所有单元格                    cell.text = cell.text if cell.text != "" else "未填写"                    c = cell.text                    row_data.append(c)                one_table_data.append(row_data)  # 把每一行存入表            # 用二维列表输出表格行和列的数据            print(one_table_data)            print("第一个单元格内容:",shape.table.rows[0].cells[0].text)         elif isinstance(shape,Picture):            print("==========================图片==============================")            index = 0            with open(f'{index}.jpg','wb') as f:                f.write(shape.image.blob)                index += 1def insert_pic(slide):    img_path = './blue.png'  # 图片路径    # 设置图片的位置和大小    left = util.Cm(8.04)    top = util.Cm(9.93)    width = util.Cm(15.07)    height = util.Cm(4.06)    # 在页面中插入图片    slide.shapes.add_picture(img_path, left, top, width, height)  if __name__ == "__main__":    slide = ppt.slides[0] #第几页    rander_template(slide)    insert_pic(slide)    ppt.save('new.pptx')  # 保存为文件
  • [技术干货] Python的flask常用函数route()【转】
    目录一、route()路由概述二、静态路由和动态路径方式1:静态路由方式2:动态路由三、route()其它参数1.methods=[‘GET’,‘POST’]一、route()路由概述功能:将URL绑定到函数路由函数route()的调用有两种方式:静态路由和动态路由二、静态路由和动态路径方式1:静态路由@app.route(“/xxx”) xxx为静态路径 如::/index / /base等,可以返回一个值、字符串、页面等12345678910111213from flask import Flaskapp = Flask(__name__) @app.route('/hello')def hello_world():    return 'Hello World!!!'     @app.route('/pro')def index():    return render_template('login.html') if __name__ == '__main__':    app.run(debug = True)方式2:动态路由采用<>进行动态url的传递@app.route(“/”),这里xxx为不确定的路径。123456789from flask import Flaskapp = Flask(__name__) @app.route('/hello/<name>')def hello_name(name):   return 'Hello %s!' % name if __name__ == '__main__':   app.run(debug = True)如果浏览器地址栏输入:http:// localhost:5000/hello/w3cschool则会在页面显示:Hello w3cschool!三、route()其它参数1.methods=[‘GET’,‘POST’]当前视图函数支持的请求方式,不设置默认为GET请求方式不区分大小写methods=[‘GET’] 支持的请求方法为GETmethods=[‘POST’] 支持的请求方法为POSTmethods=[‘GET’,‘POST’] 支持的请求方法为POST GET123456789101112@app.route('/login', methods=['GET', 'POST'])  # 请求参数设置不区分大小写,源码中自动进行了upperdef login():    if request.method == 'GET':        return render_template('login.html')    elif request.method == 'POST':        username = request.form.get('username')        pwd = request.form.get('pwd')        if username == 'yang' and pwd == '123456':            session['username'] = username            return 'login successed 200  ok!'        else:            return 'login failed!!!'
  • [技术干货] Python实现不写硬盘上传文件【转】
    目录引言文本类型二进制类型使用 requests 把字符串按照文件上传引言你写了一个 api,接受 client 上传的文件,然后在上传到 oss,你会怎么做?先写硬盘,然后在上传到 oss?太笨了!你写了一个截图服务,截到的图要上传到 oss,你会怎么做?先写硬盘,在上传到 oss?太笨了!这篇文章教你重新做人!文本类型使用 io.StringIO1234567import iofrom loguru import loggerfile_like_obj = io.StringIO("hahaha")logger.debug(file_like_obj)logger.debug(type(file_like_obj))logger.debug(getattr(file_like_obj,'read'))logger.debug(file_like_obj.read())输出结果如下:2022-07-11 21:23:51.206 | DEBUG    | __main__:<module>:8 - <_io.StringIO object at 0x100323eb0>2022-07-11 21:23:51.206 | DEBUG    | __main__:<module>:9 - <class '_io.StringIO'>2022-07-11 21:23:51.206 | DEBUG    | __main__:<module>:10 - <built-in method read of _io.StringIO object at 0x100323eb0>2022-07-11 21:23:51.206 | DEBUG    | __main__:<module>:11 - hahaha再看一个熟悉的:12345import iofrom loguru import loggerfile_like_obj = io.StringIO("hahaha")with file_like_obj as f:    logger.debug(f.read())输出结果如下:2022-07-11 21:35:04.620 | DEBUG    | __main__:<module>:9 - hahaha二进制类型使用 io.BytesIO使用 requests 把字符串按照文件上传下面的代码是标准的上传文件的代码:123456import requestsimport ioresponse = requests.post('http://localhost:5000/', files={    'file': open('纵观人类文明史.txt', 'r', encoding='utf-8')})print(response.text)但是我想把 open('纵观人类文明史.txt', 'r', encoding='utf-8') 替换为字符串。为此我想到的办法是把字符串先写到硬盘上,在按照上面的代码上传,可是这太低效率(硬盘太低效率),平白无故多了两次硬盘读写操作,我想直接把内存中的字符串按照文件上传有什么办法吗? 参考文档https://docs.python.org/zh-cn/3/library/io.html#io.StringIO