Python程序设计-从基础开发到数据分析(第2版)-微课版 课件 夏敏捷 第9-17章 网络编程和多线程- Python数据分析_第1页
Python程序设计-从基础开发到数据分析(第2版)-微课版 课件 夏敏捷 第9-17章 网络编程和多线程- Python数据分析_第2页
Python程序设计-从基础开发到数据分析(第2版)-微课版 课件 夏敏捷 第9-17章 网络编程和多线程- Python数据分析_第3页
Python程序设计-从基础开发到数据分析(第2版)-微课版 课件 夏敏捷 第9-17章 网络编程和多线程- Python数据分析_第4页
Python程序设计-从基础开发到数据分析(第2版)-微课版 课件 夏敏捷 第9-17章 网络编程和多线程- Python数据分析_第5页
已阅读5页,还剩217页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第9章网络编程和多线程9.1网络编程基础9.1.1互联网TCP/IP协议IP协议负责把数据从一台计算机通过网络发送到另一台计算机。数据被分割成一小块一小块,然后通过IP包发送出去。由于互联网链路复杂,两台计算机之间经常有多条线路,因此,路由器就负责决定如何把一个IP包转发出去。IP包的特点是按块发送,途径多个路由,但不保证能到达,也不保证顺序到达。IP地址实际上是一个32位整数(称为IPv4),以字符串表示的IP地址如实际上是把32位整数按8位分组后的数字表示,目的是便于阅读。9.1.2IP协议IP数据包TCP协议则是建立在IP协议之上的。TCP协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。TCP协议会通过握手建立连接,然后,对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发。许多常用的更高级的协议都是建立在TCP协议基础上的,比如用于浏览器的HTTP协议、发送邮件的SMTP协议等。UDP协议,同样是建立在IP协议之上,但是UDP协议面向无连接的通信协议,不保证数据包的顺利到达,不可靠传输。所以效率比TCP要高。9.1.3TCP和UDP协议面向连接TCP的时序图无连接UDP的时序图网络上两个计算机之间的数据通信,归根到底就是不同主机的进程交互,而每个主机的进程都对应着某个端口。也就是说,单独靠IP地址的无法完成通信的,必须要有IP和端口。9.1.4端口Socket是网络编程的一个抽象概念。Socket是套接字的英文名称,主要是用于网络通信编程。80年代初,美国政府的高级研究工程机构(ARPA)给加利福尼亚大学Berkeley分校提供了资金,让他们在UNIX操作系统下实现TCP/IP协议。在这个项目中,研究人员为TCP/IP网络通信开发了一个API(应用程序接口)。这个API称为Socket(套接字)。Socket是TCP/IP网络最为通用的API。任何网络通讯都是通过Socket来完成的。9.1.5Socket例如创建TCPSocket:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)创建UDPSocket:s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

日常生活中大多数连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。9.2.1TCP客户端编程【例9-1】访问新浪的TCP客户端程序。9.2TCP编程9.2.2TCP服务器端编程服务器端和客户端编程相比,服务器编程就要复杂一些。服务器端进程首先要绑定一个端口并监听来自其他客户端的连接。如果某个客户端连接过来了,服务器就与该客户端建立Socket连接,随后的通信就靠这个Socket连接了。【例9-2】编写一个简单的TCP服务器程序,它接收客户端连接,把客户端发过来的字符串加上Hello再发回去。图9-4服务器程序效果

图9-5客户端程序效果9.3UDP编程【例9-3】编写一个简单的UDP演示下棋程序。服务器端把UDP客户端发来的下棋x,y坐标信息显示出来,并把x,y坐标加1后(模拟服务器端下棋),再发给UDP客户端。9.4多线程编程线程是操作系统可以调度的最小执行单位,够执行并发处理。通常是将程序拆分成2个或多个并发运行的线程,即同时执行多个操作。例如,使用线程同时监视用户并发输入,并执行后台任务等。1.概念进程是操作系统中正在执行的应用程序的一个实例,操作系统把不同的进程(即不同程序)分离开来。每个进程至少包含一个线程,它从程序开始执行,直到退出程序,主线程结束,该进程也被从内存中卸载。主线程在运行过程中还可以创建新的线程,实现多线程的功能。9.4.1进程和线程9.4.1进程和线程2.多线程优点多线程类似于同时执行多个不同程序,多线程运行有如下优点:(1)使用线程可以把占据长时间的程序中的任务放到后台去处理。(2)用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度(3)程序的运行速度可能加快(4)在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。9.4.2创建线程Python中使用线程有两种方式:函数或者用类来创建线程对象。1.start_new_thread()函数创建线程调用_thread模块中的start_new_thread()函数来产生新线程。格式如下:_thread.start_new_thread(function,args[,kwargs])【例9-4】使用thread模块中的start_new_thread()函数来创建线程。2.Thread类创建线程threading线程模块封装了_thread模块,并提供更多功能,虽然可以使_thread模块中start_new_thread()函数创建线程,但建议使用threading模块。threading模块提供了Thread类来创建和处理线程,格式如下:线程对象=threading.Thread(target=线程函数,args=(参数列表),name=线程名,group=线程组)线程名和线程组都可以省略。【例9-5】使用threading.Thread类来创建线程例子。9.4.3线程同步如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。使用Threading的Lock(指令锁)和Rlock(可重入锁)对象可以实现简单的线程同步。【例9-7】使用指令锁实行多个线程同步。9.4.4定时器Timer定时器(Timer)是Thread的派生类,用于在指定时间后调用一个函数,具体方法如下:timer=threading.Timer(指定时间t,函数f)timer.start()执行timer.start()后,程序会在指定时间t后启动线程执行函数f。【例9-8】使用定时器Timer的例子。importthreadingimporttimedef

