正则表达式

正则表达式

  • 正则表达式的作用:

    • 数据的抓取,数据提取,如:抓取网站中的图片地址
    • 数据清洗 ,把不雅的评论清洗掉
    • 数据验证:验证手机号的合法性 11位数字
  • re模块

    Python 提供的正则表达式处理模块 re,提供了各种正则表达式的处理函数

    • 使用过程
    1.导入模块:import re
    2.  匹配:ret = re.match("正则表达式","要匹配的字符串")
    3.判断是否成功:
      ret:不为空,表示匹配成功,返回的是match对象
          为空,匹配失败
    4.取匹配结果:ret.group()
    #注意:re.match()匹配以xxx开头的字符串
    
    • 练习
    #匹配ujiuye
    content = "ujiuye.com"
    import re
    ret = re.match("ujiuye",content)
    # print(ret) #<re.Match object; span=(0, 6), match='ujiuye'>
    if ret:
        print(ret.group())
    else:
        print("匹配不成功")
    
  • 匹配单个字符

    • *1."." :表示匹配任意一个字符,除了\n(换行符)以外 (重点)
    # ret = re.match("速度与激情","速度与激情")
    # ret = re.match("速度与.情","速度与即情")
    # ret = re.match("速度与.情","速度与#情")
    # ret = re.match("速度与.情","速度与\n情")
    # ret = re.match("速度与.情","速度与#情1")
    ret = re.match("速度与.情","速度与激情abc12345")
    print(ret)
    
    • *2.[ ] :匹配"[ ]"中列举的字符 (重点)
    # ret = re.match("速度与激情","速度与激情6")
    # ret = re.match("速度与激情[123456789]","速度与激情6")
    # ret = re.match("速度与激情[123456789]","速度与激情10")
    # ret = re.match("速度与激情[1-9]","速度与激情6")
    #速度与激情6不匹配
    # ret = re.match("速度与激情[12345789]","速度与激情6")
    # ret = re.match("速度与激情[1-57-9]","速度与激情8")
    ret = re.match("速度与激情[a-z]","速度与激情c")
    print(ret)
    
      1. \d : 匹配数字,0-9 \D : 匹配非数字,即不是数字 (重点)
    # 无论是速度与激情第几部,只要是数字,都算正确
    # ret = re.match("速度与激情\d","速度与激情6")
    # ret = re.match("速度与激情\d","速度与激情#")
    
    # \D : 匹配非数字,即不是数字
    # ret = re.match("速度与激情\D","速度与激情#")
    ret = re.match("速度与激情\D","速度与激情6")
    print(ret)
    
    • 4.\s : 匹配空格 \S: 匹配非空格
    # ret = re.match("速度与激情\s","速度与激情6")
    # ret = re.match("速度与激情\s","速度与激情 ")
    
    # ret = re.match("速度与激情\S","速度与激情6")
    ret = re.match("速度与激情\S","速度与激情")
    print(ret)
    
      1. \w 匹配单词字符:(a-z,A-Z,0-9,_) \W:匹配非单词字符
    # ret = re.match("\w","1")
    # ret = re.match("\w","a")
    # ret = re.match("\w","#")
    # ret = re.match("\w","刘")
    
    ret = re.match("\W","刘")
    print(ret)
    
  • 匹配多个字符 {m},{m,n},?,+,*

    • 1.{m} :匹配前一个字符m次
    #匹配手机号
    #规则:要求满足11为数字,且第一位1
    # ret = re.match("\d{11}","12345678901")
    # ret = re.match("\d{11}","1234567890") #None
    # ret = re.match("\d{11}","12345a78901") #None
    # ret = re.match("1\d{10}","12345678901") #12345678901
    ret = re.match("1\d{10}","123456789011123")
    print(ret)
    
    • 2.{m,n} : 匹配前一个字符m到n次
    #匹配电话号码的合法性 如:010-1234567 ,0558-8080745
    #规则:区号3-4位,电话号是7-8位,中间用“-”连接
    # ret = re.match("\d{3,4}-\d{7,8}","010-1234567")
    # ret = re.match("\d{3,4}-\d{7,8}","0558-8080745")
    # ret = re.match("\d{3,4}-\d{7,8}","0558-80807455")
    ret = re.match("\d{3,4}-\d{7,8}","0558-8080745a")
    print(ret)
    
      1. ? :前一个字符出现0次或者1次,要么出现1次,要么出现0次 (重点)
    #匹配电话号码的合法性 如:010-1234567 ,0558-8080745
    #规则:区号3-4位,电话号是7-8位,中间用“-”连接,"-"可有可无
    # ret = re.match("\d{3,4}-\d{7,8}","010-1234567")
    ret = re.match("\d{3,4}-?\d{7,8}","0101234567") #0101234567
    # ret = re.match("\d{3,4}-?\d{7,8}","010-1234567") #010-1234567
    print(ret)
    
    • 4.*: 匹配前一个字符出现0次或者多次 (重点)

      #案例:把一个文本内容全部提取出来
      # content = "life is short,I use python !"
      content = "life is short\nI use python !"
      # ret = re.match(".*",content)
      ret = re.match(".*",content,re.S) #可以匹配多行 life is short\nI use python !
      print(ret)
      print(ret.group())
      
    • 5.+:匹配前一个字符出现1次或者多次,至少出现1次

      # ret = re.match("a+","aaaa") #aaaa
      ret = re.match("a+","") #None
      ret = re.match("a*","") #''
      print(ret)
      
  • 匹配开头与结尾

    • 1.“^”:匹配开头字符串
    # ret = re.match("ujiuye","ujiuye.com")
    # ret = re.search("ujiuye","www.ujiuye.com")
    # ret = re.search("^ujiuye","www.ujiuye.com") #None
    ret = re.match("[^123]","1") #None
    print(ret)
    #^用在[]中,表示取反
    
    • 2."$":匹配以xxx结尾的字符串
    #匹配手机号
    #规则:要求满足11为数字,且第一位1
    # ret = re.match("1\d{10}","12345678901abc") #匹配成功但是不符合要求
    ret = re.match("1\d{10}$","12345678901abc") #None
    print(ret)
    
  • 匹配分组

    • 1.| :匹配左右任意一个表达式
    • 2.(ab):分组
    email = "huangzhi@163.com"
    ret = re.match("(\w{4,20})@(163)\.(com)$",email)
    print(ret.group(0))
    print(ret.group(1))
    print(ret.group(2))
    print(ret.group(3))
    
    email_list = ["huangzhi@163.com","wangtao@163.cn","110123@qq.com","yuanle@163.com.cn","guyin@163ccom"]
    for email in email_list:
        ret = re.match("\w{4,20}@(163|qq)\.com$",email)
        if ret:
            print(f"{ret.group(0)}邮箱名合法")
        else:
            print(f"{email}邮箱名不合法")
    
    • 3.引用分组,引用分组中的字符串 \num
    #检查html网页语法的合法性
    #语法规则:标签必须配对
    content = "<h1>hello world</h1>"
    # content = "<h1>hello world</h2>"
    #不严谨的写法
    # ret = re.match("<\w+>.*</\w+>",content)
    #严禁的写法
    # ret = re.match("<(\w+)>.*</\\1>",content)
    ret = re.match(r"<(\w+)>.*</\1>",content)
    print(ret)
    
    • 给分组起别名 (?P<name>)
    # 给分组起别名 (?P<name>)
    content = "<h1><body>hello world</body></h1>"
    # ret = re.match("<(\w+)><(\w+)>.*</\\2></\\1>",content)
    ret = re.match("<(?P<a>\w+)><(?P<b>\w+)>.*</(?P=b)></(?P=a)>",content)
    print(ret)
    
  • re模块中的其他用法 search,findall,sub

    # 1.search:查看匹配的数据,匹配到立即返回
    #案例:匹配阅读次数
    # content = "阅读次数是88次。"
    # ret = re.search("\d+",content)
    # print(ret)
    # print(ret.group())
    
    # 2.findall:查找字符串中所有匹配的数据,返回列表
    #匹配所有的数字
    # content = "阅读次数是88次,下载次数是55次。"
    # ret = re.findall("\d+",content)
    # print(ret)
    
    #3.sub():替换,返回的是替换后的字符串
    #将所有的次数归0
    content = "阅读次数是88次,下载次数是55次。"
    ret = re.sub("\d+","0",content)
    print(ret)
    
  • 贪婪和非贪婪

    • python中默认是贪婪,总是尽可能多的匹配字符,非贪婪相反,总是尽可能少的匹配字符
    # ret = re.match("\d{2,10}","123456789")
    ret = re.match("\d{2,10}?","123456789") #使贪婪模式变为非贪婪模式
    print(ret)
    
  • 2.字符串前面加“r”表示原生字符串

  • 3.re.compile(strPattern)

  • pattern = re.compile("\d{2,10}")
    ret = pattern.match("123456789")
    print(ret)
    

