• python基础汇总(四)


    今天我们来讲一讲正则表达式与json,这些知识将涉及到WEB开发和爬虫开发等等一系列项目。

    我在学习的过程中,发现一个不错的网站,也是一个比较知名的网站,就是菜鸟教程:http://www.runoob.com

    这个网站的知识点汇总还是很齐全的。

    正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。能快速检索文本,实现一些替换文本的操作。

    使用的时候,需要引用re模块,re 模块使 Python 语言拥有全部的正则表达式功能。

    一.re.findall

    re.findall功能:在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

    例子如下:

    import re

    a='one3# 6\two@8 _three ^go'

    b=re.findall('two',a)   #匹配指定的字符串,输出结果是['two']

    c=re.findall('d',a)      #匹配任意的数字,输出结果是['3', '6', '8']

    d=re.findall('D',a)     #匹配任意非数字,包括空白,输出结果是['o', 'n', 'e', '#', ' ', '\', 't', 'w', 'o', '@', ' ', '_', 't', 'h', 'r', 'e', 'e', ' ', '^', 'g', 'o']

    e=re.findall('w',a)     #匹配数字和字母以及下划线,输出结果是['o', 'n', 'e', '3', '6', 't', 'w', 'o', '8', '_', 't', 'h', 'r', 'e', 'e', 'g', 'o']

    f=re.findall('W',a)     #匹配非(字母数字下划线),包括空白,输出结果是['#', ' ', '\', '@', ' ', ' ', '^']

    g=re,findall('s',a)      #匹配空白符号,包括相关制表符,输出结果是[' ', ' ', ' ']

    h=re.findall('S',a)     #匹配非(空白符号,相关制表符),输出结果是['o', 'n', 'e', '3', '#', '6', '\', 't', 'w', 'o', '@', '8', '_', 't', 'h', 'r', 'e', 'e', '^', 'g', 'o']

    print(b)

    print(c)

    print(d)

    print(e)

    print(f)

    print(g)

    print(h)

    输出结果:

    ['two']

    ['3', '6', '8']

    ['o', 'n', 'e', '#', ' ', '\', 't', 'w', 'o', '@', ' ', '_', 't', 'h', 'r', 'e', 'e', ' ', '^', 'g', 'o']

    ['o', 'n', 'e', '3', '6', 't', 'w', 'o', '8', '_', 't', 'h', 'r', 'e', 'e', 'g', 'o']

    ['#', ' ', '\', '@', ' ', ' ', '^']

    [' ', ' ', ' ']

    ['o', 'n', 'e', '3', '#', '6', '\', 't', 'w', 'o', '@', '8', '_', 't', 'h', 'r', 'e', 'e', '^', 'g', 'o']

    我们在这段程序中介绍了常见的其中匹配模式,我们可以总结出规律,同种字母的大小写,匹配的模式对立的;大小写对应的匹配模式如果并集,是等同于一个完整的原字符串。

    那么。下面将会介绍更多的常见匹配模式:

    import re

    a='6A5e*8W-y09udpOc7wD'

    b=re.findall('[a-z]',a)              #匹配a到z的小写字母,输出结果是:['e', 'y', 'u', 'd', 'p', 'c', 'w']

    c=re.findall('[A-Z]',a)              #匹配A到Z的大写字母,输出结果是:['A', 'W', 'O', 'D']

    d=re.findall('[0-9]',a)               #匹配0到9的所有数字,输出结果是:['6', '5', '8', '0', '9', '7']

    e=re.findall('[A-Za-z0-9]',a)    #匹配所有数字和大小写字母,输出结果是:['6', 'A', '5', 'e', '8', 'W', 'y', '0', '9', 'u', 'd', 'p', 'O', 'c', '7', 'w', 'D']

    f=re.findall('[^abcde]',a)          #匹配除了abcde小写字母以外所有的字符,输出结果是:['6', 'A', '5', '*', '8', 'W', '-', 'y', '0', '9', 'u', '$', 'p', 'O', '7', 'w', 'D']

    g=re.findall('[^A-Z]',a)             #匹配除了A到Z所有大写字母以外的所有字符,输出结果是:['6', '5', 'e', '*', '8', '-', 'y', '0', '9', 'u', 'd', '$', 'p', 'c', '7', 'w']

    print(b)

    print(c)

    print(d)

    print(e)

    print(f)

    print(g)

    输出结果:

    ['e', 'y', 'u', 'd', 'p', 'c', 'w']

    ['A', 'W', 'O', 'D']

    ['6', '5', '8', '0', '9', '7']

    ['6', 'A', '5', 'e', '8', 'W', 'y', '0', '9', 'u', 'd', 'p', 'O', 'c', '7', 'w', 'D']

    ['6', 'A', '5', '*', '8', 'W', '-', 'y', '0', '9', 'u', '$', 'p', 'O', '7', 'w', 'D']

    ['6', '5', 'e', '*', '8', '-', 'y', '0', '9', 'u', 'd', '$', 'p', 'c', '7', 'w']

    那么这些就是更多常见的匹配模式,千万要避免这些错误的写法: ’^abcde‘   ,  '^[A-Z]'   等等。

    接下来,我将拓展更多的匹配模式……

    面对一个乱七八糟的字符串,你想从中提取有效的信息,比如指定长度:

    import re

    a=‘sett3oi23oisyudga2isydhjb2siygk%sos2*sjjbdjb'

    #可能这段字符看起来非常糟糕,但可以尝试索取一下你认为最可能的信息

    b=re.findall('[a-z]{1,3}',a)  #匹配a到z字母中的长度在1到3之间的字符串

    print(b)

    输出结果是:

    ['set', 't', 'oi', 'ois', 'yud', 'ga', 'isy', 'dhj', 'b', 'siy', 'gk', 'sos', 'sjj', 'bdj', 'b']   #里面有一个sos求救信号。

    细心的你发现了吗,你发现了一个sos的字符串,这个很明显是你要提取的求救信息。

    当然,有些初心的入学者,会不注意大小写的匹配情况:

    import re

    a=’Java、C#|C++#PYThon‘

    b=re.findall('python',a)

    print(b)

    去尝试运行,却发现报错,报错内容竟是找不到匹配的相应字符串。

    是因为大小写并不一样,原字符串中是’PYThon‘,前面三个字母是大写的,自然是匹配不出来的。

    所以后面需要加一个修饰符re.I,使匹配对大小写不敏感:

    import re

    a='Java、C#|C++#PYThon'

    b=re.findall('python',a,re.I)

    print(b)

    输出结果:

    ['PYThon']    #不要陷入误区,输出结果并不会是['python'],输出结果是字符串里面匹配出来的。

    我们会经常碰到重复字符串,我们同样也需要提取处理,比如‘fuc09fuckk7efuck28s’,但是我们可以发现,如果直接进行对‘fuck’提取处理,会提取出好几个类似的‘fuc’,‘fuckk’等,这样会很耗时。

    这就涉及到贪婪匹配和非贪婪匹配模式的知识点:

     *    将有关的字符全部打印出来,包括正确,少打,多打的情况。

     +   将有关的字符打印出来,只包括正确,多打的情况。

     ?  将有关的字符打印出来,包括少打,正确的情况,对多打的情况匹配正确的情况。

    首先先确定目标字符串‘fuck’,然后选择一种匹配模式,加在字符串后面,最后进行匹配处理。

    我们来应用到代码之中:

    import re

    a='fuc09fuckk7efuck28s'

    b=re.findall('fuck*',a)   #提取正确,少打,多打的字符串,输出结果是:['fuc', 'fuckk', 'fuck']

    c=re.findall('fuck+',a)   #提取正确,多打的字符串,输出结果是:['fuckk', 'fuck']

    d=re.findall('fuck?',a)   #提取正确,少打的字符串,对多打的字符串提取正确的字符串。输出结果是:['fuc', 'fuck', 'fuck']

    print(b)

    print(c)

    print(d)

    输出结果:

    ['fuc', 'fuckk', 'fuck']

    ['fuckk', 'fuck']

    ['fuc', 'fuck', 'fuck']

    二.re.sub

    re.sub用于替换字符串中的匹配项,是对字符串的指定部分进行正则替换操作的函数。公式如下:

    re.sub(pattern, repl, string, count=0, flags=0)

    pattern是字符串中要更换的部分,repl是更换的内容,string是原始字符串。

    count是需要更换的次数,按顺序更换。其中,count=0是默认替换全部,而不是替换0个。

    flags是可选的,表示匹配模式,比如忽略大小写,多行模式等

    来看看一段简单的替换,助于理解:

    a='fuckGOyouRISHME'

    b=re.sub('GO','COME',a)

    print(b)

    输出结果:

    fuckCOMEyouRISHME

    很显然,其中的GO替换成COME了。当然了,千万不要犯错误,比如输入‘go’替换,这样会报错大小写不匹配噢。

    解决的方法当然是使这个过程不对大小写敏感,后面加一个修饰符re.I就行:b=re.sub('go','COME',a,re.I)

    等等,难道你们没有发现我这段代码不对劲吗,还有我写的东西也不对劲吗?

    没发现,直接运行,会直接报错吗?很显然,我上面这段话,犯了两个错误:

    ①编写代码的时候,永远都不要忘了你要引用re功能的时候,开头加一句import re,否则就不能使用re.sub的功能。

    ②读文章的时候,记得要养成动手的习惯,也要记住我说过的东西。

    我在上面就写了re.sub的公式:re.sub(pattern, repl, string, count=0, flags=0),请问我按照公式严格写了吗?

    所以b=re.sub(‘go’,'COME',a,re.I)是错误的写法,因为python会把re.I误识别为count的部分,而并非是flags部分。

    正确的写法是:b=re.sub(‘go’,'COME',a,0,re.I)

    不要相信我上面写的输出结果是多少,这个世界上只有你亲自打印出来的输出结果是正确的。

    永远保持动手能力和一颗质疑的心,亲自敲出来的代码才是正确的代码。

    所以,纠正一下上面的一大段话,正确的代码如下:

    import re

    a='fuckGOyouRISHME'

    b=re.sub('GO','COME',a)

    c=re.sub('go','COME',a,0,re.I)    #匹配不受大小写影响。

    print(b)

    print(c)

    输出结果:

    fuckCOMEyouRISHME

    fuckCOMEyouRISHME

    注意,re.sub一定要严格按照公式编写,如果要用到后面修饰符的功能,count部分需要写个0。

    接下来我们看看这个公式中count部分的应用吧!

    import re

    a='fuckGOyouGORISHGOME'

    b=re.sub('GO','66',a,0)

    c=re.sub('GO','66',a,2)

    print(b)

    print(c)

    输出结果:

    fuck66you66RISH66ME     #count=0是指默认全部替换,而不是替换0个。

    fuck66you66RISHGOME   #count=2,按顺序替换前面两个GO 。

    来看看对这一段程序执行的功能的白话解释:当字符串中想要更换的部分存在多个,可以后面再添加一个参数,控制更换的数量,按顺序。

    输出结果中,count=0很显然并不是一般意义上的0个,而是默认全部替换。当count=2时,会按顺序替换前面两个

    当然了,re.sub的花样并不是只有这么多,还可以进行一个删除的操作,那就是将替换的部分替换成无,不就是变相删除吗?

    import re

    a='fuckGOyouGORISHGOME'

    b=re.sub('GO',' ',a)

    print(b)

    输出结果:

    fuckyouRISHME

    当然了,玩花活是可以的,可以将这一段函数复杂化:

    import re

    a='fuckGOyouGORISHGOME'

    def convert1(value):

        pass

    b=re.sub('GO',convert1,a)

    print(b)

    输出结果:

    fuckyouRISHME

    所以可以看到,公式里的repl部分是可以用函数操作的。

    这段函数的意思就是,在re.sub的替换操作之下,对GO进行convert1函数的pass操作,也就是换成无,也就是删除。

    所以,这一段的作用就是去掉所有GO。

    当然了,除了替换无之外,还能替换添加字符的操作,比如将GO替换成666GO666,传统方法可以直接做到,但在此介绍用函数的方法替换:

    import re

    a='fuckGOyouGORISHGOME'

    def convert2(value):

        matched=value.group()    #将同时匹配到的三个’GO‘字符进行分组有序化,防止python不知道先处理哪一个而出错。

        return '666'+ matched +'666'

    b=re.sub('GO',convert2,a)

    c=re.sub('GO',convert2,a,2)

    print(b)

    print(c)

    输出结果:

    fuck666GO666you666GO666RISH666GO666ME

    fuck666GO666you666GO666RISHGOME

    这段函数的意思就是,在re.sub的替换操作之下,将GO替换成666GO666。

    那么,为什么要对value进行group()操作呢,不能直接return吗?value本身不就是字符串吗?

    原因啊,其实很简单,在匹配GO字符串出来的时候,其实是有三个GO被同时匹配出来,直接替换会被报错,python不知道怎么按顺序。

    所以,建立一个matched变量,将value变量里面匹配出来的三个GO进行分组操作,让它有序。

    注意,return的时候,要用str数据类型去返回,这样就是字符串替换字符串的正确过程。

    c变量的作用很好猜,自然是只替换前两次的GO。

    当然了,re,sub还能和if条件语句一起完成替换的过程:

    import re

    a='AKH8787AS67F67SF6A89'

    def convert3(value):

        matched=value.group()      

        if int(matched) > 7:          #注意,匹配出来的数字是str数据类型。

            return '0'

        else:

            return '1'

    b=re.sub('d',convert3,a)     #将d匹配出来的数字进行函数convert3的处理。

    print(b)

    输出结果:

    AKH0101AS11F11SF1A00

    这一段就是一个数字替换的函数,首先d匹配出所有的数字,然后按照函数内容来更换,得到最后的结果。

    注意,这次我犯了个错误,return后面的0和1我都没有打上srt引号,导致报错。

    要知道,value匹配'd'的结果是str类型的数字,然后经过group()分组处理得出的matched变量还是str类型

    所以更换数字要同样的str类型去return。

    以上就是re.sub的一些常见替换用法。

    三.re.matched和re.search

    re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

    re.search 扫描整个字符串并返回第一个成功的匹配

    a='life is short,i use python.'

    b=re.search('life.*python',k)

    print(b)

    print(b.group())

    首先,打印出输出结果

    <re.Match object; span=(0, 26), match='life is short,i use python'>

    life is short,i use python

    我们可以看到,第一条打印的是程序运行的过程,并不是用户想要看到的最终输出。

    于是第二条进行分组化,将匹配出来的字符串包装,进行打印。

    life. 是以life开头往后匹配;*python,是pytho前所有的都匹配出来。两者都包含本身。

    那么两者有什么不同之处呢?

    re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

    那么以上这些就是python中的正则表达式,那么如何赋予应用呢,我们来看看JSON吧。

    什么是JSON?

    英文全名:JavaScript Object Notation

    中文翻译:  Javascript对象标记

    JSON是一种轻量级的数据交换格式,易于人阅读和编写,网络传输效率高。

    记住,JSON是一种数据形式,JSON的表现形式是字符串。

    凡符合JSON格式的字符串就叫做JSON字符串。

    JSON的作用很强大,可以完成跨语言交换数据的功能。

    比如现有不同的A语言和B语言,若想要进行转换,中间的桥自然就是JSON数据形式。

    那么如果要使用JSON函数,还是一如既往的引用库:import json

    那么这方面我们只需要了解两个函数:

    ①json.loads

    作用:用于解码JSON数据,返回Python数据类型。

    import json

    json_thing='{"name":"666","age":"18"}'    #定义一个json类型变量。

    python_thing=json.loads(json_thing)      #解码JSON数据,转为python数据。
    print(python_thing)
    print(type(python_thing))          #查看转换后的变量类型,是否为python数据类型,输出结果是<class 'dict'>。
    print(type(json_thing))
    输出结果:

    {'name': '666', 'age': '18'}
    <class 'dict'>
    <class 'str'>

    ②json.dumps

    作用:用于将Python对象编码成JSON字符串。

    import json

    python_thing={"name":"666","age":"18"}

    json_thing=json.dumps(python_thing)
    print(json_thing)
    print(type(json_thing))                      #我们可以看到输出结果,虽然转换后的形式没变,但是数据类型变了。
    print(type(python_thing))

    输出结果:

    {"name": "666", "age": "18"}                #注意,虽然转换后的结果跟转换前的结果一样,但是数据类型变了。
    <class 'str'>                                        #我们可以发现,看上去像是字典的形式,实际上已经成了JSON的str类型。
    <class 'dict'>

    经过上面两段程序,相比大家已经对JSON有了一定的了解,能理解JSON数据类型与python数据类型之间的转换过程。

    那么我们来看看更多的转换数据类型。

    时刻清楚这一点,JSON是一种数据类型,以str形式展现。

  • 相关阅读:
    Cross-Site Scripting(XSS)简介
    nginx查看安装了哪些模块
    Win7系统修改hosts文件不能保存的解决方法
    firefox怎么修改tls协议号
    在Nginx中部署基于IP的虚拟主机
    openssl生成ssl证书
    给kali linux2.0装一个中文输入法
    tenda u1 usb wireless device install driver for kali linux kernal Debian 4.3.3-7kali2 (2016-01-27) x86_64 GNU/Linux
    python2.7.x的字符串编码到底什么鬼?(中文和英文的处理)
    fswatch rsync配置使用 rsync 传输大量细小文件
  • 原文地址:https://www.cnblogs.com/Masterpaopao/p/10061575.html
Copyright © 2020-2023  润新知