func():print(time.ctime()) #打印出当前时间print(time.ctime())timer=threading.Timer(5,func)timer.start()该程序可实现延迟5秒后调用func方法的功能。9.5网络编程案例——网络五子棋网络五子棋游戏简介建立基于UDP的Socket编程方法来制作网络五子棋程序。游戏时服务器端首先启动,当客户端连接后,服务器端可以走棋。用户根据提示信息,轮到自己下棋才可以在棋盘上落子,同时下方标签会显示对方的走棋信息,服务器端用户通过“退出游戏”按钮可以结束游戏网络五子棋游戏简介需要输入服务器IP地址(这里采用默认地址本机地址),如果正确且服务器启动则可以“连接”服务器。连接成功后客户端用户根据提示信息,轮到自己下棋才可以在棋盘上落子,同样可以通过“退出游戏”按钮结束游戏。通讯协议(1)move|下的棋子位置坐标(x,y)例如:“move|7,4”表示对方下子位置坐标(7,4)。(2)over|那方赢的信息例如:“over|黑方你赢了”表示黑方赢了。(3)exit|表示对方离开了,游戏结束。(4)join|连接服务器程序中根据接收的信息(当然都是字符串),通过字符串.split("|")获取消息类型(move,join,exit或者over),从中区分出“输赢信息over”,“下的棋子位置信息move”等,服务器端程序设计的步骤8.接收消息本程序关键部分就是接收消息data,从data字符串.split("|")中分割出消息类型(move,join,exit或者over)。如果是'join',是客户端连接服务器请求;如果是'exit',是对方客户端退出信息;如果是'move',是客户端走的位置信息;如果是'over',是对方客户端赢的信息。这里重点是处理对方走棋信息如“move|7,4”,通过字符串.split(",")分割出(x,y)坐标。服务器端程序设计的步骤9.发送消息发送消息代码很简单,仅仅调用socket的sendto函数,就可以把按协议写的字符串信息发出。defsendMessage(pos): #发送消息

globalsglobaladdrs.sendto(pos.encode(),addr)10.启动线程接收客户端的消息defstartNewThread():#启动一个新线程来接收客户器端的消息thread=threading.Thread(target=receiveMessage,args=())thread.setDaemon(True);thread.start();服务器端程序设计的步骤客户端程序设计的步骤步骤与服务器相似。接收消息data,从data字符串.split("|")中分割出消息类型(move,join,exit或者over)。功能同服务器端没有区别,仅仅没是'join'消息类型,因为客户端是连接服务器,而服务器不会连接客户端。所以少了一个'join'消息类型判断。9.5网络编程案例——Python在线聊天程序采用TCP连接用实现的一个在线聊天程序,主要功能是实现客户端与服务器端的双向通信。运行效果如图9-8所示。在线聊天服务器端在线聊天的客户端在线聊天的客户端第10章函数式编程什么是函数式编程函数式编程——FunctionalProgramming,是一种编程的基本风格,也就是构建程序结构的方式。函数式编程虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算,也就是可以使用表达式编程。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数。Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。10.1高阶函数1.高阶函数概念高阶函数它是可以将其他函数作为参数或返回结果的函数。例如,定义一个简单的高阶函数:defadd(x,y,f):returnf(x)+f(y)

add(-5,9,abs)#abs(-5)+abs(9)add(65,66,chr)#AB10.1高阶函数1.返回函数高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。def

calc_sum(*args):ax=0forninargs:ax=ax+nreturnaxdef

lazy_sum(*args):

defsum():ax=0forninargs:ax=ax+nreturnax

returnsum>>>f=lazy_sum(1,3,5,7,9)>>>f<functionlazy_sum.<locals>.sumat0x101c6ed90>>>>f()25当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为闭包(Closure)闭包y=ax+b编写函数计算y的值。

def

line_conf(a,b):