迭代器

  • 迭代:

    • 迭代是访问集合元素的一种方式,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫迭代
  • 可迭代对象

    • 可以通过for循环遍历取出元素的对象就是可迭代对象
    • 通过isinstance()判断一个对象是否是可迭代对象
    from collections import Iterable
    print(isinstance([],Iterable)) #True
    print(isinstance("",Iterable)) #True
    print(isinstance(123,Iterable)) #False
    
  • 迭代器:拥有__iter__方法和__next__方法的对象就是迭代器,帮助我们在迭代遍历时记录访问的位置,以便下一次迭代可以返回下一条数据 (重点)

    • iter()函数可以把可迭代对象中的迭代器取出来,内部调用__iter__方法
    • next()函数通过迭代器获取下一位置的值,内部调用的是__next__方法
    string = "hello"
    # for i in string:
    #     print(i)
    #获取迭代器
    iter1 = iter(string)
    # print(iter1)
    print(next(iter1))
    print(next(iter1))
    print(next(iter1))
    print(next(iter1))
    print(next(iter1))
    print(next(iter1))
    
  • 迭代器实现斐波那契数列 1,1,2,3,5,8

    class Fib:
        def __init__(self,n): #n表示前n项数列
            self.n = n
            self.a = 1
            self.b = 1
            self.index = 0 #记录位置
        def __iter__(self):
            return self
            # pass
    
        def __next__(self):
            if self.index<self.n:
                num = self.a
                self.a,self.b = self.b,self.a+self.b
                self.index+=1
                return num
            else:
                raise StopIteration
    fib = Fib(5)
    print(isinstance(fib,Iterable))
    for i in fib:
        print(i)
    

