Python核心技术实战详解(txt+pdf+epub+mobi电子书下载)


发布时间:2020-08-20 22:32:07

点击下载

作者:张洪朋 王卫军

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Python核心技术实战详解

Python核心技术实战详解试读:

前言

Python的应用越来越广泛,为了帮助程序员掌握高级的开发技术并提高编程效率,本书特意挑选了程序员常用的Python核心功能模块进行讲解,如网络编程、多线程开发、图形化界面开发、数据可视化、Web开发和爬虫开发等。本书内容

全书共10章,主要内容包括如下。

第1章详细讲解正则表达式和常用的函数。

第2章主要讲解了套接字编程、socketserver编程、使用select模块实现I/O多路复用、使用urllib包、使用HTTP包、解析XML、解析JSON数据等。

第3章介绍了_thread 模块、threading模块、进程库multiprocessing、线程优先级队列模块queue、使用subprocess模块创建进程等。

第4章讲解了Tkinter开发基础、Tkinter组件开发、Tkinter事件处理、通过Tkinter实现对话框效果,并结合开发资源管理器实例介绍了Tkinte的具体用法等。

第5章介绍了SQLite3数据库、MySQL数据库、MariaDB数据库、MongoDB数据库、Python和ORM等开发知识。

第6章介绍了Pygame框架的核心模块、经典游戏实战、传统贪吃蛇游戏和AI贪吃蛇游戏开发技术等。

第7章讲解了Matplotlib、Pygal库、Pandas库、NumPy库等,帮助读者轻松完成图表的绘制。

第8章介绍了Django及其常用的命令,并通过几个综合案例,具体讲解了Django的使用,如博客系统、新闻聚合系统和在线商城系统开发。

第9章讲解了Flask开发基础、表单操作和具体案例,并通过应用把Flask的知识串联起来,达到学以致用的目标。

第 10 章介绍了网络爬虫的基础知识、如何开发网络爬虫应用程序、如何使用爬虫框架Scrapy、如何抓取知乎数据并分析、如何实现爬虫模块等。本书特色● 内容讲解深入。

本书对Python的核心知识进行了深入剖析,循序渐进地讲解了核心功能模块的开发技术,帮助读者快速步入Python开发高手之列。● 提供更为广泛的解决方案。

本书深入讲解了10个不同的主题模块,每一个主题涵盖了特定应用开发领域。在书中不仅给出了案例讲解,还包含了更多的拓展知识,能够帮助读者使用Python 开发各种类型的应用程序。● 通过网站论坛形成互帮互学的朋友圈。

为了方便给读者答疑,特提供了网站论坛等支持,并且随时在线与读者互动,让大家在互学互帮中形成一个良好的学习编程的氛围。

本书的学习论坛是toppr网站(后缀名为.net)。

本书读者对象包括程序开发人员、软件测试人员和Web开发人员。

张洪朋编写了本书第1章和第3~9章,用友网络科技股份有限公司的王卫军编写了本书的第2章和第10章。在编写本书过程中,十分感谢家人给予的巨大支持。限于作者水平,书中纰漏之处在所难免,请读者提出意见或建议,以便我们对内容修订并使之日臻完善。编辑联系邮箱是zhangtao@ptpress.com.cn。

最后感谢您购买本书,希望本书能成为您编程路上的领航者,祝您阅读快乐!作者服务与支持

本书由异步社区出品,社区(https://www.epubit.com/)为您提供后续服务。

在异步社区本书页面中单击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。提交勘误

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可(见下图)。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。与我们联系

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。

如果您所在的学校、培训机构或企业想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。关于异步社区和异步图书“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。异步社区微信服务号第1章 正则表达式

正则表达式(Regular Expression,RE)是计算机科学中的一个重要概念。正则表达式描述了一种字符串匹配的模式,可以用来判断一个字符串是否含有某个子字符串,再将匹配的子字符串进行替换,或者从某个字符串中取出符合某个条件的子串等。本章将详细讲解在Python程序中使用正则表达式的知识,为读者进行本书后面知识的学习打下坚实的基础。1.1 基本语法

正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,字母a~z )和特殊字符(称为元字符)。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。正则表达式虽是复杂的,但它也是强大的。在当今市面中,绝大多数开发语言都支持利用正则表达式进行字符串操作,如C++、Java、C#、PHP和Python等。

正则表达式是由普通字符以及特殊字符组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。作为一个模板,正则表达式将某种字符模式与所搜索的字符串进行匹配。本节将详细讲解正则表达式的基本语法知识。1.1.1 普通字符

正则表达式包含文本和特殊字符的字符串,该字符串描述了一种可以识别各种字符串的模式。对于通用文本来说,用于正则表达式的字母表是所有大小写字母及数字的集合。普通字符包括没有显式指定为元字符的所有可打印和不可打印字符,这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。

下面介绍的正则表达式都是普通字符,它们仅用一个简单的字符串就能构造成一个匹配字符串的模式:该字符串由正则表达式定义。表1-1所示为几个正则表达式和它们所匹配的字符串。表1-1 普通字符正则表达式和它们匹配的字符串正则表达式模式匹配的字符串foofooPythonPythonabc123abc123