defline(x):returna*x+breturnline>>>line_one=line_conf(3,4)>>>line_two=line_conf(4,6)>>>line_one(5)#结果19>>>line_two(5)#结果26上述代码中line_conf是外部函数,a、b是它的参数。line(x)是内部函数,x是它的参数。在line(x)的内部通过外部函数的a、b确定闭包最终形式。闭包具有提过代码可复用性的作用。10.2Python函数式编程常用的函数1.map()函数map()是Python内置的高阶函数,有2个参数,一个是函数f(),一个是列表list,并通过把函数f()依次作用在list的每个元素上,得到一个新的list作为map()函数的返回结果。deff(x):returnx*xlist1=map(f,[1,2,3,4,5,6,7,8,9])print(list(list1))[1,4,9,10,25,36,49,64,81]10.2Python函数式编程常用的函数1.map()函数map()不仅仅可以处理只包含数值的list,事实上它可以处理包含任意类型的list,只要传入的函数f可以处理这种数据类型。list1=[2,4,6,8,10]list2=map(lambdax:x**2,list1)foreinlist2:print(e,end=",")#结果是:4,16,36,64,100,list1=["china","japan","hello"]list2=map(lambdax:x.title(),list1)#title()首字母大小foreinlist2:print(e,end=",")#结果是:China,Japan,Hello,10.2Python函数式编程常用的函数2.reduce()函数reduce()函数接收的参数和map()类似,一个函数f(),一个列表list,但reduce()传入的函数f()必须接收两个参数。reduce()对列表list的每个元素反复调用函数f(),并返回最终结果值。fromfunctoolsimportreducedeff(x,y):returnx+yreduce()还可以接收第3个可选参数,作为计算的初始值。reduce(f,[1,3,5,7,9],100)结果将变为125。reduce(f,[1,3,5,7,9])结果为25。10.2Python函数式编程常用的函数3.filter()函数filter()函数接收一个函数f()和一个list,这个函数f()的作用是对每个元素进行判断,返回True或False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。def

is_odd(x):returnx%2==1利用filter()过滤掉偶数:filter(is_odd,[1,4,6,7,9,12,17])#结果[1,7,9,17]10.2Python函数式编程常用的函数4.zip()函数zip()函数以一系列列表作为参数,将列表中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。a=[1,2,3]b=[4,5,6]zipped=zip(a,b)forelementinzipped:print(element)(1,4)(2,5)(3,6)10.2Python函数式编程常用的函数5.sorted()函数Python内置的sorted()函数可对list进行排序:>>>sorted([36,5,12,9,21])#默认升序,所以结果是[5,9,12,21,36]但sorted()也是一个高阶函数,Python3.7中它的格式如下:sorted(list,key=None,reverse=False)key指定的函数将作用于list的每个元素上,并根据key函数返回的结果排序。sorted([36,5,-12,9,-21],key=abs)#结果是[5,9,-12,-21,36]students=[('john','A',15),('jane','B',12),('dave','B',10)]sorted(students,key=lambdas:s[2])#按照年龄来排序10.2Python函数式编程常用的函数5.sorted()函数Python内置的sorted()函数可对list进行排序:>>>sorted([36,5,12,9,21])#默认升序,所以结果是[5,9,12,21,36]但sorted()也是一个高阶函数,Python3.7中它的格式如下:sorted(list,key=None,reverse=False)key指定的函数将作用于list的每个元素上,并根据key函数返回的结果排序。sorted([36,5,-12,9,-21],key=abs)#结果是[5,9,-12,-21,36]students=[('john','A',15),('jane','B',12),('dave','B',10)]sorted(students,key=lambdas:s[2])#按照年龄来排序10.3迭代器迭代器是访问集合内元素的一种方式。迭代器对象从序列(列表、元组、字典、集合)的第一个元素开始访问,直到所有的元素都被访问一遍后结束。迭代器不能回退,只能往前进行迭代。使用内建函数iter(iterable)可以获取序列的迭代器对象,方法如下:

迭代器对象=iter(序列对象)使用next()函数可以获取迭代器的下一个元素,如下:next(迭代器对象)list=['china','Japan',333]it=iter(list)#获取迭代器对象print(next(it))print(next(it))print(next(it))chinaJapan33310.4普通编程方式与函数式编程的对比【例10-2】以普通编程方式计算列表元素中正数之和。list=[2,-6,11,-7,8,15,-14,-1,10,-13,18]sum=0foriinrange(len(list)):iflist[i]>0:sum+=list[i]print(sum)fromfunctoolsimportreducelist=[2,-6,11,-7,8,15,-14,-1,10,-13,18]sum=filter(lambdax:x>0,list)s=reduce(lambdax,y:x+y,sum)print(s)通过对比,函数式编程具有如下特点:(1)代码更简单。数据,操作和返回值都放在一起。(2)没有循环体,几乎没有临时变量,也就不用分析程序的流程和数据变化过程了。(3)代码用来实现做什么,而不是怎么去做。第11章Python文本处理11.1字符串基本处理11.2正则表达式11.3Python中文分词11.1字符串基本处理1.按照某种格式生产字符串str.format(*args,**kwargs)。例如:'1+2={0}'.format(1+2)2.字符串连接和重复字符串可以用+号连接起来,用*号重复:>>>word='Help'+'A'>>>word'HelpA'>>>'<'+word*5+'>'#重复5次'<HelpAHelpAHelpAHelpAHelpA>'11.1字符串基本处理3.字符串索引和切片字符串可以象在C语言中那样用下标索引,字符串的第一个字符下标为0。Python没有单独的字符数据类型,一个字符就是长度为一的字符串。可以用切片(slice)来截取其中的任意部分形成新子串,切片即用冒号隔开的两个下标。>>>word='HelpA'>>>word[4]#下标索引为4的字符,即'A'>>>word[0:2]#'He'>>>word[2:4]'lp'11.1字符串基本处理4.判断是否是子串在python中,in判断某一字符串是否在另一个字符串中:'nice'in'niceday'#True5.替换字符串中的部分内容替换有2中方法,一种是使用字符串str对象的方法replace(),另一种是使用re模块中sub()的。6.拆分字符串主要使用str对象的split()方法。split(str="",num=string.count(str))7.合并字符串拆分功能相反,我们可以将列表合并成一个字符串。这个功能使用str对象的join()方法。11.1字符串基本处理8.检测字符串中是否包含某子字符串find()方法检测字符串中是否包含某子字符串,find()方法语法:str.find(str,beg=0,end=len(string))参数str指定检索的字符串,beg开始索引默认为0,end结束索引默认为字符字符串的长度。如果指定beg(开始)和end(结束)范围,则检查是否包含在指定范围内,如果包含子字符串则返回开始的索引值,否则返回-1。11.2正则表达式正则表达式是一种用来匹配字符串文本的强有力的武器。它是用一种描述性的语言来给字符串定义一个规则。凡是符合规则的字符串,就认为它“匹配”了,否则,该字符串就是不合法的。11.2.1

