《Python爬虫开发与项目实战》总结 第一章
一.内容框架:
二.概念:
IO在计算机中指的是Input/Output,也就是输入输出。
Stream(流)是一种重要的概念,分为输入流(Input Stream)和输出流(Output Stream)。可以理解为一个水管,数据相当于水管中的水只能单向流动。
打开文件是读写文件最常见的IO操作,为了方便IO操作,文件读写之前需要打开文件,确定文件的读写模式。
文件模式是open函数中的mode参数,通过改变mode参数可以实现对文件的不同操作。
文件缓冲区是open函数中第三个参数buffering控制着文件的缓冲。
文件读取主要分为按字节读取和按行进行读取,经常用到的方法有read(),readlines(),close()。
文件写入唯一的区别是在调用open方法时,传入标识‘w’或者‘wb’标识写入文本文件或者写入二进制文件。
序列化是把内存中数据变成可存储和可传输的过程。
反序列化是把变量内容从序列化对象重新读取到内存中。
进程池可以提供指定数量的进程供用户调用,默认大小事CPU的核数。
线程同步是多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要多个线程进行同步。
全局解释器锁(GIL):解释执行Python代码时,会产生互斥锁来限制线程对共享资源的访问,知道解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL。
协程又称为微线程,纤程,是一种用户级的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。
分布式进程是将Process进程分布到多台机器上,充分利用多台机器的性能完成复杂的任务。
本地队列的网络化是将分布式进程进行封装的过程。
连接到指定服务器进程的通信端口进行通信,所以网络通信也可以看做两个进程间的通信。
TCP编程:网络编程一般包括两部分,服务端和客户端。TCP是一种面向连接的通信方式,主动发起连接的叫客户端,被动响应连接的叫服务端。
UDP编程:只需要知道对方的IP地址和端口号,就可以直接发数据包,但是不关心是否能到达目的端。
三.方法
1.文件操作
文件打开 |
open() |
文件写入 |
Write() |
文件读取 |
read() |
文件读取/行读取 |
readlines() |
文件关闭 |
close() |
1.2文件模式
值 |
功能描述 |
‘r’ |
读模式 |
‘w’ |
写模式 |
‘a’ |
追加模式 |
‘b’ |
二进制模式 |
‘+’ |
读/写模式 |
1.3文件缓冲区
参数 |
|
0 |
I/O操作是无缓冲的,直接写到硬盘上。 |
1 |
I/O操作是有缓冲的,数据先写到内存里,只有使用flush和close函数才会将数据更新到硬盘上。 |
大于1 |
大于1表示缓冲区的大小。 |
-1 |
代表使用默认缓冲区的大小。 |
1.4操作文件目录
os.getcwd() |
获得当前Ptython脚本工作的目录路径 |
os.Listdir() |
返回指定目录下的所有文件和目录名 |
os.remove(filepath) |
删除一个文件 |
os.removedirs() |
删除多个空目录 |
os.path.isfiles(filepath) |
检验给出的路径是否是一个文件 |
os.path.isdir(filepath) |
检验给出的路径是否是一个目录 |
os.path.isabs() |
判断是否是绝对路径 |
os.path.exists() |
检验路径是否真的存在 |
os.path.split() |
分离一个路径的目录名和文件名 |
os.path.splitext() |
分离扩展名 |
os.path.dirname(filepath) |
获取路径名 |
os.path.basename(filepath) |
获取文件名 |
os.getnv()或os.putnv() |
设置环境变量 |
os.linesep |
给出平台使用的终止符 |
os.name |
指示你正在使用的平台 |
os.rename() |
重命名文件或者目录 |
os.makedirs() |
创建多级目录 |
os.mkdir() |
创建多个目录 |
os.stat() |
获取文件属性 |
os.chmod() |
修改文件权限与时间戳 |
ps.path.getsize() |
获取文件大小 |
shutil.copytree() |
复制文件夹 |
shutil.copyfile() |
复制文件 |
shutil.move() |
移动文件 |
os.rmdir() |
删除目录 |
|
|
1.4序列化操作
cPickle和pickle两个模块来实现序列化,前者由C语言编写的,效率比后者高很多。
Pickle使用dumps方法将任意对象序列化成一个str。
1.5进程和线程
一种方法是使用os模块中的fork方法,另一种方法是使用multiprocessing模块。
getpid方法用于获取当前进程的ID,getppid方法用于获取父进程的ID。
start()方法启动进程,用join()方法实现进程间的同步。
pool()可以提供指定数量的进程供用户调用,默认大小是CPU的核数。
1.6进程间通信
Queue用在多个进程之间的数据传递。有两个方法,put和get可以进行Queue操作。
|
blocked |
timeout |
|
Put |
True |
正值 |
该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时会Queue.Full异常。 |
False |
NA |
Queue满,Queue.Full异常 |
|
Get |
True |
正值 |
那么在等待时间内没有取得任何元素,会抛出Queue.Empty异常。 |
False |
有值 |
则立即返回该值。 |
|
空 |
则立即抛出Queue.Empty异常。 |
Pipe的通信机制常用来在两个进程间进行通信,两个进程分别位于管道的两端。
Pipe |
Duplex |
|
False |
conn1只负责接收消息,conn2 只负责发送消息 |
|
True |
管道是全双工模式,也就是说conn1和conn2均可收发 |
1.7多线程
Threading模块一般通过两种方式创建多线程:第一种方式是把一个函数传入并创建Thread实例,然后调用start方法开始执行;第二种方式是直接从threading.Thread继承并创建线程类,然后重写_init_方法和run方法。
1.8线程同步
Thread对象的Lock和RLock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于每次只允许一个线程操作的数据,可以将其操作放到qcuqire和release方法之间。
1.9协程
Python通过yield和gevent库是更好的选择,提供了比较完善的协程支持。gevent中的spawn方法可以看做是用来形成协程,joinall方法就是添加这些协程任务,并且启动运行。
2.0分布式进程
Multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。
2.1网络编程
Socket类型
套接字格式为:socket(family,type[,protocal]),使用给定的地址族、套接字类型、协议编号创建套接字。
Socket.AF_UNIX |
只能够用于单一的Unix系统进程通信 |
Socket.AF_INET |
服务器之间网络通信 |
Socket.AF_INET6 |
IPv6 |
Socket.SOCK_STREAM |
流式socket,用于TCP |
Socket.SOCK_DGRAM |
数据报式socket,用于UDP |
Socket.SOCK_RAW |
原始套接字,普通的套接字无法处理ICMP/IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文,此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。 |
Socket.SOCK_SEQPACKET |
可靠的连续数据包服务 |
创建TCP socket |
S=socket.socket(socket.AF_INET,socket.SOCK_STREAM) |
创建UDP socket |
S=socket.socket(socket.AF_INET,socket.SOCK_DGREAM) |
Socket函数
Socket函数 |
描述 |
|
服务器socket函数 |
S.bind(address) |
将套接字绑定到地址,在AF_INET下,以元组(host,port)的形式表示地址 |
s.listen(backlog) |
开始监听TCP传入连接,backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 |
s.accept() |
接受TCP连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据address是连接客户端的地址。 |
|
客户端 |
S.connect(address) |
连接到address处的套接字。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误 |
s.connect_ex(address) |
功能与connect(address)相同,但是返回0,失败返回errno的值。 |
|
公共socket函数 |
s.recv(bufsize[,flag]) |
接受TCP套接字的数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。Flag提供有关消息的其他信息,通常可以忽略 |
s.send(string[,flag]) |
发送TCP数据。将string中的数据发送到连接的嵌套字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
s.sendall(string[,flag]) |
完整发送TCP数据。将string中的 数据发送到连接的套接字,但在返回之前会尝试发送所有的数据。但成功返回None,失败则抛出异常。 |
s.recvfrom(bufsize[,flag]) |
接受UDP套接字的数据。将string中的数据发送到连接的套接字。返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址 |
s.sendto(string[,flag],address) |
发送UDP数据。将数据发送到套接字,address是形式(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。 |
s.close() |
关闭套接字 |
s.getpeername() |
返回连接套接字的远程地址。返回值通常是元组(ipaddr,port) |
s.getsockname() |
返回套接字自己的地址。同常是一个元组(ipaddr,port) |
s.setsockopt(level,optname,value) |
设置给定套接字选项的值 |
s.getsockopt(level,optname,[.buflen]) |
返回套接字选项的值 |
s.settimeout(timeout) |
设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般超时期应该在刚创建套接字时设置,因为它们可能会用于连接操作。 |
s.setblocking(flag) |
如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,将引起socket.error异常。 |
|
|
2.2 TCP编程
服务端 |
客户端 |
1)创建Socket,绑定Socket到本地IP与端口 |
1)创建Socket,连接远端地址。 |
2)开始监听连接 |
2)连接后发送数据和接收数据 |
3)进入循环,不断接收客户端的连接请求 |
3)传输完毕后,关闭Socket |
4)接收传来的数据并发送给对方数据 |
|
5)传输完毕后,关闭Socket |
|
|
|
UDP编程
1)创建Socket,绑定的IP和端口 |
1)创建Socket |
2)直接发送数据和接收数据 |
|
3)关闭socket |
|