表1-1中的第一个正则表达式模式是“foo”,该模式没有使用任何特殊符号去匹配其他符号,只匹配所描述的内容。所以,能够匹配这个模式的只有包含“foo”的字符串。同理,对于字符串“Python”和“abc123”,也一样。正则表达式的强大之处在于引入特殊字符来定义字符集、匹配子组和重复模式。正是由于这些特殊符号,使得正则表达式可以匹配字符串集合,而不只是单个字符串。

由此可见,普通字符表达式属于最简单的正则表达式形式。1.1.2 非打印字符

非打印字符也可以是正则表达式的组成部分,表1-2列出了表示非打印字符的转义序列。表1-2 非打印字符的转义序列字符描述\cx匹配由x指明的控制字符,例如,\cM匹配一个Control-M或回车符。x的值必须为A~Z或a~z中之一;否则将c视为一个原义的 'c' 字符\f匹配一个换页符,等价于 \x0c和\cL\n匹配一个换行符,等价于 \x0a和\cJ\r匹配一个回车符,等价于 \x0d和\cM\s匹配任何空白字符,包括空格、制表符、换页符等,等价于 [ \f\n\r\t\v]\S匹配任何非空白字符,等价于 [^ \f\n\r\t\v]\t匹配一个制表符,等价于 \x09和\cI\v匹配一个垂直制表符,等价于 \x0b和\cK1.1.3 特殊字符