正则表达式语法正则表达式并不是Python中特有的功能,它是一种通用的方法。要使用它必须会用正则表达式来描述文本规则。正则表达式使用特殊的语法来表示,表11-1列出了正则表达式语法。11.2正则表达式正则表达式使用特殊的语法来表示,表11-1列出了正则表达式语法。11.2正则表达式正则表达式使用特殊的语法来表示,表11-1列出了正则表达式语法。下面列出正则表达式的应用实例。11.2正则表达式1.匹配单个字符从正则表达式语法中可见用\d可以匹配一个数字,\w可以匹配一个字母或数字,.可以匹配任意单个字符,所以:模式'00\d'可以匹配'007',但无法匹配'00A';模式'\d\d\d'可以匹配'010';模式'\w\w\d'可以匹配'py3';模式'py.'可以匹配'pyc'、'pyo'、'py!'等等。11.2正则表达式2.匹配变长的字符串---量词要匹配变长的字符串,在正则表达式模式字符串中,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符。来看一个复杂的表示电话号码例子:电话号码例子一个复杂的表示电话号码例子:\d{3}\s+\d{3,8}我们来从左到右解读一下:\d{3}表示匹配3个数字,例如'010';\s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格;\d{3,8}表示3-8个数字,例如'67665230'。综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。'01067665230''037167665230’修改为\d{3,4}\s+\d{3,8}11.2正则表达式3.[]表示范围如果要做更精确地匹配,可以用[]表示范围,比如:[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线;[0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'等等;[a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;[a-zA-Z\_][0-9a-zA-Z\_]{0,19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。A|B可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'。[^...]形式表示排除的字符,例如[^abc]匹配除了a,b,c之外的字符。[^0-9]匹配除了数字外的字符。11.2正则表达式3.[]表示范围如果要做更精确地匹配,可以用[]表示范围,比如:[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线;[0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'等等;[a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;[a-zA-Z\_][0-9a-zA-Z\_]{0,19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。A|B可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'。[^...]形式表示排除的字符,例如[^abc]匹配除了a,b,c之外的字符。[^0-9]匹配除了数字外的字符。11.2正则表达式4.匹配字符串的开头和结束^表示字符串的开头,例如^\d表示字符串必须以数字开头。$表示字符串的结束,例如\d$表示必须以数字结束。例如:^\d{3,4}\-\d{3,8}$表示带区号的电话号码。'037167665230'aaa037167665230'\d{3,4}\s+\d{3,8}11.2正则表达式4.匹配字符串的开头和结束^表示字符串的开头,例如^\d表示字符串必须以数字开头。$表示字符串的结束,例如\d$表示必须以数字结束。例如:^\d{3,4}\-\d{3,8}$表示带区号的电话号码。'037167665230'aaa037167665230'\d{3,4}\s+\d{3,8}11.2正则表达式5.数量词的贪婪模式与非贪婪模式正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的,总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。分组注意,前面讲到的符号仅仅能让正则表达式“表示”一串字符串。但是如果要从一段字符串中“提取”出一部分内容这时就要用小括号()。例如一个字符串“我的密码是:123abc你帮我记住。”从中可见密码左边是英文冒号,右边是“你”。

当构造一个正则表达式——

:.*?你,得到结果是

:123abc你然而英文冒号和“你”并不是密码,如果只想要“123abc”,此时使用小括号()提取,即构造一个正则表达式——:(.*?)你,得到结果是

123abc11.2.2re模块Python提供re模块,包含所有正则表达式的功能。Python中pile函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象,该正则表达式对象拥有一系列方法用于正则表达式匹配和替换。同时re模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。本节主要介绍Python中常用的正则表达式处理函数。1.match()方法2.分组3.切分字符串4.search()和findall()方法5.compile函数→生成一个正则表达式对象11.2.2re模块1.match()方法re.match()格式为:re.match(pattern,string,flags)re.match()方法从字符串起始位置判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None。>>>importre#导入re正则表达式模块>>>re.match(r'^\d{3}\-\d{3,8}$','010-12345')#返回一个Match对象<_sre.SRE_Matchobject;span=(0,9),match='010-12345'>>>>re.match(r'^\d{3}\-\d{3,8}$','01012345')#'01012345'不匹配规则,返回NoneMatch对象是一次匹配的结果。(1)Match对象的属性string:匹配时使用的文本。re:匹配时使用的Pattern对象。pos:文本中正则表达式开始搜索的位置。endpos:文本中正则表达式结束搜索的位置。lastindex:最后一个被捕获的分组在文本中的位置。lastgroup:最后一个被捕获的分组的别名。(2)Match对象的方法group([group1,…]):返回一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。参数group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时返回group(0)。>>>importre>>>re.match(r'^\d{3}\-\d{3,8}$','010-12345')<re.Matchobject;span=(0,9),match='010-12345'>>>>re.match(r'\d{3}\-\d{3,8}','010-12345')<re.Matchobject;span=(0,9),match='010-12345'>>>>re.match(r'\d{3}\-\d{3,8}','010-123456789012')<re.Matchobject;span=(0,12),match=>>>>a=re.match(r'\d{3}\-\d{3,8}','010-123456789012')>>>a<re.Matchobject;span=(0,12),match=>>>>a.string#'010-123456789012'>>>a.re#pile('\\d{3}\\-\\d{3,8}')>>>a.pos#0>>>a.group(0)>>>a=re.match(r'\d{3}\-\d{3,8}','a010-123456789012')>>>aisNoneTrue11.2.2re模块2.分组正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:>>>m=re.match(r'(\d{3})-(\d{3,8})','010-123456789012')>>>m.group(0)#>>>m.group(1)#'010'>>>m.group(2)#'12345678'注意group(0)是整个匹配的子串,group(1)、group(2)……表示第1、2、……个子串(分组)。11.2.2re模块3.切分字符串re.split(r'\s+',text)将字符串按空格分割成一个单词列表。>>>re.split(r'\s+','abbbbbc')#用正则表达式['ab','bbbb','c']11.2.2re模块4.search()和findall()方法re.match()总是从字符串“开头”去匹配,并返回匹配的字符串的Match对象。所以当用re.match()去匹配非“开头”部分的字符串时,会返回NONE。str1='HelloWorld!'print(re.match(r'World',str1))#结果为:NONE如果想在字符串内任意位置去匹配请用re.search()或re.findall()。re.search()将对整个字符串进行搜索,并返回第一个匹配的字符串的Match对象。str1='HelloWorld!'print(re.search(r'World',str1))输出结果:<_sre.SRE_Matchobject;span=(6,11),match='World'>re.findall()函数将返回所有匹配的字符串的一个字符串列表。这在爬虫程序里经常使用。re.findall()函数将返回所有匹配的字符串的一个字符串列表。这在爬虫程序里经常使用。str1='Hi,IamShirleyHilton.Iamhiswife.'>>>print(re.search(r'hi',str1))输出结果将是:<_sre.SRE_Matchobject;span=(10,12),match='hi'>第一个匹配的>>>re.findall(r'hi',str1)输出结果将是:

['hi','hi']11.2.2re模块5.re.sub()方法re.sub用于替换字符串中的匹配项。格式为:re.sub(pattern,repl,string,count=0,flags=0)第一个参数pattern是正则表达式,第二个参数repl表示替换的字符串,第三个参数string要要被查找替换的原始字符串;count参数是模式匹配后替换的最大次数,默认0表示替换所有的匹配。例如:url='http://36:9011/index.html'#原始字符串pattern='http://(.*?):9011/'out=re.sub(pattern,':8089/',url)#替换网址为:8089/index.htmlprint(out)11.2.2re模块6.compile函数compile函数用于编译正则表达式,生成一个正则表达式(Pattern)对象,该对象拥有一系列方法【match()和search()、findall()】用于正则表达式匹配和替换。语法格式为:pile(pattern[,flags])pattern:一个字符串形式的正则表达式。flags:可选,表示匹配模式,比如忽略大小写,多行模式等,importrepattern=pile(r'\d+')#生成正则表达式(Pattern)对象用于匹配至少一个数字m=pattern.match('12twothree34four')#查找头部,没有匹配,结果是None<re.Matchobject;span=(0,2),match='12'>等价于m=re.match('\d+','12twothree34four')正则表达式转换成对象importrekey=r'<ahref="">中工1</a>and<ahref="">中工2</a>'p1=r'<a.*?href="(http.*?)".*?>(.*?)</a>'#正则表达式pattern1=pile(p1)#把正则表达式转换成对象来调用findall()和match()urls=pattern1.findall(key)#超链接网址的列表#urls=re.findall(p1,key)forurlinurls:print(url)11.3Python中文分词

中文分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。中文分词是网页分析索引的基础,因此搜索引擎对于分词的准确率和速率都提出了很高的要求。

“结巴”中文分词是一个支持中文分词,高准确率、高效率的Python中文分词组件。支持繁体分词和自定义词典,“结巴”中文分词支持三种分词模式:1)精确模式:试图将句子最精确地切开,适合文本分析;2)全模式:把句子中所有的可以成词的词语都扫描出来,速度非常快,但是不能解决歧义;3)搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。11.3Python中文分词

中文分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。中文分词是网页分析索引的基础,因此搜索引擎对于分词的准确率和速率都提出了很高的要求。

“结巴”中文分词是一个支持中文分词,支持繁体分词和自定义词典,“结巴”中文分词支持三种分词模式:1)精确模式:试图将句子最精确地切开,适合文本分析;2)全模式:把句子中所有的可以成词的词语都扫描出来,速度非常快,但是不能解决歧义;3)搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。我来到北京清华大学DefaultMode:我/来到/北京/清华大学FullMode:我/来到/北京/清华/清华大学/华大/大学搜索引擎模式:我/来到/北京/清华/华大/大学/清华大学11.3.1安装和使用jieba命令行状态下输入pipinstalljieba出现如下提示则安装成功。Installingcollectedpackages:jiebaRunningsetup.pyinstallforjieba...doneSuccessfullyinstalledjieba-0.38组件提供jieba.cut()方法用于分词,cut()方法接受两个输入参数:(1)第一个参数为需要分词的字符串(2)cut_all参数用来控制分词模式importjiebaseg_list=jieba.cut("我来到北京清华大学",cut_all=True)#全模式print("FullMode:",'/'.join(seg_list))seg_list=jieba.cut("我来到北京清华大学")#默认是精确模式,或者cut_all=falseprint(type(seg_list))#<class'generator'>print("DefaultMode:",'/'.join(seg_list))seg_list=jieba.cut_for_search("我来到北京清华大学")#搜索引擎模式print("搜索引擎模式:",'/'.join(seg_list))seg_list=jieba.cut("我来到北京清华大学")forwordinseg_list:print(word,end='')11.3.2jieba添加自定义词典基本用法:jieba.load_userdict(file_name)#file_name为自定义词典的路径词典格式是一个词占一行;每一行分三部分,一部分为词语,另一部分为词频,最后为词性例如如下自定义词典dict.txt:乾清宫5ns黄琉璃瓦4云计算5李小福2nr八一双鹿3nz凯特琳2nz下面是导入自定义词典后再分词。importjiebajieba.load_userdict("dict.txt")#导入自定义词典

