正则表明式,正则表达式应用

正则表明式平常不常用,平常都以用的时候,临时抱佛脚,查文档,然后就是被各类坑之后,才会逐步熟知。

re模块

os模块是与操作系统交互的贰个接口

 

在线正则表达式测试:

讲正题在此以前我们先来看贰个例证:

 

正则表明式

  首先,大家引入了正则表明式的学识。所谓正则表明式,便是对字符串操作的1种逻辑公式,正是用事先定义好的部分特定字符、及那一个特定字符的咬合,组成七个“规则字符串”,那一个“规则字符串”用来表明对字符串的一种过滤逻辑。

  正则表明式本人和python未有何样关联,正是相称字符串内容的一种规则。那里给了贰个老大好用的在线测试工具

  聊到正则,就只和字符串相关了。着眼赵犇则的时候,输入的每2个字都是一个字符串。要是在三个岗位的三个值,不晤面世什么变动,那么是不须求规则的,直接就能够合营上。在以往我们越来越多要思量的是在同叁个岗位上能够出现的字符的界定。

  字符组 : 形式为——[字符组]

  在同一个岗位只怕出现的各样字符组成了1个字符组,在正则表明式中用[
]表示字符分为很多类,比如数字、字母、标点等等。假若你今后须求贰个岗位”只可以出现三个数字”,那么那个职责上的字符只好是0、1、2…九那13个数之一。能够用[0123456789]公布,也足以用[0-9],后者只可以从小指到大,即不得以用[9-0]的形式。

字符组
待匹配字符
匹配
结果
说明
[0123456789]
8
True
在一个字符组里枚举合法的所有字符,字符组里的任意一个字符
和"待匹配字符"相同都视为可以匹配
[0123456789]
a
False
由于字符组中没有"a"字符,所以不能匹配
 

[0-9]
 

7
True
[0-9]和[0123456789]是一个意思
 

[a-z]
 

s
 

True
 

同样的如果要匹配所有的小写字母,直接用[a-z]就可以表示
 

[A-Z]
 

B
 

True
 

[A-Z]就表示所有的大写字母
 

[0-9][a-f][A-F]
 

e
 

True
 

可以匹配数字,大小写形式的a~f,用来验证十六进制字符

 

以下是正则表明式中的全数字符及其用法:

元字符
 

匹配内容
匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配字符串的开始
$ 匹配字符串的结
\W
匹配非字母或数字或下划线或汉字,即除\w能匹配的类型以外的所有类型
\D
匹配非数字,即除\d能匹配的类型以外的所有类型
\S
匹配非空白符,即除\s能匹配的类型以外的所有类型
a|b
匹配字符a或字符b
()
匹配括号内的表达式,也表示一个组
[…]
匹配字符组中的字符
[^…]
匹配除了字符组中字符的所有字符,即与[]相反
量词
用法说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

. ^
$的用法简介

正则 待匹配字符 匹配
结果
说明
海. 海燕海东西海娇

海燕

海东

海娇

  匹配所有"海."的字符
^海. 海燕海东西海娇 海燕 只从开头匹配"海."
  海.$   海燕海东西海娇 海娇 只匹配结尾的"海.$"

 

* +
? { }的用法简介

正则 待匹配字符 匹配
结果
说明
李.? 李杰和李莲英和李二棍子

李杰
李莲
李二

 

?表示重复零次或一次,即只匹配"李"后面一个任意字符,贪婪匹配

 

李.* 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
*表示重复零次或多次,即匹配"李"后面0或多个任意字符,贪婪匹配
李.+ 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
+表示重复一次或多次,即只匹配"李"后面1个或多个任意字符,贪婪匹配
李.{1,2} 李杰和李莲英和李二棍子

李杰和
李莲英
李二棍

{1,2}匹配1到2次任意字符,贪婪匹配

 注意:前面的*,+,?等都以贪心相配,约等于硬着头皮相配,前边加?号使其成为惰性相称

正则 待匹配字符 匹配
结果
说明
李.*? 李杰和李莲英和李二棍子 李杰
李莲
李二
惰性匹配

 

字符集[][^]的用法简介

正则 待匹配字符 匹配
结果
说明
李[杰莲英二棍子]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

 

表示匹配"李"字后面[杰莲英二棍子]的字符任意次

 

李[^和]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

表示匹配一个不是"和"的字符任意次
[\d] 456bdha3

4
5
6
3

表示匹配任意一个数字,匹配到4个结果
[\d]+ 456bdha3

456
3

表示匹配任意个数字,匹配到2个结果

 

分组
()与 或 |[^]的用法简介

 身份证编号是三个长度为1伍或二十三个字符的字符串,要是是壹6人则全体由数字组成,第三位不可能为0;假若是1十一位,则前1三个人1体是数字,倒数一位可能是数字或x,上边大家尝试用正则来表示:

正则 待匹配字符 匹配
结果
说明
^[1-9]\d{13,16}[0-9x]$ 110101198001017032

110101198001017032

   表示可以匹配一个正确的身份证号
^[1-9]\d{13,16}[0-9x]$ 1101011980010170

1101011980010170

表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字
^[1-9]\d{14}(\d{2}[0-9x])?$ 1101011980010170

False

现在不会匹配错误的身份证号了
()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ 110105199812067023

110105199812067023

表示先匹配[1-9]\d{16}[0-9x]如果没有匹配上就匹配[1-9]\d{14}

 

转义符
\的用法简介

在正则表明式中,有那叁个有相当含义的是元字符,比如\d和\s等,假设要在正则中相配寻常的”\d”而不是”数字”就供给对”\”举行转义,变成’\\’。

在python中,无论是正则表达式,依然待相配的内容,都以以字符串的款型出现的,在字符串中\也有拾分的意思,自身还索要转义。所以壹旦合作2次”\d”,字符串中要写成’\\d’,那么正则里即将写成”\\\\d”,这样就太辛苦了。这年大家就用到了r’\d’那一个概念,此时的正则是r’\\d’就足以了。

正则 待匹配字符 匹配
结果
说明
\d \d  False
因为在正则表达式中\是有特殊意义的字符,所以要匹配\d本身,用表达式\d无法匹配
\\d \d  True
转义\之后变成\\,即可匹配
"\\\\d" ‘\\d’  True
如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次
r’\\d’ r’\d’  True
在字符串之前加r,让整个字符串不转义

 

在线JSON格式化:

那是京东的注册页面,打开页面大家就来看那些供给输入个人音信的唤醒。
一旦我们随便的在手提式有线电电话机号码那壹栏输入一个1111111111一,它会指示我们格式有误。
其1效果是怎么落到实处的吧?
假若未来你用python写1段代码,类似:

亚洲必赢官网 1

贪欲相配

贪得无厌相配:在满意相称时,相配尽或然长的字符串,暗许景况下,选取贪婪相配

正则 待匹配字符 匹配
结果
说明
<.*>

<script>…<script>

<script>…<script>
默认为贪婪匹配模式,会匹配尽量长的字符串
<.*?> r’\d’  

<script>
<script>

加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串

注:在背后加上?后即转为非贪婪匹配形式,全数相配长度都取最短

附:非贪婪形式的1个用法——  .*?x
    正是取后面任意长度的字符,直到三个x涌出

 

 

正则表明式手册:

phone_number = input('please input your phone number : ')
'''
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.popen("bash command)  运行shell命令,获取执行结果
os.environ  获取系统环境变量

os.path

os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。
                        即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小
'''

re模块下的常用方法

import re

ret = re.findall('a', 'eva egon yuan')  # 返回所有满足匹配条件的结果,放在列表里
print(ret) #结果 : ['a', 'a']

ret = re.search('a', 'eva egon yuan').group()
print(ret) #结果 : 'a'
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

ret = re.match('a', 'abc').group()  # 同search,不过仅在字符串开始处进行匹配,如果开始没有匹配到就报错
print(ret)
#结果 : 'a'

ret = re.split('[ab]', 'abcd')  # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)  # ['', '', 'cd']

ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个
print(ret) #evaHegon4yuan4

ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret)#('evaHegonHyuanH', 3)

obj = re.compile('\d{3}')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123

import re
ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  #查看第一个结果即3
print(next(ret).group())  #查看第二个结果即4
print([i.group() for i in ret])  #查看剩余的结果,以列表的形式打印,即['7', '8', '4']

 

在意:findall和split的先期级查询:

#1 findall的优先级查询:
import re

ret = re.findall('www.(sogo|baidu).com', 'www.baidu.com')
print(ret)  # ['baidu']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

ret = re.findall('www.(?:sogo|baidu).com', 'www.baidu.com')
print(ret)  # ['www.baidu.com']





#2 split的优先级查询
ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : ['eva', 'egon', 'yuan']

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']

#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
#这个在某些需要保留匹配部分的使用过程是非常重要的。

 

 

上边举多少个演习的栗子,必要领会,为了变得更牛逼出去越来越好的装逼最佳照旧控制:

先来看下代码和运作效果呢

你怎么判断这几个phone_number是法定的吧?

亚洲必赢官网 2

1、相称标签

亚洲必赢官网 3亚洲必赢官网 4

import re


ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
#还可以在分组中利用?<name>的形式给分组起名字
#获取的匹配结果可以直接用group('名字')拿到对应的值
print(ret.group('tag_name'))  #结果 :h1
print(ret.group())  #结果 :<h1>hello</h1>

ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
#如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
#获取的匹配结果可以直接用group(序号)拿到对应的值
print(ret.group(1))
print(ret.group())  #结果 :<h1>hello</h1>

