一、re模块(Regular Expression 正则表达式)
功能:用来匹配字符串(动态、模糊的匹配),爬虫用的多。
import re
print ( re.doc ) ###查询re模块的功能信息
1、常用方法:
mathch():re.match(pattern, string[, flags]) 从头匹配
search():re.search(pattern, string[, flags]) 从整个文本搜索
findall():re.findall(pattern, string[, flags]) 在字符串中找到正则表达式所匹配的所有子串,并组成一个列表返回
split():re.split(pattern, string[, maxsplit=0, flags=0]) 可以将字符串匹配正则表达式的部分割开并返回一个列表
sub(): re.sub(pattern, repl, string[, count, flags]) 在字符串 string 中找到匹配正则表达式 pattern 的所有子串,用另一个字符串 repl 进行替换。
group():结果转化为内容
groupdict():结果转化为字典
compile :re.compile(pattern[, flags]) 作用:把正则表达式语法转化成正则表达式对象
finditer : re.finditer(pattern, string[, flags]) 和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并组成一个迭代器返回
2、常用正则表达式符号:
‘.’——默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括\n
‘^’——匹配字符开头
'KaTeX parse error: Expected 'EOF', got '\A' at position 147: …(...)' ——分组匹配 '\̲A̲' —— 只从字符开头匹配,…一样
‘\d’ ——匹配数字0-9
‘\D’ ——匹配非数字
‘\w’ ——匹配[A-Za-z0-9]
‘\W’ ——匹配非[A-Za-z0-9]
‘\s’ —— 匹配空白字符、\t、\n、\r
3、flags定义包括:
re.I:忽略大小写
re.L:表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
re.M:多行模式
re.S:’ . ’并且包括换行符在内的任意字符(注意:’ . ’不包括换行符)
re.U: 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
4、 注意:
1) 转义符号,有时候代表原有的意思,如‘\n’ ,这时候转义的话就需要‘\n’,不方便使用,因此使用 r ,r是raw(原始)的意思,即‘r\n’
二、socket 模块
——基础知识:
网络编程:即是对信息的发送和接收。主要工作:发送端:将信息以规定的协议组装成数据包;接收端:对收到的数据包解析,以提取所需要的信息。
Socket的本质:Socket是一个编程接口(API),TCP/IP协议需要向开发者提供做网络开发用的接口,这就是Socket接口,它是对TCP/IP协议网络通信的封装。
2.1 什么是套节字
Socket:两个在网络上的程序通过一个双向的通信连接,实现数据的交换,此连接的一端称为一个socket。
套接字包括两个:服务器套接字和客户机套接字
——套接字格式:(一个套接字就是一个socket模块中的socket类实例)
socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
第一个参数是地址族(默认是socket.AF_INET, 使用IPv4);
第二个参数是套接字类型(SOCK_STREAM,默认值,for TCP)或者数据报(SOCK_DGRAM,for UDP)套接字;
SOCK_RAW #原始套接字类型,可以创建这种套接字可以监听网卡上的所有数据帧,通常仅限于高级用户或管理员运行的程序使用。SOCK_RDM #是一种可靠的UDP形式,即保证交付数据报但不保证顺序。
第三个参数是使用的协议(默认是0)
——服务器套接字:
服务器套接字使用bind(绑定服务器主机ip,如果有多个网卡,就可以绑定多个ip)方法后,再调用listen方法去监听这个给定的地址。服务器套接字开始监听后,它会用accept方法来接收客户端的连接,这个方法会阻塞线程知道客户端连接,并返回一个格式为(client,address)的元组。
——客户机套接字:
客户端套接字使用connect方法连接服务器,在connect方法中使用的地址与bind方法中的地址相同(在服务器,能实现很多功能,比如使用socket.gethostname得到当前的主机名)。
2.2 套接字方法(send&recv)
套接字方法send和recv方法的状态有阻塞与非阻塞两种状态,默认状态是阻塞模式。
阻塞模式:s.setblocking(bool)——是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
在阻塞模式下send操作将会等待所有数据均被拷贝到发送缓冲区后才会返回,等待!
在阻塞模式下,recv会一直阻塞到接收缓冲区里有一个字节或一个完整的UDP数据报为止,然后再返回,等待!
非阻塞模式:
在非阻塞模式下send操作会立即返回,不等待!
在非阻塞模式下,recv会立即返回,不等待!
2.3 创建TCP服务器:
1)创建服务套接字:s = socket.socket()
2)绑定地址到套接字:s.bind()
3) 启动监听:s.listen()
4)接受客户连接:s.accept()
5)与客户端通信:recv() / send()
6)关闭套接字:s.close()
socket.bind(address) #将socket绑定到地址(常用于服务端),address地址的格式取决于地址族, 在AF_INET下,以元组(host,port)的形式表示地址。
socket.listen([backlog]) #启用服务器以接受连接(常用于服务端)。backlog >=0,指定系统在拒绝新连接之前将允许的未接受连接的数量。
socket.accept() #接收一个连接.该socket 必须要绑定一个地址和监听连接.返回值是一对(conn,address),(常用于服务端)。conn是socket对象,可以在该连接上发送和接收数据,address是连接另一端的地址。
socket.recv(bufsize[, flags]) #从socket接收数据,返回值是一个代表所收到的数据的字节对象。一次性接收的最大数据量由bufsize指定, 参数flags通常忽略。
socket.send(data[, flags]) #将数据发送到socket。python3中只能发送bytes类型的数据,因此发送时加个 “b”。
s.sendall(string[,flag]) 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
s.getpeername() 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
s.getsockname() 返回套接字自己的地址。通常是一个元组(ipaddr,port)
s.gethostname() 返回运行程序所在的计算机的主机名
s.gethostbyname(name) 尝试将给定的主机名解释为一个IP地址
s.fileno() 套接字的文件描述符
socket.connect(address) #连接到远程socket(常用于客户端) 。如果连接被信号中断,则该方法等待直到连接完成,或者如果信号处理程序没有引发异常并且套接字正在阻塞或者已经阻塞,则在超时时引入socket.timeout超时。对于非阻塞套接字,如果连接被信号中断(或由信号处理程序引发的异常),则该方法引发InterruptedError异常.
设置 socket选项 ,使用setsockopt():
setsockopt(level,optname,value)
optname参数:
SO_KEEPALIVE :可以使TCP通信的信息包保持连续性, 布尔型整数;
SO_REUSEADDR :当socket关闭后,本地端用于该socket的端口号立刻就可以被重用,布尔型整数。
S.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 这里value设置为1,表示将SO_REUSEADDR标记为TRUE,操作系统会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口,否则操作系统会保留几分钟该端口。
____________________________________________________________________________
2.4 创建TCP客户端:
1)创建客户端套接字:cs = socket.socket()
2)尝试连接服务器 :cs.connect()
3)与服务器通信:cs.send() /cs.recv()
4) 关闭客户端套接字:cs.close()
2.5 创建UDP服务器:
1)创建服务器套接字:s = socket.socket()
2) 绑定服务器套接字: s .bind()
3) 接收、发送数据:s.recvfrom()/ss.sendto()
4)关闭套接字 :s.close()
2.6 创建UDP客户端
1)创建客户端套接字:cs = socket.socket()
2)与服务器通信 :cs.sendto() /sc.recvfrom()
3) 关闭客户端套接字:cs.close()
案例:创建TCP服务端客户端通信,父进程用来连接,子进程用来通信。
import socket:
from time import strftime:
import os
class TcpTimeServer:
def __init__(self , host='', port = 123456)
self.addr = (host , port )
self.serv = socket.socket()
self.serv.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.serv.bind (self.addr )
self.serv.listen(1)
def chat(self, c_sock):
while True:
data = c_sock.recv(1024)
if data.strip() ==b'quit':
break
data = '[%s] %s' % (strftime('%H:%M:%S'),data.decode('utf8'))
c_sock.send(data.encode('utf8'))
c_sock.close()
def mainloop(self):
while True:
cli_sock,cli_addr = self.serv.accept()
pid = os.fork()
if pid :
cli_sock.close()
while True:
result = os.waitpid(-1,1)[0]
if result ==0:
else:
self.serv.close()
self.chat(cli_sock)
exit()
self.serv.close()
if __name__ == '__main__':
s = TcpTimeServer()
s.mainloop()
三、SocketServer模块
参考文件:https://www.cnblogs.com/saneri/p/5067769.html
SocketServer是标准库中一个高级别的模块。用于简化网络客户与服务器的实现。
编写一个SocketServer需要实现以下步骤:
1.>编写一个handler类,继承BaseRequestHandler,重写handle()方法
2.>针对是TCP还是UDP,生成一个server对象
3.>调用server对象的handle_request或者serve_forever方法