text="故宫的著名景点包括乾清宫、太和殿和黄琉璃瓦等"seg_list=jieba.cut(text,cut_all=False)#精确模式

print("[精确模式]:","/".join(seg_list))TF/IDFTF/IDF

是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。第12章

基于Pygame游戏设计12.1Pygame基础知识12.1.1安装Pygame库在开发Pygame程序之前,你需要安装Pygame库。可以通过Pygame的官方网站/download.shtml下载源文件。安装指导也可以在相应页面找到。一旦安装了Pygame,就可以在IDLE交互模式中输入以下语句检验是否安装成功:>>>importpygame>>>print(pygame.ver)1.9.2a01.9.2是Pygame的最新版本,读者也可以找一找其他更新的版本。12.1Pygame基础知识12.1.2Pygame的模块Pygame有大量可以被独立使用的模块。对于计算机的常用设备,都有对应的模块来进行控制,另外还有其他一些模块,例如pygame.display是显示模块;pygame.keyboard是键盘模块;pygame.mouse是鼠标模块,如表12-1所示。12.2Pygame的使用主要讲解用Pygame开发游戏的逻辑、鼠标事件的处理、键盘事件的处理、字体的使用和声音的播放等基础知识。最后以一个“移动的坦克”例子来体现这些基础知识的应用。12.2.1Pygame开发游戏的主要流程12.2.2Pygame的图像图形绘制Pygame使用surface对象来加载绘制图像。对于Pygame加载图片就是pygame.image.load(),给它一个文件名然后就返回一个surface对象。尽管读入的图像格式各不相同,surface对象隐藏了这些不同。你可以对一个surface对象进行涂画、变形、复制等各种操作。事实上,游戏屏幕也只是一个surface,pygame.display.set_mode()就返回了一个屏幕surface对象。对于任何一个Surface对象,可以用get_width(),get_height()和gei_size()函数来获得它的尺寸。get_rect()获取它的区域形状。【例12-2】使用pygame开发一个显示坦克自由移动的游戏窗口。12.2.3Pygame的键盘和鼠标事件12.2.3Pygame的键盘和鼠标事件的处理所谓事件(event)就是程序上发生的事。例如用户敲击键盘上某一个键或是单击、移动鼠标。而对于这些事件,游戏程序需要做出反应。上一个例12-2程序中,程序会一直运行下去直到你关闭窗口而产生了一个QUIT事件,Pygame会接收用户的各种操作(比如按键盘,移动鼠标等)产生事件。事件随时可能发生,而且量也可能会很大,Pygame的做法是把一系列的事件存放一个队列里,逐个的处理。例12-2程序中,使用了pygame.event.get()来处理所有的事件,如果我们使用pygame.event.wait(),Pygame就会等到发生一个事件才继续下去,一般游戏中不太实用,因为游戏往往是需要动态运作的。Pygame常用事件见表12-4所示。12.2.3Pygame的键盘和鼠标事件1.Pygame的键盘事件的处理用pygame.event.get()获取所有的事件,当event.type==KEYDOWN的时候,这时是键盘事件,再判断按键event.key的种类(即K_a,K_b,K_LEFT这种形式)。也可以pygame.key.get_pressed()来获得所有按下的键值,它会返回一个元组。这个元组的索引就是键值,对应的就是是否按下。pressed_keys=pygame.key.get_pressed()ifpressed_keys[K_SPACE]:#空格键被按下fire()#发射子弹【例12-3】使用pygame开发一个用户控制坦克移动的游戏。在例12-2基础上增加通过方向键控制坦克运动,并为游戏增加了背景图片。程序运行效果如图图12-4所示。方向键控制坦克运动的游戏窗口12.2.3Pygame的键盘和鼠标事件2.Pygame的鼠标事件的处理◾pygame.mouse.get_pressed——返回按键按下情况,返回的是一元组,分别为(左键,中键,右键),如按下则为True。◾pygame.mouse.get_rel——返回相对偏移量,(x方向偏移量,y方向偏移量)的一元组。◾pygame.mouse.get_pos——返回当前鼠标位置(x,y)。例如:x,y=pygame.mouse.get_pos()#获得鼠标位置◾pygame.mouse.set_pos——设置鼠标位置。◾pygame.mouse.set_visible——设置鼠标光标是否可见。◾pygame.mouse.get_focused——如果鼠标在pygame窗口内有效,返回True。◾pygame.mouse.set_cursor——设置鼠标的默认光标式样。◾pyGame.mouse.get_cursor——返回鼠标的光标式样。【例12-4】演示鼠标事件处理的程序。程序运行效果如图12-5所示。演示鼠标事件处理的程序运行效果12.2.4Pygame的字体使用pygame可以直接调用系统字体,也可以调用TTF字体。为了使用字体,首先应该创建一个Font对象,对于系统自带的字体,应该这样调用:font1=pygame.font.SysFont('arial',16)第一个参数是字体名,第二个参数是字号。正常情况下系统里都会有arial字体,如果没有会使用默认字体,默认字体和使用系统有关。12.2.5Pygame的声音播放1.Sound对象在初始化声音设备后,就可以读取一个音乐文件到一个Sound对象中了。pygame.mixer.Sound()接受一个文件名,或者也可以使一个文件对象,不过这个文件必须是WAV或者OGG。hello_sound=Pygame.mixer.Sound("hello.ogg")#建立Sound对象hello_sound.play()#声音播放一次12.2.5Pygame的声音播放2.music对象pygame中另外提供了一个pygame.mixer.music类来控制背景音乐的播放。pygame.mixer.music用来播放MP3和OGG音乐文件,不过MP3并不是所有的系统都支持(Linux默认就不支持MP3播放)。我们使用pygame.mixer.music.load()来加载一个文件,然后使用pygame.mixer.music.play()来播放,不放的时候就用stop()方法来停止,当然也有类似录影机上的pause()和unpause()方法。