View Code

 string msg, rex;
            Match m;
            msg = "昨日总能耗0度。 (长沙市口腔医院)星期一【紫衡技术】";
            rex = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{3}).*";
            m = Regex.Match(msg, rex);
            Console.WriteLine("0:" + m.Success);
            WriteGroupInfo(m);

            //1
            msg = @"上周总能耗28401.4度。 (沙井街道办)星期一【紫衡技术】";
             rex = @".*(上周总?能耗)([0-9]{1,}[.][0-9]*)*度。 \((.*)\)(.{3}).*";
            //昨日总能耗2582.1度。【长沙市天心区人民法院】2018 - 07 - 08【紫衡技术】
             m = Regex.Match(msg, rex);
            var r = m.Success;
            Console.WriteLine("1:"+r);
            WriteGroupInfo(m);

            //2
            rex = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。\【(.*)\】(\d{4}-\d{2}-\d{2}).*";
            msg= "昨日总能耗209.9度。【长沙市天心区人民检察院】2018-07-08【紫衡技术】";
            Match m1 = Regex.Match(msg, rex);
            Console.WriteLine("2:"+m1.Success);
            WriteGroupInfo(m1);

            //3
            rex = @".*(上周总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{3}).*";
            msg = "上周总能耗10922.4度。 (深圳市地方税务局第二稽查局)星期一【紫衡技术】";
            m1 = Regex.Match(msg, rex);
            Console.WriteLine("3:"+m1.Success);
            WriteGroupInfo(m1);

            //4
            rex = @".*(上月总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{8}).*";
            msg = "上月总能耗49276.9度。 (深圳市地方税务局第二稽查局)2018年06月【紫衡技术】";
            m1 = Regex.Match(msg, rex);
            Console.WriteLine("4:"+m1.Success);
            WriteGroupInfo(m1);

            //5
            rex = @".*(建筑名称)\:(.*),在(\d{4}-\d{2}-\d{2}).{3}([0-9]{1,}[.][0-9]*)*度。";
            msg = "建筑名称:长沙市天心区人民法院,在2018-07-08日用电2582.1度。";
            m1 = Regex.Match(msg, rex);
            Console.WriteLine("5:"+m1.Success);
            WriteGroupInfo(m1);

            //6
            rex = @"(今日能耗)\:([0-9]{1,}[.]?[0-9]*)";
            msg = "今日能耗:300【紫衡技术】";
            m1 = Regex.Match(msg, rex);
            Console.WriteLine("6:" + m1.Success);
            WriteGroupInfo(m1);

            //^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)
            //*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+
            rex = @"^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*
                 (服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+";
            msg = "【公司WNC服务监控台】异常 - 服务【Secom.Emx.SmsServer.Service】未找到或者未安装!【紫衡技术】";
            m1 = Regex.Match(msg, rex);
            Console.WriteLine("7:" + m1.Success);
            WriteGroupInfo(m1);
            Console.ReadKey();
        }

        private static void WriteGroupInfo(Match m)
        {
            var g = m.Groups;
            if (g.Count > 0)
            {
                for (var i = 0; i < g.Count; i++)
                {
                    Console.WriteLine(i+":"+g[i].Value);
                }
            }
        }
根据手机号码一共11位并且是只以13、14、15、18开头的数字这些特点,我们用python写了如下代码: 

 

2、相配整数

亚洲必赢官网 5亚洲必赢官网 6

import re

ret=re.findall(r"\d+","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) #['1', '2', '60', '40', '35', '5', '4', '3']

ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) #['1', '-2', '60', '', '5', '-4', '3']

ret.remove("")
print(ret) #['1', '-2', '60', '5', '-4', '3']

ret=re.findall(r'(-?\d+\.\d*)|-?\d+','1-2*(60+(-40.35/5)-(-4*3))')
print(ret)#['', '', '', '-40.35', '', '', '']

ret=re.findall(r'-?\d+\.\d*|-?\d+','1-2*(60+(-40.35/5)-(-4*3))')
print(ret)#['1', '-2', '60', '-40.35', '5', '-4', '3']

View Code

运维结果:

亚洲必赢官网 7亚洲必赢官网 8

 

3、数字匹配

亚洲必赢官网 9亚洲必赢官网 10

1、 匹配一段文本中的每行的邮箱
      http://blog.csdn.net/make164492212/article/details/51656638

2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;

   分别取出1年的12个月(^(0?[1-9]|1[0-2])$)、
   一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$

3、 匹配qq号。(腾讯QQ号从10000开始)  [1,9][0,9]{4,}

4、 匹配一个浮点数。       ^(-?\d+)(\.\d+)?$   或者  -?\d+\.?\d*

5、 匹配汉字。             ^[\u4e00-\u9fa5]{0,}$ 

6、 匹配出所有整数

View Code

亚洲必赢官网 11

while True:
    phone_number = input('please input your phone number : ')
    if len(phone_number) == 11 \
            and phone_number.isdigit()\
            and (phone_number.startswith('13') \
            or phone_number.startswith('14') \
            or phone_number.startswith('15') \
            or phone_number.startswith('18')):
        print('是合法的手机号码')
    else:
        print('不是合法的手机号码')

 

肆、爬虫练习

亚洲必赢官网 12亚洲必赢官网 13

import requests

import re
import json

def getPage(url):

    response=requests.get(url)
    return response.text

def parsePage(s):

    com=re.compile('<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?(?P<title>.*?)'
                   '.*?(?P<rating_num>.*?).*?(?P<comment_num>.*?)评价',re.S)

    ret=com.finditer(s)
    for i in ret:
        yield {
            "id":i.group("id"),
            "title":i.group("title"),
            "rating_num":i.group("rating_num"),
            "comment_num":i.group("comment_num"),
        }

def main(num):

    url='https://movie.douban.com/top250?start=%s&filter='%num
    response_html=getPage(url)
    ret=parsePage(response_html)
    print(ret)
    f=open("move_info7","a",encoding="utf8")

    for obj in ret:
        print(obj)
        data=json.dumps(obj,ensure_ascii=False)
        f.write(data+"\n")

if __name__ == '__main__':
    count=0
    for i in range(10):
        main(count)
        count+=25

View Code

 

至黄永辉则的知识方今就到那边,下边要说关于模块的学问

 


 

急需注意的地点,待匹配文字中的空格以及全角和半角字符要留心区分。

看清手提式有线电话机号码是或不是合法一

在意:os.stat(‘path/filename’)  获取文件/目录新闻 的布局表明

what’s the 是模块

  1个模块正是3个暗含了python定义和证明的文本,文件名便是模块名字加上.py的后缀。

但实在import加载的模块分为多个通用项目: 

  一运用python编写的代码(.py文件)

  二已被编写翻译为共享库或DLL的C或C++扩大

  叁 包好一组模块的包

  4施用C编写并链接到python解释器的内置模块

何以要运用模块?

 
 假使您退出python解释器然后再也进入,那么你前边定义的函数只怕变量都将遗失,由此我们司空眼惯将顺序写到文件中以便永久保存下来,需求时就因而python
test.py格局去履行,此时test.py被称之为脚本script。

   
随着程序的腾飞,作用尤为多,为了方便管理,大家普通将顺序分成3个个的文件,那样做程序的结构更清晰,方便管理。那时我们不但能够把这一个文件作为脚本去实施,还足以把她们作为模块来导入到其余的模块中,完成了效果的再度使用。

  模块的导入应该在先后的起第四人置。格式为import +模块名

 

 

  首先我们学了re模块,re模块与正则说明式皮之不存毛将焉附,关于re模块的运用,在上文正则表明式中就有提起,即findallsearchmatch的使用方法,那里不做赘述。

  然后大家来探视关于collection模块

积存正则表达式字符串,不能够储存到Json文件中,特殊字符会出现转义,存XML中并未有那几个标题。通过组织sql语句存款和储蓄到mysql中的时候,反斜杠\将会被平昔吃掉,所以插入在此之前要先进行转义。

这是你的写法,现在我要展示一下我的写法:

亚洲必赢官网 14亚洲必赢官网 15

collection模块

  在放手数据类型(dict、list、set、tuple)的基本功上,collections模块还提供了几个附加的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等亚洲必赢官网,。

    一.namedtuple:
生成可以接纳名字来拜会成分内容的tuple

    二.deque:
双端队列,能够非常的慢的从其余壹侧追加和生产对象

    三.Counter:
计数器,紧要用来计数

    肆.OrderedDict:
有序字典

    5.defaultdict:
带有默许值的字典

上边大家来详细介绍一下那七种数据类型:

namedtuple:第二用在坐标上表示,如代表一个点照旧3个圆

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
p.x
p.y


#表示圆
#namedtuple('名称', [属性list]):
Circle = namedtuple('Circle', ['x', 'y', 'r'])

 

deque:

  因为list是线性存储,数据量大的时候,插入和删除功用十分低。deque是为着快捷落到实处插入和删除操作的双向列表,适合用来队列和栈:

from collections import deque
q = deque(['a', 'b', 'c'])
q.append('x')
q.appendleft('y')
print(q)#['y', 'a', 'b', 'c', 'x']

注:deque除了落成list的append()和pop()“外,还援助appendleft()和popleft(),那样就能够丰裕便捷地往尾部添加或删除成分。

正则表明式,正则表达式应用。 

OrderedDict:动用dict时,Key是冬日的。在对dict做迭代时,大家无能为力鲜明Key的依次。要是要保持Key的次第,能够用OrderedDict

from collections import OrderedDict
d = dict([('a', 1), ('b', 2), ('c', 3)])# dict的Key是无序的
print(d)#{'a': 1, 'c': 3, 'b': 2}

od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])# OrderedDict的Key是有序的
print(od)#OrderedDict([('a', 1), ('b', 2), ('c', 3)])

注:“OrderedDict的Key会根据插入的顺序排列,不是依据Key本人排序

 

defaultdict:使用“dict时,倘使引用的Key不设有,就会抛出KeyError。假诺期望key不存在时,重回八个暗中认可值,就足以用defaultdict