生成器

  • 概念:生成器的本质就是迭代器,但是比迭代器更优雅

  • 生成器有两种:生成器函数和生成器表达式

  • 生成器函数:一个包含yield关键字的函数就是生成器函数。yield不能和return共用 (重点)

    • 生成器函数执行后会得到一个生成器作为返回值,并不会执行函数体。

    • 执行了next()方法之后才会执行函数体,并且获得返回值

    • next()内置方法,内部调用的是__next__()方法

    • yield和return相同的是都可以返回值,不同的是yield不会结束函数

  • send()

    • send()获取下一个值的效果和next基本一致,只是在获取下一个值的时候,给上一个yield传递数据
    • 注意:第一次使用生成器的时候,使用next方法获取下一个值
  • yield from 循环遍历容器类型

  • 生成器表达式 (重点)

    • 格式:将列表推导式[ ]改成( )即可

unitTest

  • 单元测试:是用来对一个模块/一个函数/一个类来进行正确性检验的测试工作

  • 单元测试的四个核心:

    • test case(测试用例):一个py文件就是一个测试用例
    • test suit(测试套件):测试用例的集合
    • test runner(测试运行器):执行测试套件
    • test fixture(测试脚手架)
  • test case(测试用例):一条用例就是一个完整的测试流程

    步骤

    • 1.导入unittest模块,被测文件中的类
    • 2.创建一个测试类,继承unittest.TestCase
    • 3.重写setUp和tearDown方法(初始化条件和结束条件)
    • 4.定义测试函数,函数名以test_开头
    • 5.在函数中使用断言来判断测试结果是否符合预期
    • 6.调用unittest.main()方法运行测试用例,无此方法也可以运行

    设置setUp和tearDown:每次用例执行前都会执行初始化条件和结束条件

python2 vs python3 (重点)

  • print

    • python2中是输出语句
    • python3 中是函数
  • range和xrange

    • range()在python2中会得到一个列表,xrange(1,3)得到一个生成器
    • 在python3中是生成器,没有xrange
  • 字符串

    • python2中存储字符串,底层使用的是ascii编码
    • python3储存字符串,使用的是Unicode
  • 异常处理

    python2

    try:
        print 1/0
    except Exception,e:
        print e
    
  • 打开文件

    f = file()

    f = file("1.txt","w")
    f.write("hello")
    f.close()
    
  • 标准输入

    python2有两种标准输入

    info = raw_input("提示信息"),输入数据全部转换为字符串
    info = input("提示信息:") ,输入什么数据就输出什么数据类型
    
  • 除法操作

    python2 /:表示的是整除,加上浮点数就是真实除法

    python3:/表示除法,//表示整除

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341