所谓特殊字符,就是一些有特殊含义的字符,如“*.txt”中的星号,就表示任何字符串的意思。如果要查找文件名中有“*”的文件,则需要对“*”进行转义,即在其前加一个“\”,即“\*.txt”。如果要匹配这些特殊字符,则必须首先对字符进行转义,即将“\”放在它们的前面。表1-3列出了正则表达式中的特殊字符。表1-3 正则表达式中的特殊字符特殊字符描述$匹配输入字符串的结尾位置,如果设置了RegExp对象的Multiline属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$( )标记一个子表达式的开始和结束位置。可以获取子表达式供以后使用。要匹配这些字符,请使用“\(”和“\)”*匹配前面的子表达式零次或多次。要匹配“*”字符,请使用“\*”+匹配前面的子表达式一次或多次。要匹配“+”字符,请使用“\+”.匹配除换行符\n之外的任何单字符。要匹配“.”字符,请使用“\.”[标记一个中括号表达式的开始。要匹配“[”,请使用“\[”?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配“?”字符,请使用“\?”\将下一个字符标记为特殊字符或原义字符或向后引用或八进制转义符。例如,'n' 匹配字符 'n','\n' 匹配换行符,序列 '\\' 匹配 "\",而 '\(' 则匹配 "("^匹配输入字符串的开始位置。要匹配“^”字符本身,请使用“\^”{标记限定符表达式的开始。要匹配“{”,可使用“\{”|指明两项之间的一个选择。要匹配“|”,可使用“\|”literal匹配文本字符串的字面值1.使用择一匹配符号匹配多个正则表达式模式

竖线“|”表示择一匹配的管道符号,也就是键盘上的竖线,表示一个“从多个模式中选择其一”的操作,用于分隔不同的正则表达式。例如,在表1-4中,左边是一些运用择一匹配的模式,右边是左边相应模式所能够匹配的字符。表1-4 “从多个模式中选择其一”的操作正则表达式模式匹配的字符串at| homeat、homer2d2 | c3por2d2、c3pobat | bet | bitbat、bet、bit

有了这个符号,就能够增强正则表达式的灵活性,使得正则表达式能够匹配多个字符串而不只是一个字符串。择一匹配有时也称并(union)或者逻辑或(logical OR)。2.匹配单个任意字符

点符号“.”可以匹配除了换行符“\n”以外的任何字符(Python正则表达式有一个编译标记S或者DOTALL,该标记是个例外,它使点号能够匹配换行符)。无论是一个字母、数字、空格(并不包括“\n”换行符)、可打印字符、不可打印字符,还是一个符号,使用点号都能够匹配它们,例如表1-5中的演示信息。表1-5 匹配单个任意字符的演示信息正则表达式模式匹配的字符串f.o匹配在字母“f”和“o”之间的任意一个字符,例如fao、f9o、f#o等..任意两个字符.end匹配在字符串end之前的任意一个字符注意:要显式匹配一个句点本身,必须使用反斜线进行转义,即“\.”。3.从字符串起始或者结尾以及单词边界匹配

一些符号和相关的特殊字符用于在字符串的起始和结尾部分指定所搜索的模式。如果要匹配字符串的开始位置,就必须使用脱字符“^”或者特殊字符“\A”(反斜线和大写字母A)。后者主要用于那些没有脱字符的键盘(例如,某些国际键盘)。同样,美元符号“$”或“\Z”将用于匹配字符串的末尾位置。注意:在本书讲解与字符串中模式相关的正则表达式时,会用术语“匹配”(matching)进行剖析。在Python术语中,主要有两种方法完成模式匹配。● 搜索(searching):在字符串任意部分中搜索匹配的模式。● 匹配(matching):指判断一个字符串能否从起始处全部或者部

分地匹配某个模式。搜索通过search()函数或方法来实现,而匹

配通过调用match()函数或方法来实现。总之,当涉及模式时,

全部使用术语“匹配”。

我们按照Python如何完成模式匹配的方式来区分“搜索”和“匹配”。

使用这些符号的模式与其他大多数模式是不同的,因为这些模式指定了位置或方位。表1-6展示了一些表示“边界绑定”的正则表达式搜索模式。表1-6 “边界绑定”的正则表达式搜索模式正则表达式模式匹配的字符串^From任何以From起始的字符串/bin/tcsh$任何以/bin/tcsh结尾的字符串^Subject: hi$任何由单个字符串Subject: hi构成的字符串

如果要依次匹配这些字符中的任何一个或者全部,就必须使用反斜线进行转义。例如,要匹配任何以美元符号结尾的字符串,一个可行的正则表达式方案就是使用模式“.*\$$”。

特殊字符\b和\B可以用来匹配字符边界。而两者的区别在于\b将用于匹配一个单词的边界,这意味着这个模式必须位于单词的起始部分,不管该单词前面(单词位于字符串中间)是否有其他任何字符,都认为这个单词位于行首。同样,\B将匹配出现在一个单词中间的模式(即不是单词边界)。表1-7是一些实例。表1-7 匹配字符边界的实例正则表达式模式匹配的字符串the任何包含the的字符串\bthe任何以the开始的字符串\bthe\b仅匹配单词the\Bthe任何包含但并不以the起始的字符串4.创建字符集

尽管句点可以用于匹配任意符号,但是在某些时候,可能想要匹配某些特定字符。正因如此,发明了中括号。该正则表达式能够匹配一对中括号中包含的任何字符,表1-8列出了一些实例。表1-8 创建字符集的实例

正则表达式模匹配的字符串式b[aeiu]tbat、bet、bit、but[cr][23][dp][o2]一个包含4个字符的字符串,第一个字符是“c”或“r”,然后是“2”或“3”,接着是“d”或“p”,最后要么是“o”要么是“2”。例如,c2do、r3p2、r2d2、c3po等

在“[cr][23][dp][o2]”这个正则表达式中,如果仅允许“r2d2”或者“c3po”作为有效字符串,就需要更严格限定的正则表达式。因为中括号仅表示逻辑或的功能,所以使用中括号并不能满足这一要求。唯一的方案就是使用择一匹配,例如“r2d2|c3po”。然而,对于单个字符的正则表达式来说,使用择一匹配和字符集是等效的。例如,我们以正则表达式“ab”作为开始。该正则表达式只匹配包含字母“a”且后面跟着字母“b”的字符串。如果要匹配一个字母的字符串,例如要么匹配“a”,要么匹配“b”,就可以使用正则表达式[ab],因为此时字母“a”和字母“b”是相互独立的字符串。我们也可以选择正则表达式“a|b”。然而,如果要匹配满足模式“ab”后面跟着“cd”的字符串,就不能使用中括号,因为字符集的方法只适用于单字符的情况。这种情况下,唯一的方法就是使用“ab|cd”,这与刚才提到的r2d2/c3po问题是相同的。5.使用闭包操作符实现存在性和频数匹配

下面开始介绍最常用的正则表达式符号,即特殊符号*、+和“ ?”,所有这些都可以用于匹配一个、多个或者没有出现的字符串模式。具体说明如下所示。● 星号(*)操作符将匹配其左边的正则表达式出现零次或者多次

的情况(在计算机编程语言和编译原理中,该操作称为Kleene闭

包)。● 加号(+)操作符将匹配一次或者多次出现的正则表达式(也叫

正闭包操作符)。● 问号(?)操作符将匹配零次或者一次出现的正则表达式。● 大括号操作符({}),表示里面或者是单个值或者是一对由逗号

分隔的值。这将最终精确地匹配前面的正则表达式N次(如果是

{N})或者一定范围的次数;例如,{M,N}将匹配M~N次出现。

这些符号能够由反斜线符号转义;\*匹配星号,等等。注意:在表1-3中曾使用问号(重载),这意味着要么匹配零次,要么匹配一次,或者其他含义:如果问号紧跟在任何使用闭合操作符的匹配后面,则它将直接要求正则表达式引擎匹配尽可能少的次数。尽可能少的次数是指,当模式匹配使用分组操作符时,正则表达式引擎将试图“吸收”匹配该模式的尽可能多的字符。这通常称为贪婪匹配。问号要求正则表达式引擎去“偷懒”,如果可能,就在当前的正则表达式中尽可能少地匹配字符,留下尽可能多的字符给后面的模式(如果存在)。

使用闭包操作符演示存在性和频数匹配的具体实例如表1-9所示。表1-9 使用闭包操作符演示存在性和频数匹配的具体实例

正则表达式模匹配的字符串式[dn]ot?字母“d”或者“n”,后面跟着一个“o”,然后最多一个“t”,例如,do、no、dot、not0?[1-9]任何数值数字,它可能前置一个“0”,例如,匹配一系列数(表示1~9月的数值),不管是一个还是两个数字[0-9]{15,16}匹配15或者16个数字(如信用卡号码)]+>匹配全部有效的(和无效的)HTML标签[KQRBNP][a-h]在“长代数”标记法中,表示国际象棋合法的棋盘移动(仅移动,[1-8]-[a-h][1-8]不包括吃子和将军)。即“K”“Q”“R”“B”“N”或“P”等字母后面加上“a1”~“h8”的棋盘坐标。前面的坐标表示从哪里开始走棋,后面的坐标表示走到哪个位置(棋格)上6.表示字符集的特殊字符

一些特殊字符能够表示字符集。与使用“0~9”这个范围表示的十进制数相比,可以简单地使用\d表示匹配任何十进制数字。另一个特殊字符(\w)能够用于表示全部字母数字的字符集,相当于[A-Za-z0-9_]的缩写形式,\s可以用来表示空格字符。这些特殊字符的大写版本表示不匹配。例如,\D表示任何非十进制数(与[^0-9]相同)。使用这些缩写,可以表示一些更复杂的实例,如表1-10所示。表1-10 表示字符集的特殊字符

正则表达式模匹配的字符串式\w+-\d+一个由字母数字组成的字符串和一串由一个连字符分隔的数字[A-Za-z]\w*第一个字符是字母,其余字符(如果存在)可以是字母或者数字(几乎等价于Python中的有效标识符)\d{3}-\d{3}-\d{4}美国电话号码的格式,前面是区号前缀,如800-555-1212\w+@\w+.com以XXX@YYY.com格式表示的简单电子邮件地址1.1.4 使用小括号指定分组

在Python程序中,有时可能会对之前匹配成功的数据更感兴趣。我们不仅想要知道整个字符串是否匹配指定的标准,而且想要知道能否提取任何已经成功匹配的特定字符串或者子字符串。要提取成功匹配的特定字符串成子字符串,只要用一对小括号包裹任何正则表达式即可。

当使用正则表达式时,一对小括号可以实现以下任意一个(或者两个)功能。● 对正则表达式进行分组。● 匹配子组。

对正则表达式进行分组的一个很好的示例是,有两个不同的正则表达式而且想用它们来比较同一个字符串。另一个原因是,将正则表达式分组可以在整个正则表达式中使用重复操作符(而不是一个单独的字符或者字符集)。

使用小括号进行分组的一个坏处就是,匹配模式的子字符串可以保存起来供后续使用。这些子组能够被同一次的匹配或者搜索重复调用,或者提取出来用于后续处理。

为什么匹配子组这么重要?主要原因是在很多时候除了进行匹配操作外,还需要提取所匹配的模式。例如,如果匹配模式是\w+-\d+,但是想要分别保存第一部分的字母和第二部分的数字,该如何实现?这样做的原因是,对于任何成功的匹配,可能想要看到这些匹配正则表达式模式的字符串究竟是什么。

如果为两个子模式都加上小括号,如(\w+)-(\d+),就能够分别访问每一个匹配子组。我们更倾向于使用子组,这是因为择一匹配首先通过编写代码来判断是否匹配,然后执行另一个单独的程序(该程序也需要另外创建),以表示整个匹配仅用于提取两个部分。表1-11展示了使用小括号实现指定分组的说明。表1-11 使用小括号实现指定分组的说明

正则表达式模匹配的字符串式\d+(\.\d*)?表示简单浮点数的字符串。也就是说,任何十进制数字后面可以接一个小数点和零个或者多个十进制数字,如“0.004”“2”“75.”等(Mr?s?.)?[A-Z]名字和姓氏,以及对名字的限制(如果有,首字母必须大写,后[a-z]*[A-Za-z-]+续字母小写),全名前可以有可选的“Mr.”“Mrs.”“Ms.”或者“M.”,姓氏没有限制,可以有多个单词、横线以及大写字母1.1.5 限定符

限定符用来指定正则表达式的一个给定组件必须出现多少次才匹配,有“*”“+”“?”以及{n}、{n,}、{n,m}这6种。正则表达式中的限定符信息如表1-12所示。表1-12 正则表达式中的限定符信息字符描述*匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。“*”等价于{0,}+匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配"z"。“+”等价于 {1,}?匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do"。“?”等价于 {0,1}{n}n是一个非负整数,能匹配确定的n次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个o{n,}n是一个非负整数,至少匹配n次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有o。'o{1,}' 等价于 'o+','o{0,}' 则等价于 'o*'{n,m}m和n均为非负整数,其中nm。最少匹配n次且最多匹配m次。例如,"o{1,3}" 将匹配 "fooooood" 中的前3个o。'o{0,1}' 等价于 'o?'。请注意,在逗号和两个数之间不能有空格

举个例子,本书页数很多,所以全书由很多章(一级目录)组成,每一章下面又分了节(二级目录),每一节下面又分了小节(三级目录)。因为本书内容多,有些章节编号超过9节,所以我们需要采用一种方式来处理两位或三位的章节编号。这时可以通过限定符来实现。下面的正则表达式匹配编号为任何位数的章节标题。/Chapter [1-9][0-9]*/

请注意,限定符出现在范围表达式之后,所以它应用于整个范围表达式。在本例中,只指定从0~9的数字(包括0和9)。

这里没有使用“+”限定符,因为在第二个位置或后面的位置不一定需要一个数字。也没有使用“?”字符,因为它将章节编号限制到两位数。我们需要至少匹配 Chapter和空格字符后面的一个数字。如果我们知道本书最多有99章,则可以使用下面的表达式来至少指定一位,至多指定两位数字。/Chapter [0-9]{1,2}/

上面的表达式的缺点是,大于99的章号仍只匹配开头两位数字。另一个缺点是Chapter 0也将匹配。下面是只匹配两位数字的更好的表达式。/Chapter [1-9][0-9]?/或:/Chapter [1-9][0-9]{0,1}/

其实“*”“+”和“?”限定符都是贪婪的,所以它们会尽可能多地匹配文字,在它们的后面加上一个“?”就可以实现非贪婪或最小匹配。例如,我们可能搜索HTML文档,目的是查找括在H1标记内的章节标题。假设这个要搜索的文本是通过如下形式存在的。

Chapter 1 – Introduction to Regular Expressions

下面的表达式可以匹配从开始H1标记的小于(<)符号到关闭H1标记的大于(>)符号之间的所有内容。/<.*>/

如果只需要匹配开始H1标记,则下面的“非贪心”表达式只会匹配

。/<.*?>/

通过在“*”“+”和“?”限定符之后放置“?”,该表达式从“贪心”表达式转换为“非贪心”表达式或者最小匹配。1.1.6 定位符

定位符能够将正则表达式固定到行首或行尾。另外,它还可以帮助我们创建这样的正则表达式,这些正则表达式出现在一个单词内、一个单词的开头或者一个单词的结尾。定位符用来描述字符串或单词的边界,^和$分别指字符串的开始与结束,\b用于描述单词的前边界或后边界,\B表示非单词边界。常用的正则表达式定位符如表1-13所示。表1-13 常用的正则表达式定位符字符描述^匹配输入字符串开始的位置。如果设置了RegExp对象的Multiline属性,^ 还会与\n或\r之后的位置匹配$匹配输入字符串结尾的位置。如果设置了RegExp对象的Multiline属性,$ 还会与\n或\r之前的位置匹配\b匹配一个字边界,即字与空格间的位置\B匹配非字边界

如果要在搜索章节标题时使用定位点,下面的正则表达式匹配一个章节标题,该标题只包含两个尾随数字,并且出现在行首。/^Chapter [1-9][0-9]{0,1}/

真正的章节标题不仅出现在行的开始处,还是该行中仅有的文本。它既出现在行首又出现在同一行的结尾。下面的表达式能确保指定的匹配只匹配章节而不匹配交叉引用。通过创建只匹配一行文本的开始和结尾的正则表达式,就可做到这一点。/^Chapter [1-9][0-9]{0,1}$/

匹配字边界稍有不同,但向正则表达式添加了很重要的功能。字边界是单词和空格之间的位置,非字边界是任何其他位置。下面的表达式匹配单词Chapter的开头3个字符,因为这3个字符出现在字边界后面。/\bCha/

\b字符的位置是非常重要的。如果它位于要匹配的字符串的开始,则它在单词的开始处查找匹配项。如果它位于字符串的结尾,则它在单词的结尾处查找匹配项。例如,下面的表达式匹配单词Chapter中的字符串ter,因为它出现在字边界的前面。/ter\b/

下面的表达式匹配Chapter中的字符串apt,但是不匹配aptitude中的字符串apt。/\Bapt/

字符串apt出现在单词Chapter中的非字边界处,但出现在单词aptitude中的字边界处。对于\B非字边界运算符,位置并不重要,因为匹配不关心究竟是单词开头还是结尾。1.1.7 限定范围和否定

除单字符之外,字符集还支持匹配指定的字符范围。方括号中两个符号中间用连字符(-)连接,用于指定一个字符的范围。例如,A-Z、a-z和0-9分别用于表示大写字母、小写字母与数字。这是一个按照字母顺序的范围,所以不能将它们仅限定于字母和十进制数字上。另外,如果脱字符(^)紧跟在左方括号后面,这个符号就表示不匹配给定字符集中的任何一个字符。具体实例如表1-14所示。表1-14 限定范围和否定的实例

正则表达式模匹配的字符串式z.[0-9]字母“z”后面首先跟着任何一个字符,然后跟着一个数字[r-u][env-y][us]字母“r”“s”“t”或者“u”后面首先跟着“e”“n”“v”“w”“x”或者“y”,然后跟着“u”或者“s”[^aeiou]一个非元音字符[^\t\n]不匹配制表符或者\n["-a]在一个ASCII系统中,所有字符都位于“"”和“a”之间,即范围是34~971.1.8 运算符优先级

正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式类似。相同优先级的从左到右进行运算,不同优先级的运算先高后低。表1-15从最高到最低说明了各种正则表达式中运算符的优先级顺序。表1-15 正则表达式中运算符的优先级运算符描述\转义符()、(?:)、(?=)、小括号和方括号[]*、+、?、{n}、限定符{n,}、{n,m}^、$、\任何元定位点和序列(即位置和顺序)字符、任何字符|替换,或操作字符具有高于替换运算符的优先级,使得"m|food"匹配"m"或"food"。若要匹配"mood"或"food",请使用括号创建子表达式,从而产生"(m|f)ood"1.1.9 扩展表示法

扩展表示法以问号(?…)开始,通常用于在判断匹配之前提供标记,实现一个前视(或者后视)匹配或者条件检查。表1-16展示了扩展表示法的基本用法。表1-16 扩展表示法的基本用法

正则表达式模匹配的字符串式(?:\w+.)*以句点结尾的字符串,如“google.”“twitter.”“facebook.”,但是这些匹配的字符串不会保存下来供后续使用(?#comment)此处并不进行,只是作为注释(?=.com)字符串后面跟着“.com”才进行匹配,并不使用任何目标字符串(?!.net)字符串后面不跟着“.net”才进行匹配(?<=800-)字符串之前为“800-”才进行匹配,假定为电话号码,同样并不使用任何输入字符串(?

在Python中,可使用re模块提供的内置标准库函数来处理正则表达式。在这个模块中,既可以直接匹配正则表达式的基本函数,也可以通过编译正则表达式对象,并使用其方法来使用正则表达式。本节将详细讲解使用re模块的基本知识。1.2.1 re模块中的库函数和属性

表1-17列出了 re模块中常用的内置库函数,它们中的大多数函数与已经编译的正则表达式对象(regex object)和正则表达式匹配对象(regex match object)的方法同名并且具有相同的功能。表1-17 re模块中常用的内置库函数函数描述compile(pattern使用任何可选的标记来编译正则表达式的模式,并返回一个正则,flags = 0)表达式对象match(pattern,尝试使用带有可选标记的正则表达式的模式来匹配字符串。如果string,flags=0)匹配成功,就返回匹配对象;如果失败,就返回Nonesearch(pattern使用可选标记搜索字符串中第一次出现的正则表达式模式。如果,string,匹配成功,则返回匹配对象;如果失败,则返回Noneflags=0)findall(pattern,查找字符串中所有(非重复)出现的正则表达式模式,并返回一string [, flags] )个匹配列表finditer(pattern,与函数findall()相同,但返回的不是一个列表,而是一个迭代器。string [, flags] )对于每次匹配,迭代器都返回一个匹配对象split(pattern,根据正则表达式的模式分隔符,split函数将字符串分割为列表,string,然后返回成功匹配的列表,最多分割maxsplit次(默认分割所有匹maxsplit=0)配成功的位置)sub(pattern,使用repl替换所有正则表达式的模式在字符串中出现的位置,除repl,string,非定义count,否则将替换所有出现的位置(另见subn()函数,该count=0)函数返回替换操作的数目)purge()清除隐式编译的正则表达式模式group(num=0)返回整个匹配对象,或者编号为num的特定子组groups(default=返回一个包含所有匹配子组的元组(如果没有成功匹配,则返回None)一个空元组)groupdict(default返回一个包含所有匹配的命名子组的字典,所有的子组名称作为=None)字典的键(如果没有成功匹配,则返回一个空字典)

表1-18列出了 re模块中常用的属性信息。表1-18 re模块中常用的属性信息属性说明re.I、re.不区分大小写的匹配IGNORECASEre.L、re.根据所使用的本地语言环境,通过\w、\W、\b、\B、\s、\S实现匹LOCALE配re.M、re.^和$分别匹配目标字符串中行的起始与结尾,而不是严格匹配整MULTILINE个字符串本身的起始和结尾re.S、re.“.”(点号)通常匹配除\n(换行符)之外的所有单个字符;该标DOTALL记表示“.”(点号)能够匹配全部字符re.X、re.通过反斜线转义后,所有空格加上#(以及在该行中的所有后续VERBOSE文字)的内容都被忽略1.2.2 使用函数compile()

在Python程序中,函数compile()的功能是编译正则表达式。使用函数compile()的语法如下所示。compile(source, filename, mode[, flags[, dont_inherit]])

通过使用上述格式,能够将source编译为代码或者抽象语法树对象。代码对象能够通过exec语句来执行或者使用eval()进行求值。各个参数的具体说明如下所示。● 参数source:字符串或者抽象语法树对象。● 参数filename:代码文件名称,如果不从文件读取代码,则传递

一些可辨认的值。● 参数mode:指定编译代码的种类,可以指定为exec、eval和

single。● 参数flags和dont_inherit:可选参数,极少使用。

下面的实例文件compilechuli.py演示了使用函数compile()将正则表达式的字符串形式编译为Pattern实例的过程。源码路径:daima\1\1-2\compilechuli.pyimport repattern = re.compile('[a-zA-Z]')result = pattern.findall('as3SiOPdj#@23awe')print(result)

在上述代码中,先使用函数re.compile()将正则表达式的字符串形式编译为Pattern实例,然后使用Pattern实例处理文本并获得匹配结果(一个匹配的实例),最后使用Match实例获得信息,进行其他操作。执行后输出:['a', 's', 'S', 'i', 'O', 'P', 'd', 'j', 'a', 'w', 'e']1.2.3 使用函数match()

在Python程序中,函数match()的功能是在字符串中匹配正则表达式,如果匹配成功,则返回MatchObject对象实例。使用函数match()的语法格式如下所示。re.match(pattern, string, flags=0)

各参数的具体说明如下。● 参数pattern:匹配的正则表达式。● 参数string:要匹配的字符串。● 参数flags:标志位,用于控制正则表达式的匹配方式,如是否区

分大小写、匹配多行等。参数flags的选项如表1-19所示。表1-19 参数flags的选项参数意义re.I忽略大小写re.L根据本地设置而更改\w、\W、\b、\B、\s以及\S的匹配内容re.M多行匹配模式re.S如果使“.”元字符,也匹配换行符re.U匹配Unicode字符re.X忽略模式中的空格,并且可以使用“#”注释注意:在Python中有多个内置模块,在每个内置模块中都会有很多内置函数。在平常描述时通常会直接使用函数名,而不会用模块前缀的方式。但是在程序中,必须使用函数的完整形式。例如,在上面的内容中,函数match()是内置模块re.的成员,所以在平常可以直接使用函数名的形式。但是在编写程序时,必须用完整的形式,即re.match。在本书的正文描述中将采用简写函数名的形式,在代码中将采用模块前缀的形式。

匹配成功后,函数re.match()会返回一个匹配的对象,否则返回None。可以使用函数group(num) 或函数groups()来获取匹配的表达式,如表1-20所示。表1-20 使用函数group(num)或函数groups()获取匹配的表达式

匹配对象方法描述group(num=0)匹配整个表达式的字符串,可以一次向group()输入多个组号,这种情况下它将返回一个包含那些组所对应值的元组groups()返回一个包含所有组中字符串的元组

下面是如何运用match()(以及group())的一个示例。>>> m = re.match('foo', 'foo') #模式匹配字符串>>> if m is not None: #如果匹配成功,就输出匹配内容... m.group()...'foo'

模式“foo”完全匹配字符串“foo”,也能够确认m是交互式解释器中匹配对象的实例。>>> m #确认返回的匹配对象

下面是一个失败的匹配示例,它会返回None。>>> m = re.match('foo', 'bar')#模式并不能匹配字符串>>> if m is not None: m.group() #单行版本的if 语句...>>>

因为上面的匹配失败,所以m被赋值为None,而且以此方法构建的if 语句没有指明任何操作。对于剩余的示例,为了简洁起见,可省去if 语句块。但是在实际操作中,最好不要省去,以避免AttributeError异常(None是返回的错误值,该值并没有group()属性[方法])。

只要模式从字符串的起始部分开始匹配,即使字符串比模式长,匹配也能够成功。例如,模式“foo”将在字符串“food on the table”中找到一个匹配,因为它是从字符串的起始部分进行匹配的。>>> m = re.match('foo', 'food on the table') # 匹配成功>>>m.group()'foo'

此时可以看到,尽管字符串比模式要长,但从字符串的起始部分开始匹配就会成功。子串“foo”是从那个比较长的字符串中抽取出来的匹配部分,甚至可以充分利用Python原生的面向对象特性,忽略保存中间过程产生的结果。>>>re.match('foo', 'food on the table').group()'foo'注意:在上述演示实例中,如果匹配失败,将会抛出AttributeError异常。

下面的实例文件sou.py演示了使用函数match()进行匹配的过程。源码路径:daima\1\1-2\sou.pyimport re #导入模块reprint(re.match('www', 'www.example.com').span())#在起始位置匹配print(re.match('net', 'www.example.com')) #不在起始位置匹配

执行后会输出:(0, 3)None

在正则表达式应用中,经常会看到关于电子邮件地址格式的正则表达式“\w+@\w+.com”,通常用于匹配这个正则表达式所允许的更多邮件地址。为了支持在域名前添加主机名称,如www.example.com,仅允许example.com作为整个域名,必须修改现有的正则表达式。为了表示主机名是可选的,需要创建一个模式来匹配主机名(后面跟着一个句点),使用问号( ?)操作符来表示该模式出现零次或一次,然后按照如下实例文件duoge.py所示的方式将可选的正则表达式插入之前的正则表达式\w+@(\w+\.)?\w+\.com中。源码路径:daima\1\1-2\duoge.py1 import re2 patt = '\w+@(\w+\.)?\w+\.com'3 print(re.match(patt, 'guan@example.com').group())4 print(re.match(patt, 'guan@www.example.com').group())56 patt = '\w+@(\w+\.)*\w+\.com'7 print(re.match(patt, 'guan@www.xxx.yyy.zzz.com').group())

从上述实例代码可以看出,表达式“\w+@(\w+\.)?\w+\.com”允许在“.com”前面有一个或者两个名称。第6行代码允许任意数量的中间子域名存在,读者需要注意这里的细节变化,此处将前面的“?”形式修改为“\w+@(\w+\.)*\w+.com”。这样仅使用字母数字字符的方式,并不能匹配组成电子邮件地址的全部可能字符。上面的正则表达式不能匹配诸如.com的域名,或者使用非单词“\W”字符组成的域名。

下面的实例文件tiqu.py演示了使用函数group()提取字母和数字字符的过程。源码路径:daima\1\1-2\tiqu.pyimport rem = re.match('(\w\w\w)-(\d\d\d)', 'abc-123')print(m.group())#完整匹配print(m.group(1))#子组1print(m.group(2))#子组2print(m.groups())#全部子组

在上述代码中,使用正则表达式能够提取字母、数字字符串和数字,方法是使用函数group()访问每个独立的子组,以及使用函数groups()获取一个包含所有匹配子组的元组。执行后会输出:abc-123abc123('abc', '123')1.2.4 使用函数search()

在Python程序中,函数search()的功能是扫描整个字符串并返回第一个成功的匹配。事实上,搜索模式出现在一个字符串中间部分的概率要远大于出现在字符串起始部分的概率。现在是将函数search()派上用场的时候。函数search()的工作方式与函数match()的几乎完全一致,不同之处在于,函数search()会用它的字符串参数在任意位置搜索给定正则表达式模式第一次出现的匹配情况。如果搜索到成功的匹配,就会返回一个匹配对象;否则,返回None。

使用函数search()的语法格式如下所示。re.search(pattern, string, flags=0)● 参数pattern:匹配的正则表达式。● 参数string:要匹配的字符串。● 参数flags:标志位,用于控制正则表达式的匹配方式,例如是否

区分大小写、允许多行匹配等。

匹配成功后,re.match()方法会返回一个匹配的对象;否则,返回None。可以使用函数group(num) 或函数groups()函数来获取匹配表达式。

下面的实例文件ser.py演示了使用函数search()进行匹配的过程。源码路径:daima\1\1-2\ser.pyimport re #导入模块reprint(re.search('www', '').span()) #在起始位置匹配print(re.search('net', '').span()) #不在起始位置匹配

执行后会输出:(0, 3)(10, 13)

下面的实例文件说明了函数match()和search()之间的差别,功能是使用字符串“foo”去匹配“seafood”。源码路径:daima\1\1-2\sousuo.pyimport re #导入模块rem = re.match('foo', 'seafood') #匹配失败if m is not None: m.group()m = re.search('foo', 'seafood') #使用 search() 代替if m is not None: m.group()

在上述代码中,当使用函数match()从字符串的起始部分进行匹配时,会失败。也就是说,模式中的“f”将匹配到字符串的首字母“s”上,这样的匹配肯定是失败的。然而,字符串“foo”确实出现在“seafood”之中(某个位置)。要想让Python得到肯定的结果,需要使用函数search(),而不是尝试匹配。函数search()不但会搜索模式在字符串中第一次出现的位置,而且严格地从左到右搜索字符串。1.2.5 使用函数findall()

在Python程序中,函数findall()的功能是在字符串中查找所有符合正则表达式的字符串,并返回这些字符串的列表。如果在正则表达式中使用了组,则返回一个元组。函数 re.match()和函数re.search()的作用基本一样。不同的是,函数re.match()只从字符串中第一个字符开始匹配,而函数re.search()则搜索整个字符串。

使用函数findall()的语法格式如下所示。re.findall(pattern, string, flags=0)

下面的实例文件fi.py演示了使用函数findall()进行匹配的过程。源码路径:daima\1\1-2\fi.pyimport re #导入模块re#定义一个要操作的字符串变量ss = "adfad asdfasdf asdfas asdfawef asd adsfas "reObj1 = re.compile('((\w+)\s+\w+)')#将正则表达式的字符串形式编译为Pattern实例print(reObj1.findall(s))#第1次调用函数findall()reObj2 = re.compile('(\w+)\s+\w+')#将正则表达式的字符串形式编译为Pattern实例print(reObj2.findall(s)) #第2次调用函数findall()reObj3 = re.compile('\w+\s+\w+') #将正则表达式的字符串形式编译为Pattern实例print(reObj3.findall(s)) #第3次调用函数findall()

因为函数findall()返回的总是正则表达式在字符串中所有匹配结果的列表,所以此处主要讨论列表中“结果”的展现方式,即findall返回列表中每个元素包含的信息。上述代码调用了三次函数findall(),具体说明如下所示。● 第1次调用:当给出的正则表达式中有多对小括号时,列表的元

素为多个字符串组成的元组,元组中的字符串个数与小括号对数

相同,字符串的内容与每个小括号内的正则表达式相对应,并且

按小括号中出现的顺序排放。● 第2次调用:当给出的正则表达式中有一对小括号时,列表的元

素为字符串,此字符串的内容与小括号中的正则表达式相对应(不是整个正则表达式的匹配内容)。● 第3次调用:当给出的正则表达式中不带小括号时,列表的元素

为字符串,此字符串为整个正则表达式匹配的内容。

执行后会输出:[('adfad asdfasdf', 'adfad'), ('asdfas asdfawef', 'asdfas'), ('asd adsfas', 'asd')]['adfad', 'asdfas', 'asd']['adfad asdfasdf', 'asdfas asdfawef', 'asd adsfas']

下面的实例文件wangzhi.py演示了使用函数findall()提取网址和锚文本的过程。源码路径:daima\1\1-2\wangzhi.pyimport rerelink = '(.*)'info = 'baidu'cinfo = re.findall(relink,info)print(cinfo)1.2.6 使用函数sub()和subn()

在Python程序中,两个函数/方法可用于实现搜索和替换功能,这两个函数分别是sub()和subn()。两者几乎一样,都用于将某字符串中所有匹配正则表达式的部分进行某种形式的替换。用来替换的部分通常是一个字符串,也可能是一个函数,该函数返回一个用来替换的字符串。函数subn()和函数sub()的用法类似,但是函数subn() 可以返回一个替换总次数,替换后的字符串和表示替换总次数的数字一起作为一个拥有两个元素的元组返回。

在Python程序中,函数sub()和函数subn()的语法格式分别如下。re.sub( pattern, repl, string[, count])re.subn( pattern, repl, string[, count])

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载