from collections import defaultdict
dd=defaultdict(lambda :'N/A')#即key不存在时返回设置的默认值
dd['k1']='abc'
print(dd['k1'])#abc
print(dd['k2])#N/A

拿defaultdict举个小栗子:

亚洲必赢官网 16亚洲必赢官网 17

#有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。
#即: {'k1': 大于66 , 'k2': 小于66}

#利用字典的解决方式:
l= [11, 22, 33,44,55,66,77,88,99,90]
my_dict = {}
for value in  l:
    if value>66:
        if my_dict.has_key('k1'):
            my_dict['k1'].append(value)
        else:
            my_dict['k1'] = [value]
    else:
        if my_dict.has_key('k2'):
            my_dict['k2'].append(value)
        else:
            my_dict['k2'] = [value]



#利用defaultdict的解决方法:
from collections import defaultdict

l= [11, 22, 33,44,55,66,77,88,99,90]

my_dict = defaultdict(list)

for value in l:
    if value>66:
        my_dict['k1'].append(value)
    else:
        my_dict['k2'].append(value)

View Code

 

Counter:Counter类的指标是用来跟踪值出现的次数。它是七个无序的器皿类型,以字典的键值对格局储存,其瓜时素作为key,其计数作为value。计数值可以是不管37二10一的Interger(包罗0和负数)。

c = Counter('abcdeabcdabcaba')
print c
#Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})

 

 var _TemplateReg = v.Value.TemplateReg.Replace("\\", "\\\\");

亚洲必赢官网 18亚洲必赢官网 19

亚洲必赢官网 20

岁月模块

  在Python中,平常有那三种方法来代表时间:时间戳(timestamp)、元组(struct_time)、格式化的光阴字符串(Format
String) 

  (一)时间戳(timestamp)
:平常来说,时间戳表示的是从一九七零年10月30日00:00:00始发按秒总计的偏移量。大家运营“type(time.time())”,再次来到的是float类型。

  (二)格式化的日子字符串(Format
String):表现情势为 ‘一九9玖-1二-0陆’,下文子禽详细介绍

  (3)元组(struct_time)
:struct_time元组共有8个因素共7个因素:(年,月,日,时,分,秒,一年中第几周,一年中第几天和是还是不是是夏令时)

注:时间戳是电脑能够识其他时间;时间字符串是人能够看懂的光阴;元组则是用来操作时间的

索引(Index) 属性(Attribute) 值(Values)
0 tm_year(年) 比如2011
1 tm_mon(月) 1 – 12
2 tm_mday(日) 1 – 31
3 tm_hour(时) 0 – 23
4 tm_min(分) 0 – 59
5 tm_sec(秒) 0 – 61
6 tm_wday(weekday) 0 – 6(0表示周日)
7 tm_yday(一年中的第几天) 1 – 366
8 tm_isdst(是否是夏令时) 默认为-1
import time
#时间戳
print(time.time())#1502179789.9325476
#时间字符串,%都有对应的意思
print(time.strftime('%Y-%m-%d %X'))#2017-08-08 16:09:49
#时间元祖
print(time.localtime())#time.struct_time(tm_year=2017, tm_mon=8, tm_mday=8, tm_hour=16, tm_min=9, tm_sec=49, tm_wday=1, tm_yday=220, tm_isdst=0)

有关于岁月字符串中的格式化符号,具体如下:

亚洲必赢官网 21亚洲必赢官网 22

%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身

python中时间日期格式化符号:

View Code

 

两种格式之间的更换方式如下图:

亚洲必赢官网 23

具体方法如下:

#时间戳转化为结构化时间(元祖)-->time.gmtime()  time.localtime()
print(time.gmtime())#UTC时间,即格林尼治时间,与英国伦敦当地时间一致
print(time.localtime())#当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时 = 北京时间
#如果括号内有参数,则输出的是参数所代表的时间
print(time.gmtime(1500000000))#time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)
print(time.localtime(1500000000))#time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)

#结构化时间(元祖)转化为时间戳-->time.mktime(结构化的时间)
print(time.mktime(time.localtime()))#1502180872.0

#结构化时间(元祖)转换为字符串时间(格式化)-->time.strftime("格式定义","结构化时间")  结构化时间参数若不传,则现实当前时间
print(time.strftime('%Y-%m-%d %X'))#2017-08-08 16:30:16
print(time.strftime("%Y-%m-%d %X",time.localtime(1500000000)))#2017-07-14 10:40:00

#字符串时间(格式化)转化为结构化时间(元祖)-->time.strptime(时间字符串,字符串对应格式)
print(time.strptime("2017-03-16","%Y-%m-%d"))#time.struct_time(tm_year=2017, tm_mon=3, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=75, tm_isdst=-1)
print(time.strptime("07/24/2017","%m/%d/%Y"))#time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=205, tm_isdst=-1)

 

除此以外还有1种特别的更换格局,如下图:

亚洲必赢官网 24

具体方法如下:

#结构化时间(元祖)转化为%a %b %d %H:%M:%S %Y串-->time.asctime(结构化时间),如果不传参数,直接返回当前时间的格式化串
print(time.asctime())#Tue Aug  8 16:47:55 2017
print(time.asctime(time.localtime(1500000000)))#Tue Aug  8 16:47:55 2017

#%a %d %d %H:%M:%S %Y串转化为结构化时间-->time.ctime(时间戳),如果不传参数,直接返回当前时间的格式化串
print(time.ctime())#Tue Aug  8 16:49:54 2017
print(time.ctime(1500000000))#Fri Jul 14 10:40:00 2017

 

在C#中\\表示\,\\\\就表示\\。

import re
phone_number = input('please input your phone number : ')
if re.match('^(13|14|15|18)[0-9]{9}$',phone_number):
        print('是合法的手机号码')
else:
        print('不是合法的手机号码')
stat 结构:

st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。

random模块

  random模块的功效便是随机,可任意生成整数、小数、字母,首要的施用措施是生成验证码。

import random
print(random.random())#随机生成0-1之间的小数
print(random.uniform(1,3))#随机生成1-3之间的小数
#
# 生成四个随机整数:
l = []
l.append(str(random.randint(0,9)))
l.append(str(random.randint(0,9)))
l.append(str(random.randint(0,9)))
l.append(str(random.randint(0,9)))
print(''.join(l))#随机四个数,如4041
print(l)#随机四个数组成的列表,如['4', '0', '4', '1']

print(random.randint(1000,9999))#随机生成1000-9999之间的整数,也可以视为给了四个随机整数的一种方法
print(random.randrange(1,7,2))#也可以使用步距

ret = random.choice([1,2,'b',4,'a',6])
print(ret)#随机从列表的元素中取出一个
ret = random.sample([1,2,'b',4,'a',6],3)
print(ret)#随机从列表的元素中取出三个

l = list(range(100))
random.shuffle(l)#随机打乱l中的顺序,
print(l)

random模块的叁个至关首要应用场景是生成验证码,下边举几个板栗:

亚洲必赢官网 25亚洲必赢官网 26

#写一个验证码,首先要有数字,其次要有字母,一共4位,可以重复
new_num_l = list(map(str,range(10)))  #['0','1'...'9']
# alph_l = []   #用来存字母
# for i in range(65,91):#查询ascii码得到英文字母A-Z对应的数字为65-90
#     alph = chr(i)
#     alph_l.append(alph)   #['A'..'Z']
alph_l = [chr(i) for i in range(65,91)]  #列表推导式
new_num_l.extend(alph_l)
Alph_l = [chr(i) for i in range(97,124)]
new_num_l.extend(Alph_l)
# ret_l = []   #存生成的随机数字或字母
# for i in range(4):
#     ret_l.append(random.choice(new_num_l))
ret_l = [random.choice(new_num_l) for i in range(4)]
#ret_l中有4个元素
# ret = random.sample(new_num_l,4)
print(''.join(ret_l))



#高级方法:
def myrandom():
    new_num_l = list(map(str,range(10)))
    alph_l = [chr(i) for i in range(65,91)]  #列表推导式
    Alph_l = [chr(i) for i in range(97,124)]
    new_num_l.extend(alph_l)
    new_num_l.extend(Alph_l)
    ret_l = [random.choice(new_num_l) for i in range(4)]
    return ''.join(ret_l)
print(myrandom())

View Code

 

前边在三个全局变量中储存了好多数量,以往自家索要将其储存到数据库中。原来的代码如下:

判断手提式有线话机号码是还是不是合法二

亚洲必赢官网 27

os模块

 os模块是与操作系统交互的3个接口

亚洲必赢官网 28亚洲必赢官网 29

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.environ  获取系统环境变量
os.path.abspath(path)  返回path规范化的绝对路径
os.path.split(path)  将path分割成目录和文件名二元组返回
os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小

有着关于os模块的章程

在Linux和Mac平台上,该函数会原样返回path,在windows平台上会将路径中所有字符转换为小写,并将所有斜杠转换为饭斜杠。
>>> os.path.normcase('c:/windows\\system32\\')   
'c:\\windows\\system32\\'   


规范化路径,如..和/
>>> os.path.normpath('c://windows\\System32\\../Temp/')   
'c:\\windows\\Temp'   

>>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'
>>> print(os.path.normpath(a))
/Users/jieli/test1

os路径处理
#方式一:推荐使用
import os
#具体应用
import os,sys
possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一级
    os.pardir,
    os.pardir
))
sys.path.insert(0,possible_topdir)


#方式二:不推荐使用
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

 

 

 

亚洲必赢官网 30亚洲必赢官网 31

相比下边的三种写法,此时此刻,笔者要问您你喜爱哪一种办法呀?你一定依旧会说第3种,为啥吧?因为第3种不用学呀!
而是借使明日有一个文书,作者让你从一切文件里相称出全数的手提式有线电话机号码。你用python给本人写个试试?
唯独学了后天的技能之后,分分钟帮您解决!

stat 结构

sys模块

