主要内容:
1.标点符号的特殊含义
(1)\s 表示任意空白字符,\S 表示任意非空白字符
import re
# \s 表示任意空白字符
# \S 表示任意非空白字符
m1=re.findall(r'\s','sd \nasrse')
print(m1) #[' ', '\n']
m2=re.findall(r'\S','\t\n asfsrer')
print(''.join(m2)) #asfsrer
(2)( )表示一个分组
m1=re.search(r'q(\d+)a','sdq2231asrse')
print(m1.group()) #q2231a
print(m1.group(1)) #2231
(3)标点符号都有特殊含义,如果要表示括号,就要在前面加 \
m2=re.search(r'\(.*\)','ad(1+2)sdz')
print(m2) #<_sre.SRE_Match object; span=(2, 7), match='(1+2)'>
(4) . 表示匹配除了换行以外的任意字符,如果想要匹配 . 需要使用 .
# . 表示匹配除了换行以外的任意字符,如果想要匹配 . 需要使用 \.
m1 = re.findall(r'.', 'asdt_s123242')
print(''.join(m1)) # asdt_s123242
m2 = re.findall(r'\.', 'asd.xvf')
print(m2) # ['.']
(5) [ ] 用来表示可选项范围 [x-y]表示x到y的区间,包含x和y
# [] 用来表示可选项范围 [x-y]表示x到y的区间,包含x和y
m1=re.search(r'a[0-6]d','wada2det')
print(m1) #<_sre.SRE_Match object; span=(3, 6), match='a2d'>
m2=re.search(r'a[0-6]+d','wada23605det')
print(m2) #<_sre.SRE_Match object; span=(3, 10), match='a23605d'>
m3=re.search(r'd[0-9a-dx]e','asdxer') #<=0 value <=9或者<=a value <=d 或者value=x
print(m3) #<_sre.SRE_Match object; span=(2, 5), match='dxe'>
(6)| 表示或者,与[ ]相似,区别在于[ ]里的值表示的是区间,而且是单个字符,| 就是可选值,可以出现多个值
# | 表示或者
# 区别:[]里的值表示的是区间,| 就是可选值
print(re.search(r'm(s|scd|a)x', 'asdmscdxasd')) #<_sre.SRE_Match object; span=(3, 8), match='mscdx'>
(7){ } 用来限定前面元素出现的次数
#{n} 表示前面元素出现n次
#{n,} 表示前面的元素出现n次以上( >=n )
#{,n} 表示前面的元素出现n次以下( <=n )
#{m,n} 表示前面的元素出现m到n次
print(re.findall(r'go{2}d', 'good')) #['good']
print(re.findall(r'go{1,}d','good')) #['good']
print(re.findall(r'go{,3}','god')) #['go']
print(re.findall(r'go{1,4}d','goood')) #['goood']
(8)* 表示前面的元素出现任意次数(0次及以上) 等价于 {0,}
print(re.search(r'go*d', 'gd')) #<_sre.SRE_Match object; span=(0, 4), match='gd'>
print(re.search(r'go*d', 'good')) #<_sre.SRE_Match object; span=(0, 4), match='good'>
(9)+ 表示前面的元素至少出现一次,相当于{1,}
# + 表示前面的元素至少出现一次,相当于{1,}
print(re.search(r'go+d', 'gd')) #None
print(re.search(r'go+d','good')) #<_sre.SRE_Match object; span=(0, 4), match='good'>
(10)? 两种用法:(1)规定前面的元素最多只能出现一次,相等于{,1};(2)将贪婪模式转换成非贪婪模式
import re
# ? 两种用法:
#(1)规定前面的元素最多只能出现一次,相等于{,1}
#(2)将贪婪模式转换成非贪婪模式
print(re.search(r'go?d','gd'))
print(re.search(r'go?d','god'))
print(re.search(r'go?d','good')) #None
(11) ^ 以指定内容开头 & 以指定内容结尾
# ^ 以指定内容开头 & 以指定内容结尾
print(re.search(r'^a.*d$','asdafgdzzz')) #None
print(re.search(r'^a.*d$','asdfd').group()) #asdfd
print(re.search(r'^a.*d$','asdde\navgd\nefd',re.M).group()) #avgd
2.特殊字母的含义
字母表示它本身,很多字母前面 \ 会有特殊含义
\ n 表示换行 \ t 表示一个制表符 \ s 空白字符
\ S 非空白字符 \ d 表示数字,等价于[ 0-9 ]
^ 除了表示以指定字符开头,还可以在[ ]里表示取反
\D 表示非数字,等价于[^0-9]
\w 表示数字、字母以及下划线_、中文等
\W 表示\w取反
import re
print(re.search(r'a\d+p', 'adsdza234pfgr').group()) #a234p
print(re.search(r'a[0-9]+p', 'adsdza234pfgr').group()) #a234p
# ^ 除了表示以指定字符开头,还可以在[]里表示取反
# \D 表示非数字,等价于[^0-9]
print(re.search(r'\D+', 'asd2345ax').group()) #asd
print(re.search(r'[^0-9]+', 'asd2345ax').group()) #asd
# \w 表示数字、字母以及下划线_、中文等
print(re.search(r'\w+', 'ase_213.*()/').group()) #ase_213
print(re.search(r'[0-9a-zA-Z_]+', 'ase_213.*()/').group()) #ase_213
print(re.findall(r'\w+','新年 快乐')) #['新年', '快乐']
# \W 表示\w取反
print(re.findall(r'\W+','新年 快乐!')) #[' ', '!']
3.正则替换
import re
#第一个参数是正则表达式
#第二个参数是新字符或者一个函数
#第三个参数是需要被替换的原来的新字符
print(re.sub(r'\d', 'x', 'asd324ko90az')) #asdxxxkoxxaz
print(re.sub(r'\d+', 'x', 'asd324ko90az')) #asdxkoxaz
#sub内部在调用test方法时,会把每一个匹配到的数据以re.Match的格式传参
def test(x):
y=int(x.group(0))
y*=2
return str(y)
print(re.sub(r'\d', test, 'asd324ko90az')) #asd648ko180az,test函数是自动调用的
4.贪婪模式和非贪婪模式
在python的正则表达式里,默认是贪婪模式,尽可能多地匹配
在贪婪模式后面加 ? 可以将贪婪模式转换成非贪婪模式
import re
# 在python的正则表达式里,默认是贪婪模式,尽可能多地匹配
print(re.search(r'm.*a', 'xcmsadskoahihakj').group()) # msadskoahiha
# 在贪婪模式后面加 ? 可以将贪婪模式转换成非贪婪模式
# 尽可能少的匹配
print(re.search(r'm.*?a', 'xcmsadskoahihakj').group()) # msa
print(re.search(r'aa(\d+)', 'aa2343kjh').group(0)) # aa2343
print(re.search(r'aa(\d+?)', 'aa2343kjh').group(0)) # aa2
print(re.search(r'aa(\d+)', 'aa2343kjh').group(1)) # 2343
print(re.search(r'aa(\d+?)', 'aa2343kjh').group(1)) # 2
print(re.search(r'aa(\d{2,}?)', 'aa2343kjh').group(1)) # 23
print(re.search(r'aa(\d+?)kj', 'aa2343kjh').group(1)) # 2343
print(re.search(r'aa(\d+?)kj', 'aa2343kjh').group(0)) # aa2343kj
print(re.search(r'aa(\d+?).*', 'aa2343kjh').group(1)) # 2
print(re.search(r'aa(\d??)(.*)', 'aa3243kiz').group(1)) # 为空
print(re.search(r'aa(\d??)(.*)', 'aa3243kiz').group(2)) # 3243kiz
5.ip地址
IP地址就是给每个连接在Internet上的主机分配的一个32bit地址。按照TCP/IP协议规定,IP地址用二进制来表示,每个IP地址长32bit,比特换算成字节,就是4个字节。包括主机地址和网络。点分十进制
ip地址要在同一个网段才能通信,ip地址要使用8个二进制(也就是255)
ip地址:192.168.31.100
子网掩码:255.255.255.0 按位与运算
网段:192.168.31.X ==> X表示主机位
1)如果子网掩码是255.255.255.0,这个网络里最多能放多少台主机?答:254台(256-2)
2)255.255.0.0呢?答:256*256-2
192.168.1.X
主机位全0就表示网络位,192.168.1.0
主机位全1就表示广播,192.168.1.255
(ip地址必须要结合子网掩码才能确认是否在同一个网段)
ip地址的分类:
IP地址根据网络号和主机号来分,分为A、B、C三类及特殊地址D、E。 全0和全1的都保留不用。
A类:(1.0.0.0-126.0.0.0)(默认子网掩码:255.0.0.0或 0xFF000000)第一个字节为网络号,后三个字节为主机号。该类IP地址的最前面为“0”,所以地址的网络号取值于1~126之间。一般用于大型网络。
B类:(128.0.0.0-191.255.0.0)(默认子网掩码:255.255.0.0或0xFFFF0000)前两个字节为网络号,后两个字节为主机号。该类IP地址的最前面为“10”,所以地址的网络号取值于128~191之间。一般用于中等规模网络。
C类:(192.0.0.0-223.255.255.0)(子网掩码:255.255.255.0或 0xFFFFFF00)前三个字节为网络号,最后一个字节为主机号。该类IP地址的最前面为“110”,所以地址的网络号取值于192~223之间。一般用于小型网络。
D类:是多播地址。该类IP地址的最前面为“1110”,所以地址的网络号取值于224~239之间。一般用于多路广播用户[1] 。
E类:是保留地址。该类IP地址的最前面为“1111”,所以地址的网络号取值于240~255之间。
在IP地址3种主要类型里,各保留了3个区域作为私有地址,其地址范围如下:
A类地址:10.0.0.0~10.255.255.255
B类地址:172.16.0.0~172.31.255.255
C类地址:192.168.0.0~192.168.255.255
6.网络通信
DHCP:用来分配ip
DNS:DNS是互联网的一项服务,它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。简单的讲DNS就是翻译官。就像把http://www.baidu.com翻译成220.181.111.188让机器理解。
DNS是用来做域名解析的,它会在你上网输入网址后,把它转换成IP,然后去访问对方服务器,没有它,你想上百度就要记住百度的IP,上163就要记住163的IP,有了DNS的处理,你只需要记住对应网站的域名–也就是网址就可以了。
7.端口和套接字
不同电脑之间使用端口区分程序,同一台电脑之间使用PID(进程id)区分程序。
什么是Socket?socket(套接字)是进程之间一种通信方式。简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口。
8.udp发送数据
udp协议:该协议称为用户数据报协议。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据报的方法。也就是说只管写,不管对方是否有人接收。
import socket
#不同电脑之间的通信需要使用socket
#socket:可以在不同电脑间通信,还可以在同一个电脑的不同程序间通信
#1.创建socket,并连接
#AF_INET:表示这个socket是进行网络连接
#SOCK_DGRAM:表示是一个 udp 连接
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#2.发送数据
#data:套传送的数据,是个二进制数据
#adress:发送给谁,参数是一个元组,元组里有两个元素
#第0个表示目标地址的ip,第1个表示程序的端口号
#给192.168.43.30这台主机的8000端口发送hello,world
#端口:0-65536 0-1024端口不要使用,系统一些重要的服务在使用
s.sendto('hello'.encode('utf-8'),('192.168.43.30',9090))
#3.关闭socket
s.close()
9.udp接受数据
import socket
#创建一个基于udp的网络socket连接
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#绑定端口号和ip地址
s.bind(('192.168.43.30',9090))
#recvfrom接受数据, recvfrom是一个阻塞的方法,等待
#接受到的数据是一个元组,里面有两个元素
#第0个元素是接受到的数据,第1个元素是发送方的ip地址和端口号
# content=s.recvfrom(1024)
# print(content) #(b'hello', ('192.168.43.30', 50926))
data,addr=s.recvfrom(1024)
print('从{}地址{}端口号接受到了信息,内容是:{}'.format(addr[0],addr[1],data.decode('utf-8')))
#从192.168.43.30地址60497端口号接受到了信息,内容是:你好
s.close()