#加载背景音乐

pygame.mixer.music.load("hello.mp3")pygame.mixer.music.set_volume(music_volume/100.0)#循环播放,从音乐第30秒开始

pygame.mixer.music.play(-1,30.0)在游戏退出事件中加入停止音乐播放代码:

#停止音乐播放

pygame.mixer.music.stop()12.2.6Pygame的精灵使用pygame.sprite.Sprite是Pygame里面用来实现精灵的一个类,使用时并不需要对它实例化,只需要继承它,然后按需写出自己的类,因此非常简单实用。1.精灵所有精灵在建立时都是从pygame.sprite.Sprite中继承的。建立精灵要设计自己的精灵类。【例12-5】建立Tank精灵。12.3基于Pygame设计贪吃蛇游戏12.4基于Pygame设计飞机大战游戏相信玩过雷电打飞机的朋友都熟悉,这里将游戏做了简化。飞机的速度固定,子弹的速度固定,基本操作是通过键盘移动玩家飞机,敌机随机从屏幕上方出现并匀速落到下方,子弹从玩家飞机发出,碰到目标飞机会击毁,如果目标飞机碰到玩家飞机,则GameOver并显示分数。12.4基于Pygame设计飞机大战游戏12.4.1游戏角色本游戏中所需的角色包括玩家飞机、敌机及子弹。用户可以通过键盘移动玩家飞机在屏幕上的位置来打击不同位置的敌机。因此设计以下玩家类Player,敌机类Enemy和子弹类Bullet三个类对应三种游戏角色。对于玩家类Player,需要的操作有射击和移动两种,移动又分为上下左右4种情况。对于敌机类Enemy,则比较简单,只需要移动即可,从屏幕上方出现并移动到屏幕下方。对于子弹类Bullet,与飞机相同,仅需要以一定速度移动即可。玩家、子弹、敌机都可以写成一个类,继承pygame的sprite类,实现一些动画效果,以及检测碰撞。12.4.2游戏界面显示游戏画面中使用了一些飞机、子弹图像,这里使用shoot.png文件(图12-8)存储所有飞机、子弹、爆炸等图像,在程序中需要分割出来显示。当然可以图像处理软件分解成一个个独立文件,这样处理后开发程序简单些。12.4基于Pygame设计飞机大战游戏12.4.3游戏逻辑实现下面进入游戏主循环。在主循环中,我们进行了以下工作:(1)处理键盘输入的事件(上下左右按键操作),增加游戏操作交互(玩家飞机的上下左右移动)。(2)处理子弹这里控制发射子弹频率,并发射子弹。移动已发射过的子弹,若超出窗口范围则删除。(3)敌机处理敌机需要随机在界面上方随机产生,并以一定速度向下移动。详细步骤:1.生成敌机,需要控制生成频率。2.移动敌机。3.敌机与玩家飞机碰撞效果处理。4.移动出屏幕后删除敌机。5.敌机被子弹击中效果处理。(4)得分显示在游戏界面固定位置显示消灭了多少目标敌机。12.4基于Pygame设计飞机大战游戏第13章Python爬取网页信息13.1相关HTTP协议知识HTTP工作流程13.1相关HTTP协议知识而我们现在的一般使用的HTTP1.1协议解析网页过程是不同的,在1.1版本中同一个连接可以包含多个请求和对应响应。但是其原理是不变的。如图:网络爬虫,也叫网络蜘蛛(WebSpider),如果把互联网比喻成一个蜘蛛网,Spider就是一只在网上爬来爬去的蜘蛛。是搜索引擎抓取系统的重要组成部分。爬虫的主要目的是将互联网的网页下载到本地形成一个互联网内容的镜像备份。URL就是统一资源定位符(UniformResourceLocator),它的一般格式如下:protocol://hostname[:port]/path/[;parameters][?query]#fragmentURL的格式由三部分组成:(1)protocol:第一部分就是协议,例如百度使用的就是https协议;(2)hostname[:port]:第二部分就是主机名(还有端口号为可选参数),一般网站默认的端口号为80,例如百度的主机名就是,这个就是服务器的地址;(3)path:第三部分就是主机资源的具体地址,如目录和文件名等。网络爬虫应用一般分为两个步骤:①通过网络链接获取网页内容;②对获得的网页内容进行处理。网络爬虫urllib是Python标准库中最为常用的Python网页访问的模块,我们可以使用urlib这个库抓取网页。13.2urllib库urllib是一个URL处理包,这个包中集合了一些处理URL的模块,如下:(1)urllib.request模块是用来打开和读取URL的;(2)urllib.error模块包含一些有urllib.request产生的错误,可以使用try进行捕捉处理;(3)urllib.parse模块包含了一些解析URL的方法;(4)urllib.robotparser模块用来解析robots.txt文本文件。它提供了一个单独的RobotFileParser类,通过该类提供的can_fetch()方法测试爬虫是否可以下载一个页面。1.获取网页信息urllib.request和urllib.parse模块urlopen()函数格式:urllib.urlopen(url[,data[,proxies]])urlopen返回的response对象提供了如下方法:read(),readline(),readlines(),fileno(),close():这些方法的使用方式与文件对象完全一样;info():返回一个httplib.HTTPMessage对象,表示远程服务器返回的头信息;getcode():返回Http状态码。如果是http请求,200表示请求成功完成;404表示网址未找到;geturl():返回请求的url;1.获取网页信息urllib.request和urllib.parse模块