sys模块是与python解释器交互的三个接口

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称

 

        /// <summary>
        /// 短信模板
        /// </summary>
        #region old code
        Dictionary<string, SmsTemplate> templates = new Dictionary<string, SmsTemplate> {
            // 能耗日报模板  
            {
                "能耗提醒",
                new SmsTemplate {
                    TemplateCode = "SMS_139242133",
                    TemplateReg = @"测试短信通知",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "紫衡技术"
                }
            },
            {
                "测试",
                new SmsTemplate {
                    TemplateCode = "SMS_119091381",
                    TemplateReg = @"测试短信通知",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "紫衡技术"
                }
            },
            {
                "能耗",
                new SmsTemplate {
                    TemplateCode = "SMS_119076277",
                    TemplateReg = @"^[^(上周)|(上月)]*(能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*$",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            {
                "能耗Extend",
                new SmsTemplate
                {
                    TemplateCode = "SMS_128880488",
                    TemplateReg = @"^[^(上周)|(上月)]*(能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*$",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty, extend=string.Empty},
                    SignName = "能耗报告"
                }
            },
            {
                "昨日能耗",
                new SmsTemplate {
                    TemplateCode = "SMS_139242142",
                    TemplateReg = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{3}).*",//昨日总能耗16677.6度。 (天心区鑫远白天鹅酒店)星期一【紫衡技术】
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
             {
                "昨日能耗1",
                new SmsTemplate {
                    TemplateCode = "SMS_139242142",
                    TemplateReg = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。\【(.*)\】(\d{4}-\d{2}-\d{2}).*",//昨日总能耗209.9度。【长沙市天心区人民检察院】2018-07-08【紫衡技术】
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            {
                "上周能耗",
                new SmsTemplate {
                    TemplateCode = "SMS_119081757",
                    TemplateReg = @".*(上周总?能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            {
                "上月能耗",
                new SmsTemplate {
                    TemplateCode = "SMS_119086386",
                    TemplateReg = @".*(上月总?能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            {
                "定额",
                new SmsTemplate {
                    TemplateCode = "SMS_119076277",
                    TemplateReg = @".*(定额)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            {
                "基准",
                new SmsTemplate {
                    TemplateCode = "SMS_119076277",
                    TemplateReg = @".*(基准)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            {
                "节能量",
                new SmsTemplate {
                    TemplateCode = "SMS_119076277",
                    TemplateReg = @".*(节能量)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            {
                "优化",
                new SmsTemplate {
                    TemplateCode = "SMS_119076277",
                    TemplateReg = @".*(优化)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, energy=string.Empty },
                    SignName = "能耗报告"
                }
            },
            // 报警日报模板
            {
                "报警",
                new SmsTemplate {
                    TemplateCode = "SMS_119076278",
                    TemplateReg = @"(建筑\[)*(.+?)([\],,])*产生以下报警:(.+)(【紫衡技术】)",
                    TemplateParam =  new { name=string.Empty, date=string.Empty, alarm=string.Empty },
                    SignName = "能管系统报警"
                }
            },
            // 运维工单模板
            {
                "运维通知",
                new SmsTemplate {
                    TemplateCode = "SMS_119091206",
                    TemplateReg = "您有一条新的(.+)工单需处理【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "运维抢单",
                new SmsTemplate {
                    TemplateCode = "SMS_119076276",
                    TemplateReg = "您有一条新的(.+)工单(提示)*【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "运维派单",
                new SmsTemplate {
                    TemplateCode = "SMS_119076273",
                    TemplateReg =  "您有新的(.+)工单无人[抢|接]单【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "库存不足",
                new SmsTemplate {
                    TemplateCode = "SMS_119091203",
                    TemplateReg =  ".+【([^】]+)】.+库存已不足.+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "维修签到",
                new SmsTemplate {
                    TemplateCode = "SMS_119076712",
                    TemplateReg =  ".*您有(.*)未签到【工单号:([^】]+)】.+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            }

            ,
            {
                "报警抢单",
                new SmsTemplate {
                    TemplateCode = "SMS_119091869",
                    TemplateReg =  "您有(.*)报警.*无人[抢|接]单【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            }
            ,
            {
                "广医派工",
                new SmsTemplate {
                    TemplateCode = "SMS_135795374",
                    TemplateReg =  "您有新的(.+)工单(.+)需处理,详情请打开“智慧机电运维系统APP”查看。",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            }
            ,
            {
                "报警签到",
                new SmsTemplate {
                    TemplateCode = "SMS_119081998",
                    TemplateReg =  "您有(.*)报警事件未现场签到【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "未处理完崔单",
                new SmsTemplate {
                    TemplateCode = "SMS_119076997",
                    TemplateReg =  "您有(.*)处理尚未完成【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "运维崔单",
                new SmsTemplate {
                    TemplateCode = "SMS_119087014",
                    TemplateReg =  "您有一条(.+)催单提示【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "运维工单事件",
                new SmsTemplate {
                    TemplateCode = "SMS_119091936",
                    TemplateReg =  "您有新的工单事件【工单号[::]([^】]+).+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "运维系统"
                }
            },
            {
                "MAN服务未找到异常",
                new SmsTemplate {
                    TemplateCode = "SMS_120120306",
                    TemplateReg =  "^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+",
                    TemplateParam =  new { type=string.Empty, code=string.Empty },
                    SignName = "能管365"
                }
            }

        };
        #endregion

明天大家要学习python里的re模块和正则表明式,学会了那个就足以帮我们缓解刚刚的疑团。正则表明式不仅在python领域,在全部编制程序届都占据首要的地点。

 

类别化模块

将原来的字典、列表等剧情转换到2个字符串的进程就叫做序列化

 

字符串str——通过反连串化——数据结构

 

数据结构——通过体系化——字符串str

 

亚洲必赢官网 32亚洲必赢官网 33

比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。
但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。
你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串,
但是你要怎么把一个字符串转换成字典呢?
聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)

注意事项

种类化的指标

一、以某种存款和储蓄格局使自定义对象持久化;

二、将对象从三个地点传递到另一个地点。

三、使程序更具维护性。

Json模块是种类化模块的一种,提供了多个效益:dumps、dump、loads、load,上面是实效:

亚洲必赢官网 34亚洲必赢官网 35

#dumps和loads的用法
import json
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)  #序列化:将一个字典转换成一个字符串
print(type(str_dic),str_dic)  #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"}
#注意,json转换完的字符串类型的字典中的字符串是由""表示的

dic2 = json.loads(str_dic)  #反序列化:将一个字符串格式的字典转换成一个字典
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
print(type(dic2),dic2)  #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}


list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型 
print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]



#dump和load的用法
import json
f = open('json_file','w')
dic = {'k1':'v1','k2':'v2','k3':'v3'}
json.dump(dic,f)  #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
f.close()

f = open('json_file')
dic2 = json.load(f)  #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
f.close()
print(type(dic2),dic2)

View Code

 

pickle模块也是连串化的1种,它与json极其相似,甚至说比json还要厉害。

    json是用以字符串 和
python数据类型间展开转移,pickle是用于python特有的类型 和
python的数据类型间实行转换

    pickle模块提供了八个成效:dumps、dump(系列化,存)、loads(反体系化,读)、load
 (不仅能够类别化字典,列表…        
能够把python中自由的数据类型系列化

注:那里大家要证实一下,json是一种具有的语言都足以识其他数据结构。倘使大家将2个字典也许列表系列化成了三个json存在文件里,那么java代码可能js代码也足以拿来用。不过一旦大家用pickle实行种类化,其他语言就无法读懂那是如何了。所以,假设您体系化的情节是列表可能字典,非凡推荐使用json模块。但假设由于某种原因你不得不连串化别的的数据类型,而未来还会用python对这么些数额实行反种类化的话,那么就足以选用pickle。

此间对pickle模块的用法实行验证:

import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)
print(str_dic)  #一串二进制内容

dic2 = pickle.loads(str_dic)
print(dic2)    #字典

import time
struct_time  = time.localtime(1000000000)
print(struct_time)
f = open('pickle_file','wb')
pickle.dump(struct_time,f)
f.close()

f = open('pickle_file','rb')
struct_time2 = pickle.load(f)
print(struct_time.tm_year)

 

View Code

亚洲必赢官网 36亚洲必赢官网 37

重临顶部

shelve模块

shelve也是python提必要我们的种类化学工业具,比pickle用起来更简雅培(Abbott)些。shelve只提须求我们叁个open方法,是用key来访问的,使用起来和字典类似。

import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操作,就可以存入数据
f.close()

import shelve
f1 = shelve.open('shelve_file')
existing = f1['key']  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)

这几个模块有个限制,它不帮助多少个利用同方今间往同三个DB进行写操作。所以当大家驾驭大家的选择要是只实行读操作,大家能够让shelve通过只读格局打开DB

import shelve
f = shelve.open('shelve_file', flag='r')
existing = f['key']
f.close()
print(existing)

由于shelve在暗许景况下是不会记录待持久化对象的别的修改的,所以我们在shelve.open()时候需求修改暗中认可参数,不然对象的改动不会保留。

import shelve
f1 = shelve.open('shelve_file')
print(f1['key'])
f1['key']['new_value'] = 'this was not here before'
f1.close()

f2 = shelve.open('shelve_file', writeback=True)
print(f2['key'])
f2['key']['new_value'] = 'this was not here before'
f2.close()

writeback格局有帮助和益处也有弱点。优点是缩减了大家失误的可能率,并且让对象的持久化对用户越来越的晶莹了;但这种艺术并不是具有的动静下都急需,首先,使用writeback未来,shelf在open()的时候会增多额外的内存消耗,并且当DB在close()的时候会将缓存中的每贰个指标都写入到DB,那也会拉动相当的等待时间。因为shelve没有艺术知道缓存中哪些对象修改了,哪些对象未有改动,因而具有的对象都会被写入。

 

 

自身想一向通过代码来机关将其搬迁到mysql数据库中去。

不管以后你是不是去做python开发,只要你是一个程序员就应该了解正则表达式的基本使用。如果未来你要在爬虫领域发展,你就更应该好好学习这方面的知识。
但是你要知道,re模块本质上和正则表达式没有一毛钱的关系。re模块和正则表达式的关系 类似于 time模块和时间的关系
你没有学习python之前,也不知道有一个time模块,但是你已经认识时间了 12:30就表示中午十二点半(这个时间可好,一般这会儿就该下课了)。
时间有自己的格式,年月日时分秒,12个月,365天......已经成为了一种规则。你也早就牢记于心了。time模块只不过是python提供给我们的可以方便我们操作时间的一个工具而已

sys模块

 hashlib模块

  hashlib模块的成效是提供了周围的摘要算法,如MD伍,SHA壹,SHA25陆,SHA512等等

  那么,什么是摘要算法呢?摘要算法便是足以把自由长度的数量转换为定位长度的字符串(经常用1陆进制的字符串表示)。摘要算法就是经过摘要函数f()对轻易长度的数额data计算出一定长度的摘要digest,目标是为了发现原本数据是还是不是被人篡改过,也足以用来加密文书。

  摘要算法之所以能建议数据是还是不是被篡改过,正是因为摘要函数是2个单向函数,计算f(data)很简单,但通过digest反推data却非凡困难。而且,对原本数据做1个bit的修改,都会促成总括出的摘要完全两样。

此地以科学普及的摘要算法MD5为例,总结出一个字符串的MD5值:

import hashlib

obj = hashlib.md5()
obj.update('what is your name?')
print md5.hexdigest()

计算结果如下:
d26a53750bc40b38b65a520292f69306


#如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:
obj= hashlib.md5()
obj.update('hello,my name is jack')
obj.update('what is your name')
obj.update('nice to meet you')
obj.update('goodbye')
print md5.hexdigest()
#其结果与将所有的话合成一句话后调用摘要算法的结果完全一样

 

MD五是最广泛的摘要算法,速度急忙,生成结果是原则性的128bit字节,经常用2个三十四个人的16进制字符串表示。另1种普遍的摘要算法是SHA一,调用SHA壹和调用MD5截然类似:

import hashlib

sha1 = hashlib.sha1()
sha1.update('you motherfuker ')
sha1.update('oh shit,get out of here!')
print sha1.hexdigest()

 

摘要算法的一大使用正是将文件实行加密。

  任何允许用户登录的网址都会存款和储蓄用户登录的用户名和口令。怎么样存款和储蓄用户名和口令呢?方法是存到数据库表中。假若以公开保存用户口令,借使数据库败露,全体用户的口令就落入黑客的手里。其余,网站运转人士是足以访问数据库的,也正是能取获得拥有用户的口令。正确的保存口令的主意是不存储用户的公然口令,而是存储用户口令的摘要,比如MD5。

  不过假设您的口令设置的过火简短比如‘1二③’,‘abc’之类的,攻击者能够达成算出那一个值的摘要,然后来拓展比对,1旦有用户的口令不难到被黑客猜中了,就会收到攻击。所以那便是干什么都推荐我们将密码设置的相对复杂的来由,诸如12三、888、生日之类的尽量制止。

  当然啦,为了掩护那几个脑回路简单的用户的平安,网址的程序员在编码时也会对考虑到这么些难题并采纳对应的诀要。1般是通过对原始口令加八个犬牙相错字符串来落到实处,俗称“加盐”

import hashlib

sha1 = hashlib.sha1(‘i am the salt’)#在初始位置加个东西,每个人的口令都会加上这一串,从而起到复杂化的作用,俗称‘加盐’
sha1.update('you motherfuker ')
sha1.update('oh shit,get out of here!')
print sha1.hexdigest()

  经过加盐处理的MD伍口令,只要‘盐’不被黑客知道,固然用户输入不难口令,就很难通过MD五反推明文口令。

  可是假若有五个用户都利用了平等的简要口令比如12345陆,在数据库中,将积存两条相同的MD5值,那阐明那五个用户的口令是一律的。有未有办法让动用同一口令的用户存款和储蓄分化的MD5呢?即便壹旦用户不恐怕修改登录名,就足以由此把登录名作为Salt的1有的来测算MD伍,从而完结均等口令的用户也蕴藏不一样的MD五。

 注:摘要算法不是加密算法,不可能用于加密(因为不也许通过摘要反推明文),只好用来防篡改,不过它的单向总括性情决定了能够在不存款和储蓄明文口令的场合下验证用户口令。

 

        /// <summary>
        /// 初始化数据,将原来代码中的模板配置生成并加载到数据库中
        /// </summary>
        /// <param name="templates"></param>
        /// <returns></returns>
        public int InitData(Dictionary<string, SmsTemplate> templates)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("INSERT INTO smstemplate VALUES");
            foreach(var v in templates)
            {
                var _TemplateReg = v.Value.TemplateReg.Replace("\\", "\\\\");
                sb.AppendFormat(@"('{0}','{1}','{2}','{3}','{4}'),",v.Key,v.Value.TemplateCode, _TemplateReg, JsonConvert.SerializeObject(v.Value.TemplateParam),v.Value.SignName);
            }
            string sql= sb.ToString().TrimEnd(',');
            var cmd = db.GetSqlStringCommand(sql);
            return db.ExecuteNonQuery(cmd);
        }
        /// <summary>
        /// 从数据库中加载模板配置列表
        /// </summary>
        /// <returns>模板配置列表</returns>
        public Dictionary<string, SmsTemplate> GetSmsTemplate()
        {
            Dictionary<string, SmsTemplate> dic = new Dictionary<string, SmsTemplate>();
            var sql = "SELECT `Key`,`TemplateCode`,`TemplateReg`,`TemplateParam`,`SignName` FROM smstemplate";
            try
            {
                var cmd = db.GetSqlStringCommand(sql);
                SmsTemplate item;
                string key;
                using (var reader = db.ExecuteReader(cmd))
                {
                    while (reader.Read())
                    {
                        key = reader.GetString(0);
                        item = new SmsTemplate();
                        item.TemplateCode = reader.GetString(1);
                        item.TemplateReg = reader.GetString(2);
                        item.TemplateParam = (JObject)JsonConvert.DeserializeObject(reader.GetString(3));
                        item.SignName = reader.GetString(4);
                        dic.Add(key, item);
                    }
                }
            }
            catch(Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return dic;
        }

构造完成后的sql脚本:

正则表达式和re模块

sys模块是与python解释器交互的一个接口

configparser模块

该模块适用于配置文件的格式与windows
ini文件类似,能够分包2个或多个节(section),每一个节能够有多个参数(键=值)。

来看二个浩大软件的普遍文书档案格式如下:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no

接下去大家用python生成一个那样的文书档案

import configparser

config = configparser.ConfigParser()

config["DEFAULT"] = {'ServerAliveInterval': '45',
                      'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11':'yes'
                     }

config['bitbucket.org'] = {'User':'hg'}

config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}

with open('example.ini', 'w') as configfile:

   config.write(configfile)

查找文件

import configparser

config = configparser.ConfigParser()

#---------------------------查找文件内容,基于字典的形式

print(config.sections())        #  []

config.read('example.ini')

print(config.sections())        #   ['bitbucket.org', 'topsecret.server.com']

print('bytebong.com' in config) # False
print('bitbucket.org' in config) # True


print(config['bitbucket.org']["user"])  # hg

print(config['DEFAULT']['Compression']) #yes

print(config['topsecret.server.com']['ForwardX11'])  #no


print(config['bitbucket.org'])          #<Section: bitbucket.org>

for key in config['bitbucket.org']:     # 注意,有default会默认default的键
    print(key)

print(config.options('bitbucket.org'))  # 同for循环,找到'bitbucket.org'下所有键

print(config.items('bitbucket.org'))    #找到'bitbucket.org'下所有键值对

print(config.get('bitbucket.org','compression')) # yes       get方法Section下的key对应的value

增加和删除改操作

import configparser

config = configparser.ConfigParser()

config.read('example.ini')

config.add_section('yuan')



config.remove_section('bitbucket.org')
config.remove_option('topsecret.server.com',"forwardx11")


config.set('topsecret.server.com','k1','11111')
config.set('yuan','k2','22222')

config.write(open('new2.ini', "w"))

 

亚洲必赢官网 38亚洲必赢官网 39

正则表明式

壹说规则本人早已知道您很晕了,现在就让大家先来看一些实际上的应用。在线测试工具 

首先你要知道的是,谈到正则,就只和字符串相关了。在我给你提供的工具中,你输入的每一个字都是一个字符串。
其次,如果在一个位置的一个值,不会出现什么变化,那么是不需要规则的。
  比如你要用"1"去匹配"1",或者用"2"去匹配"2",直接就可以匹配上。这连python的字符串操作都可以轻松做到。
那么在之后我们更多要考虑的是在同一个位置上可以出现的字符的范围。

字符组 : [字符组]
在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示
字符分为很多类,比如数字、字母、标点等等。
假如你现在要求一个位置"只能出现一个数字",那么这个位置上的字符只能是0、1、2...9这10个数之一。
正则
待匹配字符
匹配
结果
说明
[0123456789]
8
True
在一个字符组里枚举合法的所有字符,字符组里的任意一个字符
和"待匹配字符"相同都视为可以匹配
[0123456789]
a
False
由于字符组中没有"a"字符,所以不能匹配
 

[0-9]
 

7
True
也可以用-表示范围,[0-9]就和[0123456789]是一个意思
 

[a-z]
 

s
 

True
 

同样的如果要匹配所有的小写字母,直接用[a-z]就可以表示
 

[A-Z]
 

B
 

True
 

[A-Z]就表示所有的大写字母
 

[0-9][a-f][A-F]
 

e
 

True
 

可以匹配数字,大小写形式的a~f,用来验证十六进制字符
 
sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version        获取Python解释程序的版本信息
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
INSERT INTO smstemplate
VALUES
    (
        '能耗提醒',
        'SMS_139242133',
        '测试短信通知',
        '{"name":"","date":"","energy":""}',
        '紫衡技术'
    ),
    (
        '测试',
        'SMS_119091381',
        '测试短信通知',
        '{"name":"","date":"","energy":""}',
        '紫衡技术'
    ),
    (
        '能耗',
        'SMS_119076277',
        '^[^(上周)|(上月)]*(能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*$',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '能耗Extend',
        'SMS_128880488',
        '^[^(上周)|(上月)]*(能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*$',
        '{"name":"","date":"","energy":"","extend":""}',
        '能耗报告'
    ),
    (
        '昨日能耗',
        'SMS_139242142',
        '.*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \\((.*)\\)(.{3}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '昨日能耗1',
        'SMS_139242142',
        '.*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。\\【(.*)\\】(\\d{4}-\\d{2}-\\d{2}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '上周能耗',
        'SMS_119081757',
        '.*(上周总?能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '上月能耗',
        'SMS_119086386',
        '.*(上月总?能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '定额',
        'SMS_119076277',
        '.*(定额)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '基准',
        'SMS_119076277',
        '.*(基准)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '节能量',
        'SMS_119076277',
        '.*(节能量)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '优化',
        'SMS_119076277',
        '.*(优化)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*',
        '{"name":"","date":"","energy":""}',
        '能耗报告'
    ),
    (
        '报警',
        'SMS_119076278',
        '(建筑\\[)*(.+?)([\\],,])*产生以下报警:(.+)(【紫衡技术】)',
        '{"name":"","date":"","alarm":""}',
        '能管系统报警'
    ),
    (
        '运维通知',
        'SMS_119091206',
        '您有一条新的(.+)工单需处理【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '运维抢单',
        'SMS_119076276',
        '您有一条新的(.+)工单(提示)*【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '运维派单',
        'SMS_119076273',
        '您有新的(.+)工单无人[抢|接]单【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '库存不足',
        'SMS_119091203',
        '.+【([^】]+)】.+库存已不足.+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '维修签到',
        'SMS_119076712',
        '.*您有(.*)未签到【工单号:([^】]+)】.+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '报警抢单',
        'SMS_119091869',
        '您有(.*)报警.*无人[抢|接]单【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '广医派工',
        'SMS_135795374',
        '您有新的(.+)工单(.+)需处理,详情请打开“智慧机电运维系统APP”查看。',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '报警签到',
        'SMS_119081998',
        '您有(.*)报警事件未现场签到【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '未处理完崔单',
        'SMS_119076997',
        '您有(.*)处理尚未完成【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '运维崔单',
        'SMS_119087014',
        '您有一条(.+)催单提示【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        '运维工单事件',
        'SMS_119091936',
        '您有新的工单事件【工单号[::]([^】]+).+',
        '{"type":"","code":""}',
        '运维系统'
    ),
    (
        'MAN服务未找到异常',
        'SMS_120120306',
        '^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+',
        '{"type":"","code":""}',
        '能管365'
    )

字符:

 

元字符
 

匹配内容
匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配字符串的开始
$ 匹配字符串的结尾
\W
匹配非字母或数字或下划线
\D
匹配非数字
\S
匹配非空白符
a|b
匹配字符a或字符b
()
匹配括号内的表达式,也表示一个组
[…]
匹配字符组中的字符
[^…]
匹配除了字符组中字符的所有字符

 

亚洲必赢官网 40亚洲必赢官网 41

View Code

量词:

量词
用法说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

 

import sys
try:
    sys.exit(1)
except SystemExit as e:
    print(e)
JsonConvert.SerializeObject(v.Value.TemplateParam),把原来的对象进行序列化。
之前一直用的在线正则表达式匹配http://tool.oschina.net/regex/,不过发现不方便,于是我自己写了一个小工具。

源码下载:https://github.com/zouyujie/RegexTool
吐槽:阿里云的短信平台,短信模板中的单个变量长度不超过20个字符,而且还不支持组合变量,变量之间要用文字或者字符隔开,这样一来,假设我有需要发出去的变量文字是超过20个字符的,就不得不拆开,中间还要用字符或者汉字拆开,那么这样的话,客户收到的短信岂不是很奇葩,活生生的一些连续的描述文字被拆开了。
记录以备忘。

. ^ $

正则 待匹配字符 匹配
结果
说明
海. 海燕海娇海东 海燕海娇海东   匹配所有"海."的字符
^海. 海燕海娇海东 海燕 只从开头匹配"海."
  海.$   海燕海娇海东 海东 只匹配结尾的"海.$"

 

特别处理和status

* + ? { }

正则 待匹配字符 匹配
结果
说明
李.? 李杰和李莲英和李二棍子

李杰
李莲
李二

 

?表示重复零次或一次,即只匹配"李"后面一个任意字符

 

李.* 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
*表示重复零次或多次,即匹配"李"后面0或多个任意字符
李.+ 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
+表示重复一次或多次,即只匹配"李"后面1个或多个任意字符
李.{1,2} 李杰和李莲英和李二棍子

李杰和
李莲英
李二棍

{1,2}匹配1到2次任意字符

 注意:前面的*,+,?等都是名缰利锁匹配,也便是拼命三郎相配,后边加?号使其成为惰性匹配

正则 待匹配字符 匹配
结果
说明
李.*? 李杰和李莲英和李二棍子

惰性匹配

 

 

字符集[][^]

正则 待匹配字符 匹配
结果
说明
李[杰莲英二棍子]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

 

表示匹配"李"字后面[杰莲英二棍子]的字符任意次

 

李[^和]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

表示匹配一个不是"和"的字符任意次
[\d] 456bdha3

4
5
6
3

表示匹配任意一个数字,匹配到4个结果
[\d]+ 456bdha3

456
3

表示匹配任意个数字,匹配到2个结果

 

回去顶部

分组 ()与 或 |[^]

 身份证号码是三个长短为15或1柒个字符的字符串,要是是二1贰人则全体️数字组合,首位不可能为0;假若是二十一个人,则前壹陆个人1体是数字,倒数一位恐怕是数字或x,下边大家尝试用正则来代表:

正则 待匹配字符 匹配
结果
说明
^[1-9]\d{13,16}[0-9x]$ 110101198001017032

110101198001017032

   表示可以匹配一个正确的身份证号
^[1-9]\d{13,16}[0-9x]$ 1101011980010170

1101011980010170

表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字
^[1-9]\d{14}(\d{2}[0-9x])?$ 1101011980010170

False

现在不会匹配错误的身份证号了
()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ 110105199812067023

110105199812067023

表示先匹配[1-9]\d{16}[0-9x]如果没有匹配上就匹配[1-9]\d{14}

 

种类化模块

转义符 \

在正则表明式中,有不少有异样意义的是元字符,比如\d和\s等,如若要在正则中万分平常的”\d”而不是”数字”就供给对”\”进行转义,变成’\\’。

在python中,无论是正则表明式,照旧待相称的始末,都以以字符串的样式出现的,在字符串中\也有特异的意义,本人还供给转义。所以假如合营一遍”\d”,字符串中要写成’\\d’,那么正则里即将写成”\\\\d”,这样就太难为了。今年大家就用到了r’\d’那一个概念,此时的正则是r’\\d’就足以了。

正则 待匹配字符 匹配
结果
说明
\d \d  False
因为在正则表达式中\是有特殊意义的字符,所以要匹配\d本身,用表达式\d无法匹配
\\d \d  True
转义\之后变成\\,即可匹配
"\\\\d" ‘\\d’  True
如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次
r’\\d’ r’\d’  True
在字符串之前加r,让整个字符串不转义

 

 

贪欲相配

贪得无厌相配:在知足相配时,匹配尽可能长的字符串,默许情状下,接纳贪婪匹配

正则 待匹配字符 匹配
结果
说明
<.*>

<script>…<script>

<script>…<script>
默认为贪婪匹配模式,会匹配尽量长的字符串
<.*?> r’\d’  

<script>
<script>

加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串

何以叫类别化——将原来的字典、列表等剧情转换来二个字符串的进度就叫做序列化

多少个常用的非贪婪相称帕特tern

*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

亚洲必赢官网 42亚洲必赢官网 43

.*?的用法

亚洲必赢官网 44

. 是任意字符
* 是取 0 至 无限长度
? 是非贪婪模式。
何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
.*?x

就是取前面任意长度的字符,直到一个x出现

亚洲必赢官网 45

亚洲必赢官网 46

re模块下的常用方法

 

亚洲必赢官网 47

import re

ret = re.findall('a', 'eva egon yuan')  # 返回所有满足匹配条件的结果,放在列表里
print(ret) #结果 : ['a', 'a']

ret = re.search('a', 'eva egon yuan').group()
print(ret) #结果 : 'a'
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

ret = re.match('a', 'abc').group()  # 同search,不过尽在字符串开始处进行匹配
print(ret)
#结果 : 'a'

ret = re.split('[ab]', 'abcd')  # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)  # ['', '', 'cd']

ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个
print(ret) #evaHegon4yuan4

ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret)

obj = re.compile('\d{3}')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123

import re
ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  #查看第一个结果
print(next(ret).group())  #查看第二个结果
print([i.group() for i in ret])  #查看剩余的左右结果

亚洲必赢官网 48

 

比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。
但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。
你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串,
但是你要怎么把一个字符串转换成字典呢?
聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)

【python】正则表明式-group和group的区分

正则表明式中,group()用来建议分组截获的字符串,()用来分组

1
2
3
4
5
6
7
8
 
import re
= "123abc456"
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group()   #123abc456
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)  #123abc456
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)  #123
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)  #abc
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)  #456
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups()  #('123', 'abc', '456')

  上边正则表达式中的三组括号把相称结果分成3组

  •  group() 同group(0)就是相称正则表明式全体结果
  •  group(一) 列出第一个括号相配部分,group(贰)
    列出第三个括号相配部分,group(三) 列出首个括号匹配部分。
  • groups()是把具有相配出来的分组参新币组中
 1
2
3
4
5
 
import re
= "123abc456"
print re.search("[0-9]*[a-z]*[0-9]*",a).group()   #123abc456
print re.search("[0-9]*[a-z]*[0-9]*",a).group(0)  #123abc456
print re.search("[0-9]*[a-z]*[0-9]*",a).groups()  #()

 当然正则表达式中向来不括号分组,group(1)和groups肯定不对了。

 

注意:

亚洲必赢官网 49

① findall的先期级查询:

亚洲必赢官网 50

import re

ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['oldboy']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['www.oldboy.com']

亚洲必赢官网 51

 

干什么要有体系化模块

二 split的预先级查询

亚洲必赢官网 52

ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : ['eva', 'egon', 'yuan']

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']

#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
#这个在某些需要保留匹配部分的使用过程是非常重要的。

亚洲必赢官网 53

 

类别化的指标

练习

一、以某种存储形式使自定义对象持久化;

一、相配标签

亚洲必赢官网 54亚洲必赢官网 55

import re


ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
#还可以在分组中利用?<name>的形式给分组起名字
#获取的匹配结果可以直接用group('名字')拿到对应的值
print(ret.group('tag_name'))  #结果 :h1
print(ret.group())  #结果 :<h1>hello</h1>

ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
#如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
#获取的匹配结果可以直接用group(序号)拿到对应的值
print(ret.group(1))
print(ret.group())  #结果 :<h1>hello</h1>

View Code

 

贰、将对象从二个地点传递到另3个地点。

二、相配整数

亚洲必赢官网 56亚洲必赢官网 57

import re

ret=re.findall(r"\d+","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) #['1', '2', '60', '40', '35', '5', '4', '3']
ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) #['1', '-2', '60', '', '5', '-4', '3']
ret.remove("")
print(ret) #['1', '-2', '60', '5', '-4', '3']

View Code

 

三、使程序更具维护性。

三、数字相称

亚洲必赢官网 58亚洲必赢官网 59

1、 匹配一段文本中的每行的邮箱
      http://blog.csdn.net/make164492212/article/details/51656638

2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;

   分别取出1年的12个月(^(0?[1-9]|1[0-2])$)、
   一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$

3、 匹配qq号。(腾讯QQ号从10000开始)  [1,9][0,9]{4,}

4、 匹配一个浮点数。       ^(-?\d+)(\.\d+)?$   或者  -?\d+\.?\d*

5、 匹配汉字。             ^[\u4e00-\u9fa5]{0,}$ 

6、 匹配出所有整数

View Code

 

亚洲必赢官网 60

4、爬虫演习

亚洲必赢官网 61亚洲必赢官网 62

import requests

import re
import json

def getPage(url):

    response=requests.get(url)
    return response.text

def parsePage(s):

    com=re.compile('<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?(?P<title>.*?)'
                   '.*?(?P<rating_num>.*?).*?(?P<comment_num>.*?)评价',re.S)

    ret=com.finditer(s)
    for i in ret:
        yield {
            "id":i.group("id"),
            "title":i.group("title"),
            "rating_num":i.group("rating_num"),
            "comment_num":i.group("comment_num"),
        }

def main(num):

    url='https://movie.douban.com/top250?start=%s&filter='%num
    response_html=getPage(url)
    ret=parsePage(response_html)
    print(ret)
    f=open("move_info7","a",encoding="utf8")

    for obj in ret:
        print(obj)
        data=json.dumps(obj,ensure_ascii=False)
        f.write(data+"\n")

if __name__ == '__main__':
    count=0
    for i in range(10):
        main(count)
        count+=25

View Code

 

 

json

Json模块提供了四个功能:dumps、dump、loads、load

亚洲必赢官网 63亚洲必赢官网 64

亚洲必赢官网 65

import json
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)  #序列化:将一个字典转换成一个字符串
print(type(str_dic),str_dic)  #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"}
#注意,json转换完的字符串类型的字典中的字符串是由""表示的

dic2 = json.loads(str_dic)  #反序列化:将一个字符串格式的字典转换成一个字典
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
print(type(dic2),dic2)  #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}


list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型 
print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]

亚洲必赢官网 66

loads和dumps

亚洲必赢官网 67亚洲必赢官网 68

亚洲必赢官网 69

import json
f = open('json_file','w')
dic = {'k1':'v1','k2':'v2','k3':'v3'}
json.dump(dic,f)  #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
f.close()

f = open('json_file')
dic2 = json.load(f)  #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
f.close()
print(type(dic2),dic2)

亚洲必赢官网 70

load和dump

亚洲必赢官网 71亚洲必赢官网 72

亚洲必赢官网 73

import json
f = open('file','w')
json.dump({'国籍':'中国'},f)
ret = json.dumps({'国籍':'中国'})
f.write(ret+'\n')
json.dump({'国籍':'美国'},f,ensure_ascii=False)
ret = json.dumps({'国籍':'美国'},ensure_ascii=False)
f.write(ret+'\n')
f.close()

亚洲必赢官网 74

ensure_ascii关键字参数

 

pickle

 

json & pickle 模块

 

用以种类化的五个模块

 

  • json,用于字符串 和 python数据类型间展开转移
  • pickle,用于python特有的类型 和 python的数据类型间开始展览转移

 

pickle模块提供了八个作用:dumps、dump(类别化,存)、loads(反系列化,读)、load
 (不仅能够连串化字典,列表…可以把python中随机的数据类型类别化

 

亚洲必赢官网 75亚洲必赢官网 76

亚洲必赢官网 77

import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)
print(str_dic)  #一串二进制内容

dic2 = pickle.loads(str_dic)
print(dic2)    #字典

import time
struct_time  = time.localtime(1000000000)
print(struct_time)
f = open('pickle_file','wb')
pickle.dump(struct_time,f)
f.close()

f = open('pickle_file','rb')
struct_time2 = pickle.load(f)
print(struct_time2.tm_year)

亚洲必赢官网 78

pickle

 

这会儿机智的你又要说了,既然pickle如此强大,为何还要学json呢?
此地大家要证美素佳儿(Friso)(Nutrilon)下,json是1种具有的语言都足以分辨的数据结构。
假诺大家将二个字典或许类别化成了贰个json存在文件里,那么java代码只怕js代码也得以拿来用。
但是如若我们用pickle举行系列化,其余语言就不可能读懂那是怎么着了~
故而,如果您系列化的始末是列表也许字典,大家相当推荐你使用json模块
但借使由于某种原因你只好系列化别的的数据类型,而现在你还会用python对这么些数据开始展览反类别化的话,那么就能够使用pickle

shelve

shelve也是python提须求大家的系列化学工业具,比pickle用起来更简美赞臣(Meadjohnson)些。
shelve只提供给咱们三个open方法,是用key来访问的,使用起来和字典类似。

亚洲必赢官网 79亚洲必赢官网 80

亚洲必赢官网 81

import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操作,就可以存入数据
f.close()

import shelve
f1 = shelve.open('shelve_file')
existing = f1['key']  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)

亚洲必赢官网 82

shelve

这些模块有个限制,它不援救八个应用同暂且间往同二个DB进行写操作。所以当大家知晓大家的选取假设只举办读操作,我们能够让shelve通过只读情势打开DB

亚洲必赢官网 83亚洲必赢官网 84

import shelve
f = shelve.open('shelve_file', flag='r')
existing = f['key']
f.close()
print(existing)

shelve只读

由于shelve在暗中同意情况下是不会记录待持久化对象的别样改动的,所以大家在shelve.open()时候供给修改默许参数,不然对象的改动不会保留。

亚洲必赢官网 85亚洲必赢官网 86

亚洲必赢官网 87

import shelve
f1 = shelve.open('shelve_file')
print(f1['key'])
f1['key']['new_value'] = 'this was not here before'
f1.close()

f2 = shelve.open('shelve_file', writeback=True)
print(f2['key'])
f2['key']['new_value'] = 'this was not here before'
f2.close()

亚洲必赢官网 88

设置writeback

writeback格局有优点也有欠缺。优点是减掉了大家失误的可能率,并且让对象的持久化对用户尤其的晶莹了;但那种办法并不是怀有的事态下都急需,首先,使用writeback以往,shelf在open()的时候会大增额外的内部存款和储蓄器消耗,并且当DB在close()的时候会将缓存中的每3个目的都写入到DB,那也会拉动相当的等候时间。因为shelve未有艺术知道缓存中什么对象修改了,哪些对象未有改动,由此全数的指标都会被写入。

 

回来顶部

re模块

讲正题从前我们先来看1个例证:

那是京东的挂号页面,打开页面我们就来看这么些须求输入个人新闻的提醒。
即使大家随便的在手提式有线电话机号码那1栏输入三个1111111111一,它会提醒大家格式有误。
其一意义是怎么落到实处的吧?
只要以往你用python写一段代码,类似:

phone_number = input('please input your phone number : ')

您怎么判断那些phone_number是官方的呢?

根据手机号码一共11位并且是只以13、14、15、18开头的数字这些特点,我们用python写了如下代码:

亚洲必赢官网 89亚洲必赢官网 90

亚洲必赢官网 91

while True:
    phone_number = input('please input your phone number : ')
    if len(phone_number) == 11 \
            and phone_number.isdigit()\
            and (phone_number.startswith('13') \
            or phone_number.startswith('14') \
            or phone_number.startswith('15') \
            or phone_number.startswith('18')):
        print('是合法的手机号码')
    else:
        print('不是合法的手机号码')

亚洲必赢官网 92

看清手提式有线电话机号码是不是合法一

这是你的写法,现在我要展示一下我的写法:

亚洲必赢官网 93亚洲必赢官网 94

import re
phone_number = input('please input your phone number : ')
if re.match('^(13|14|15|18)[0-9]{9}$',phone_number):
        print('是合法的手机号码')
else:
        print('不是合法的手机号码')

判定手提式有线电话机号码是或不是合法二

相比较下面的二种写法,此时此刻,作者要问您你喜爱哪一种艺术呀?你一定照旧会说第1种,为啥吗?因为第二种不用学呀!
但是假使今天有二个文书,作者让你从一切文件里相配出全部的手提式有线电话机号码。你用python给作者写个试试?
唯独学了今天的技术之后,分分钟帮您消除!

后天咱们要读书python里的re模块和正则表明式,学会了那个就足以帮大家缓解刚刚的问号。正则表明式不仅在python领域,在方方面面编制程序届都挤占非常重要的身份。

亚洲必赢官网 95亚洲必赢官网 96

亚洲必赢官网 97

不管以后你是不是去做python开发,只要你是一个程序员就应该了解正则表达式的基本使用。如果未来你要在爬虫领域发展,你就更应该好好学习这方面的知识。
但是你要知道,re模块本质上和正则表达式没有一毛钱的关系。re模块和正则表达式的关系 类似于 time模块和时间的关系
你没有学习python之前,也不知道有一个time模块,但是你已经认识时间了 12:30就表示中午十二点半(这个时间可好,一般这会儿就该下课了)。
时间有自己的格式,年月日时分秒,12个月,365天......已经成为了一种规则。你也早就牢记于心了。time模块只不过是python提供给我们的可以方便我们操作时间的一个工具而已

亚洲必赢官网 98

正则表明式和re模块

正则表明式本身也和python未有何关系,就是相称字符串内容的一种规则

官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

正则表明式

壹说规则本身已经知晓您很晕了,以后就让大家先来看有个别实在的施用。在线测试工具 

首先你要知道的是,谈到正则,就只和字符串相关了。在我给你提供的工具中,你输入的每一个字都是一个字符串。
其次,如果在一个位置的一个值,不会出现什么变化,那么是不需要规则的。
  比如你要用"1"去匹配"1",或者用"2"去匹配"2",直接就可以匹配上。这连python的字符串操作都可以轻松做到。
那么在之后我们更多要考虑的是在同一个位置上可以出现的字符的范围。

亚洲必赢官网 99亚洲必赢官网 100

字符组 : [字符组]
在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示
字符分为很多类,比如数字、字母、标点等等。
假如你现在要求一个位置"只能出现一个数字",那么这个位置上的字符只能是0、1、2...9这10个数之一。

字符组

正则
待匹配字符
匹配
结果
说明
[0123456789]
8
True
在一个字符组里枚举合法的所有字符,字符组里的任意一个字符
和"待匹配字符"相同都视为可以匹配
[0123456789]
a
False
由于字符组中没有"a"字符,所以不能匹配
 

[0-9]
 

7
True
也可以用-表示范围,[0-9]就和[0123456789]是一个意思
 

[a-z]
 

s
 

True
 

同样的如果要匹配所有的小写字母,直接用[a-z]就可以表示
 

[A-Z]
 

B
 

True
 

[A-Z]就表示所有的大写字母
 

[0-9a-fA-F]
 

e
 

True
 

可以匹配数字,大小写形式的a~f,用来验证十六进制字符

字符:

 

元字符
 

匹配内容
匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配字符串的开始
$ 匹配字符串的结尾
\W
匹配非字母或数字或下划线
\D
匹配非数字
\S
匹配非空白符
a|b
匹配字符a或字符b
()
匹配括号内的表达式,也表示一个组
[…]
匹配字符组中的字符
[^…]
匹配除了字符组中字符的所有字符

 

量词:

量词
用法说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

 

. ^ $

正则 待匹配字符 匹配
结果
说明
海. 海燕海娇海东 海燕海娇海东   匹配所有"海."的字符
^海. 海燕海娇海东 海燕 只从开头匹配"海."
  海.$   海燕海娇海东 海东 只匹配结尾的"海.$"

 

* + ? { }

正则 待匹配字符 匹配
结果
说明
李.? 李杰和李莲英和李二棍子

李杰
李莲
李二

 

?表示重复零次或一次,即只匹配"李"后面一个任意字符

 

李.* 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
*表示重复零次或多次,即匹配"李"后面0或多个任意字符
李.+ 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
+表示重复一次或多次,即只匹配"李"后面1个或多个任意字符
李.{1,2} 李杰和李莲英和李二棍子

李杰和
李莲英
李二棍

{1,2}匹配1到2次任意字符

 注意:前面的*,+,?等都以名缰利锁相配,也正是硬着头皮相配,后边加?号使其变为惰性匹配

正则 待匹配字符 匹配
结果
说明
李.*? 李杰和李莲英和李二棍子

惰性匹配

 

字符集[][^]

正则 待匹配字符 匹配
结果
说明
李[杰莲英二棍子]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

 

表示匹配"李"字后面[杰莲英二棍子]的字符任意次

 

李[^和]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

表示匹配一个不是"和"的字符任意次
[\d] 456bdha3

4
5
6
3

表示匹配任意一个数字,匹配到4个结果
[\d]+ 456bdha3

456
3

表示匹配任意个数字,匹配到2个结果

 

分组 ()与 或 |[^]

 身份证编号是3个长短为一伍或1九个字符的字符串,假设是1九个人则全部️数字组合,第贰个人不能够为0;若是是十八人,则前一八人一体是数字,最后一位可能是数字或x,下边我们尝试用正则来代表:

正则 待匹配字符 匹配
结果
说明
^[1-9]\d{13,16}[0-9x]$ 110101198001017032

110101198001017032

   表示可以匹配一个正确的身份证号
^[1-9]\d{13,16}[0-9x]$ 1101011980010170

1101011980010170

表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字
^[1-9]\d{14}(\d{2}[0-9x])?$ 1101011980010170

False

现在不会匹配错误的身份证号了
()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ 110105199812067023

110105199812067023

表示先匹配[1-9]\d{16}[0-9x]如果没有匹配上就匹配[1-9]\d{14}

 

转义符 \

在正则表达式中,有许多有破例含义的是元字符,比如\d和\s等,假诺要在正则中非常日常的”\d”而不是”数字”就供给对”\”举办转义,变成’\\’。

在python中,无论是正则表明式,依然待匹配的剧情,都以以字符串的花样出现的,在字符串中\也有万分的含义,本人还亟需转义。所以假设相称叁遍”\d”,字符串中要写成’\\d’,那么正则里即将写成”\\\\d”,那样就太费事了。那一年大家就用到了r’\d’这几个定义,此时的正则是r’\\d’就能够了。

正则 待匹配字符 匹配
结果
说明
\d \d  False
因为在正则表达式中\是有特殊意义的字符,所以要匹配\d本身,用表达式\d无法匹配
\\d \d  True
转义\之后变成\\,即可匹配
"\\\\d" ‘\\d’  True
如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次
r’\\d’ r’\d’  True
在字符串之前加r,让整个字符串不转义

 

贪婪相配

野心勃勃相称:在满意相配时,匹配尽也许长的字符串,暗许情形下,选择贪婪相配

正则 待匹配字符 匹配
结果
说明
<.*>

<script>…<script>

<script>…<script>
默认为贪婪匹配模式,会匹配尽量长的字符串
<.*?> r’\d’  

<script>
<script>

加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串
几个常用的非贪婪匹配Pattern

*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

.*?的用法

亚洲必赢官网 101

. 是任意字符
* 是取 0 至 无限长度
? 是非贪婪模式。
何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
.*?x

就是取前面任意长度的字符,直到一个x出现

亚洲必赢官网 102

re模块下的常用方法

 

亚洲必赢官网 103

import re

ret = re.findall('a', 'eva egon yuan')  # 返回所有满足匹配条件的结果,放在列表里
print(ret) #结果 : ['a', 'a']

ret = re.search('a', 'eva egon yuan').group()
print(ret) #结果 : 'a'
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

ret = re.match('a', 'abc').group()  # 同search,不过尽在字符串开始处进行匹配
print(ret)
#结果 : 'a'

ret = re.split('[ab]', 'abcd')  # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)  # ['', '', 'cd']

ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个
print(ret) #evaHegon4yuan4

ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret)

obj = re.compile('\d{3}')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123

import re
ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  #查看第一个结果
print(next(ret).group())  #查看第二个结果
print([i.group() for i in ret])  #查看剩余的左右结果

亚洲必赢官网 104

注意:

一 findall的事先级查询:

亚洲必赢官网 105

import re

ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['oldboy']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['www.oldboy.com']

亚洲必赢官网 106

 

2 split的预先级查询

亚洲必赢官网 107

ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : ['eva', 'egon', 'yuan']

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']

#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
#这个在某些需要保留匹配部分的使用过程是非常重要的。

亚洲必赢官网 108

 

 

练习

一、相配标签

亚洲必赢官网 109亚洲必赢官网 110

亚洲必赢官网 111

import re


ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
#还可以在分组中利用?<name>的形式给分组起名字
#获取的匹配结果可以直接用group('名字')拿到对应的值
print(ret.group('tag_name'))  #结果 :h1
print(ret.group())  #结果 :<h1>hello</h1>

ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
#如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
#获取的匹配结果可以直接用group(序号)拿到对应的值
print(ret.group(1))
print(ret.group())  #结果 :<h1>hello</h1>

亚洲必赢官网 112

View Code

 

2、相称整数

亚洲必赢官网 113亚洲必赢官网 114

亚洲必赢官网 115

import re

ret=re.findall(r"\d+","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) #['1', '2', '60', '40', '35', '5', '4', '3']
ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) #['1', '-2', '60', '', '5', '-4', '3']
ret.remove("")
print(ret) #['1', '-2', '60', '5', '-4', '3']

亚洲必赢官网 116

View Code

 

3、数字相配

亚洲必赢官网 117亚洲必赢官网 118

亚洲必赢官网 119

1、 匹配一段文本中的每行的邮箱
      http://blog.csdn.net/make164492212/article/details/51656638

2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;

   分别取出1年的12个月(^(0?[1-9]|1[0-2])$)、
   一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$

3、 匹配qq号。(腾讯QQ号从10000开始)  [1,9][0,9]{4,}

4、 匹配一个浮点数。       ^(-?\d+)(\.\d+)?$   或者  -?\d+\.?\d*

5、 匹配汉字。             ^[\u4e00-\u9fa5]{0,}$ 

6、 匹配出所有整数

亚洲必赢官网 120

View Code

 

四、爬虫演练

亚洲必赢官网 121亚洲必赢官网 122

亚洲必赢官网 123

import requests

import re
import json

def getPage(url):

    response=requests.get(url)
    return response.text

def parsePage(s):

    com=re.compile('<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?(?P<title>.*?)'
                   '.*?(?P<rating_num>.*?).*?(?P<comment_num>.*?)评价',re.S)

    ret=com.finditer(s)
    for i in ret:
        yield {
            "id":i.group("id"),
            "title":i.group("title"),
            "rating_num":i.group("rating_num"),
            "comment_num":i.group("comment_num"),
        }

def main(num):

    url='https://movie.douban.com/top250?start=%s&filter='%num
    response_html=getPage(url)
    ret=parsePage(response_html)
    print(ret)
    f=open("move_info7","a",encoding="utf8")

    for obj in ret:
        print(obj)
        data=json.dumps(obj,ensure_ascii=False)
        f.write(data+"\n")

if __name__ == '__main__':
    count=0
    for i in range(10):
        main(count)
        count+=25

亚洲必赢官网 124

View Code

亚洲必赢官网 125亚洲必赢官网 126

亚洲必赢官网 127

import re
import json
from urllib.request import urlopen

def getPage(url):
    response = urlopen(url)
    return response.read().decode('utf-8')

def parsePage(s):
    com = re.compile(
        '<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?(?P<title>.*?)'
        '.*?(?P<rating_num>.*?).*?(?P<comment_num>.*?)评价', re.S)

    ret = com.finditer(s)
    for i in ret:
        yield {
            "id": i.group("id"),
            "title": i.group("title"),
            "rating_num": i.group("rating_num"),
            "comment_num": i.group("comment_num"),
        }


def main(num):
    url = 'https://movie.douban.com/top250?start=%s&filter=' % num
    response_html = getPage(url)
    ret = parsePage(response_html)
    print(ret)
    f = open("move_info7", "a", encoding="utf8")

    for obj in ret:
        print(obj)
        data = str(obj)
        f.write(data + "\n")

count = 0
for i in range(10):
    main(count)
    count += 25

亚洲必赢官网 128

简化版

亚洲必赢官网 129亚洲必赢官网 130

亚洲必赢官网 131

flags有很多可选值:

re.I(IGNORECASE)忽略大小写,括号内是完整的写法
re.M(MULTILINE)多行模式,改变^和$的行为
re.S(DOTALL)点可以匹配任意字符,包括换行符
re.L(LOCALE)做本地化识别的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境,不推荐使用
re.U(UNICODE) 使用\w \W \s \S \d \D使用取决于unicode定义的字符属性。在python3中默认使用该flag
re.X(VERBOSE)冗长模式,该模式下pattern字符串可以是多行的,忽略空白字符,并可以添加注释

亚洲必赢官网 132

flags

 

作业

实现能计算类似 
1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式的计算器程序

 

在线测试工具 

网站地图xml地图