urlopen()函数格式:urllib.urlopen(url[,data[,proxies]])

url参数不仅可以是一个字符串,例如:。url也可以是一个Request对象

req=request.Request("/")#Request对象

response=request.urlopen(req)html=response.read()html=html.decode("utf-8")print(html)注意,如果要把对应文件下载到本地,可以使用urlretrieve()函数。fromurllibimportrequestrequest.urlretrieve("/_mediafile/index/2017/06/24/1qjdyc7vq5.jpg","aaa.jpg")2.获取服务器响应信息urllib.request和urllib.parse模块

request.urlopen()代表请求过程,它返回的HTTPResponse对象代表响应。

HTTPResponse对象status属性返回请求HTTP后的状态,在处理数据之前要先判断状态情况。如果请求未被响应,需要终止内容处理。reason属性非常重要,可以得到未被响应的原因,url属性是返回页面URL。

HTTPResponse.read()是获取请求的页面内容的二进制形式。3.向服务器发送数据urllib.request和urllib.parse模块GET也可以提交,与POST的区别如下。1)GET方式可以通过URL提交数据,待提交数据是URL的一部分;采用POST方式,待提交数据放置在HTMLHEADER内。2)GET方式提交的数据最多不超过1024二字节,POST没有对提交内容的长度限制。如果没有设置urlopen()函数的data参数,HTTP请求采用GET方式,也就是我们从服务器获取信息,如果我们设置data参数,HTTP请求采用POST方式,也就是我们向服务器传递数据。data参数有自己的格式,具体格式我们不用了解,因为我们可以使用urllib.parse.urlencode()函数将字符串自动转换成上面所说的格式。下面是发送data实例,向“百度翻译”发送要翻译数据data,得到翻译结果。urllib.request和urllib.parse模块#创建Form_Data字典,存储向服务器发送的Data

Form_Data={'from':'en','to':'zh','query':en_str,'transtype':'hash'}#创建Form_Data字典,存储向服务器发送的Data

Form_Data

={}

Form_Data['from']='en'

Form_Data['to']='zh'

Form_Data['query']=en_str#要翻译数据

Form_Data['transtype']='hash'URL='http:///v2transapi?from=en&to=zh&query=hello%20world&transtype=hash'

data=parse.urlencode(Form_Data).encode('utf-8')#使用urlencode方法转换标准格式response=request.urlopen(URL,data)#传递Request对象和转换完格式的数据html=response.read().decode('utf-8')#读取信息并解码

translate_results=json.loads(html)#使用JSON#print(translate_results)#打印出JSON数据

translate_results=translate_results['trans_result']['data'][0]['dst']#找到翻译结果print

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论