python_new
  • Introduction
  • First Chapter
  • 一、python基础
    • 1.1 常识
      • sys
    • 1.2 基础语法(1)
    • 1.2 基础语法(2)
    • 1.3 常见问题求解
    • 1.4 算法
  • 二、爬虫
    • urllib库(1)
      • urllib库(2)
    • requests模块(1)
      • requests模块(2)
    • 2.1 爬虫基础(3)HTTP原理
    • 2.1 爬虫基础(4)会话和Cookies
    • 2.1 爬虫基础(5)数据存储
      • Mysql存储
      • MongoDB存储
      • Redis存储
    • 2.3 正则表达式
    • 2.4 解析库lxml
      • BeautifulSoup
      • pyquery(1)
      • pyquery(2)
    • 2.5 selenium(1)
    • 2.5 seleium(2)
    • 2.6 Json
    • 2.7 scrapy
      • scrapy(2)
    • 2.9 异步加载
    • 2.6 Splash
  • ORM框架
    • SQLAlchemy
  • Django
    • 1、初阶(一)
    • 初学:投票教程(一)
    • 初学:投票教程(二)
    • 初学:投票教程(三)
    • 初学:投票教程(总结)
    • 模型(一)
    • 模型(二)
    • 视图(一)
    • 视图(二)
    • 模板(一)
    • django实际使用笔记
  • 面试题收集总结
    • 数据结构原理
    • 算法篇
      • 排序
    • 题目篇
  • python数据分析
    • 基础了解(一)
    • 基础了解(二)
    • 基础了解(三)
  • 多线程
  • 深度学习
    • 疑问
  • keras(一)
  • 神经网络
  • 图像识别
  • Docker
    • 一、基础了解
Powered by GitBook
On this page

Was this helpful?

  1. 二、爬虫

2.3 正则表达式

一、匹配

1.元字符:不与自身匹配,会和一些其他字符匹配

.   ^   $   *   +   ?   []   {}   \   |   ()

2.元字符 ‘[ ]’,用于制定一个字符类(所想指定的字符集)

[abc] #可以匹配字符‘a’‘b’‘c’中的任意一个字符
[a-c] #与上面的有相同功能

元字符在字符类中不起作用

[abc$] #其中$只代指‘$’这个字符,不具备其他意义

3.元字符‘ () ’,分组,可以使用group()方法来索引

import re

p = re.compile('ab')
m = p.match('ab')
m.group(0)
'ab'

group()默认0为匹配字符串

import re

p = re.compile('(a(b)c)d')
m = p.match('abcd')
m.group(0)
'abcd'
m.group(1)
'abc'
m.group(2)
'b'
m.group(0,1,2)
('abcd','abc','b')

分组使得很容易从匹配到的字符串中提取数据,也可以很容易进行组合以元组的形式输出

#接上面
p = re.comple(r'\b(\w+)\s\1')
p.match('He is a abc from overseas') #??

如何逆向引用?

4.元字符 ‘ ^ ’,在‘[ ]’内时匹配除此之外的任意字符

[^a] #必须把‘^’作为首字符,不然不起作用,该字符类匹配除a之外的所有字符

还可以用于只匹配字符串的开头,如果使用了标志M,则会匹配每一行字符串的开头

import re

print (re.search('com', 'http://www.baidu.com'))
None
print (re.search('From', 'From here to there'))
<_sre.SRE_Match object; span=(0, 4), match='From'>

5.转义字符 ‘\’,用于取消元字符的特殊意义

\[ #取消‘[’的意义
\\ #取消‘\’的意义

但是一些特殊组合表示特定的意义,如

\d #匹配十进数,相当于类[0-9]
\D #匹配任何非数字字符,相当于类[^0-9]
\s #匹配任何空白字符,相当于[\t\n\r\f\v]
\S #匹配任何非空白字符,相当于[^\t\n\r\f\v]
\w #匹配任何字母数字字符,相当于[a-zA-Z0-9]
\W #匹配任何非字母数字字符,相当于[^a-zA-Z0-9]

#举例
[\s,.]

6.元字符 ‘ . ’,可以匹配除了换行符之外的所有字符

7.元字符‘ | ’,‘或’操作符,如‘ (A|B) ’,则会匹配A或B,常和分组符号‘()’一起用

8.元字符‘ $ ’,与‘ ^ ’刚好相反,只匹配行尾的字符串,或者任何后面紧跟着一个换行符的位置。

9.零宽界定符‘ \b ’,没有宽度,用于匹配单词的开头和结尾

import re

p = re.compile(r'\bclass\b')
p.search('no class at all')
<_sre.SRE_Match object; span=(3, 8), match='class'>
p.search('classfied')
None

10.与‘ \b ’类似,‘ \B ’另一个零宽界定符,只有不是开头和结尾才符合

二、重复

指定某一部分的重复次数

1.元字符‘ * ’,‘贪婪’的重复(Greedy),可以重复零个或任意多个字符

[ca*t]   #可以匹配‘ct’ ‘cat’ ‘caaat’等字符串
a[bcd]*b #可以匹配‘abcdb’‘abcb’‘abb’等字符串 ?

2.元字符‘ + ’,至少有一个

[ca+t] #可以匹配‘cat’‘caat’,但不能匹配‘ct’

3.元字符‘ ? ’,有一个或零个

[a-?b] #只能匹配‘a-b’或者‘ab’

4.重复限定符{m,n},表示至少重复m次,最多不能超过n次,省略m,则默认下限为0,省略n,则默认无上限或上限为无穷

a/{1,2}b #可以匹配‘a/b’'a//b',但不能匹配‘ab’'a///b'

前面三种都可以有{m.n}的格式来表示

三、使用

re模块:一个被Python包含的C扩展模块,就像socket模块

1.正则表达式被便以为正则表达式对象,可以用来做模式匹配或字符串替换

import re

p = re.compile('ab*')
p = re.compile('ab*', re.IGNORECASE) #该参数可以忽略匹配字符串的大小写

2.反斜杠的问题,为了避免反斜杠的重复,使用python中原始字符串来简化

r'\n'        #代表‘\’和‘n‘
r'\\section' #代表‘\section‘ ??

3.正则表达式对象的方法和属性

  • match() 判断从字符串开头是否匹配正则表达式

import re

p = re.compile('[a-z]+')
m = p.match('')
print m
None

如果可以匹配的话,会回复一个match对象

<_sre.SRE_Match object; span=(0, 3), match='3b2'>

match对象的方法和属性

import re

p = re.compile('[a-z]+')
m = p.match('ok')
m.group()          #返回匹配正则表达式的字符串
'ok'
m.start(),m.end()  #前者返回匹配字符串开始的位置,后者返回匹配字符串结束的位置
(0, 2)
m.span()           #返回一个包括开始和结束位置的元组
(0, 2)
  • 模块中也有match(), search(), sub()函数等

实际中可以用正则表达式对象本身的方法,也可以使用模块的中的函数,当调用函数时,第一个参数就是正则表达式,之后该函数会自动创建一个正则表达式对象。两者使用时如何选择,之后再了解。

4.编译标志

ASCII, A      #使\w,\b,\W,\B,\s,\S只匹配ASCII字符,而不匹配Unicode
DOTALL, S     #使字符'.'匹配任意字符,包括换行符
INGORECASE, I #使匹配对大小不敏感
LOCALE, L     #做本地化识别 ??
MULTILINE, M  #多行匹配,会影响 ??
VERBOSE, V    #能够使用正则表达式的verbose装填,使之更加清晰易懂  ??

四、无捕获组和命名组、前向界定符

当我们捕获一个字符串时,其中有我们感兴趣的部分,也有不是很在意的部分。通过正则表达式中的分组功能,我们可以定义字符串中的无捕获组和命名组,来区分字符串中的信息。

  • 无捕获组:格式为‘ (? = REs) ’,REs为正则表达式,只能从组1开始。

import re

m = re.match('([abc])+','abc')
m.groups()
('c',)
m = re.match('(?:[abc])+','abc')
m.groups()
()
  • 命名组:格式为‘ (?P<name>) ’,命名组的作用是将特别关心的信息命名,之后调用的时候,就不用难记的序号,而是用名字直接引用。

import re

p = re.compile(r'(?P<word>\b\w+\b)')
m = p.search('((Hello World))')
m.group('word')
'Hello'
m.group(1)
'Hello'

重要的是,逆向引用中也可以使用命名组。

#接上

p = re.compile(r'(?P<word>\b\w+)\s+(?P<word>)')
n = p.search('Say Hello')
m.group()

仍然不会逆向引用。。。

前向界定符,又称为‘前向断言’,是一种不会引起正则表达式引擎移动的匹配模式,只会返回匹配结果,有肯定和否定两种。

  • 肯定前向界定符:格式为' (?REs) ',在当前位置匹配成功时,返回成功,否则失败。

import re

p = re.compile('re(?gular)')
m = p.match('regular expression')
're'
p = re.compile('re(?Gular)')
m = p.match('regular expression')
None
  • 否定前向定界符:格式为' (?!REs) ',在当前位置匹配不成功时,返回成功,否则失败。

import re

p = re.compile('re(?gular)')
m = p.match('regular expression')
None
p = re.compile('re(?Gular)')
m = p.match('regular expression')
're'

前向界定符可以用来简化很多情况,比如当匹配模式中想要排除某种情况,直接用‘ ^ ’的形式,可能会非常复杂,但是使用前向界定符直接判断前方是否有那种情况,如果有则失败,没有则继续匹配。

五、修改字符串

除了搜索特定字符串之外,正则表达式还可以动态地修改字符串,主要操作有切片,替换等。

1.切片 split()

  • 正则表达式对象中的方法,可以设置参数来控制切片的数量。

import re

p = re.compile(r'\W+')
p.split('This is a test string of split().')
['This', 'is', 'a', 'test', 'string', 'of', 'split', '']
p.split('This is a test string of split().', 3)
['This', 'is', 'a', 'test string of split().']

有时我们对于分隔符也比较感兴趣,这时使用捕获括号,就能将分隔符作为列表的元素返回

import re

p = re.compile(r'(\W+)')
p.split('This is a test string of split().')
['This', ' ', 'is', ' ', 'a', ' ', 'test', ' ', 'string', ' ', 'of', ' ', 'split', '().', '']
  • 模块中的函数 re.split(REs, string, [maxstep = 0] )

import re

re.split('[\W]+','This is a test string of split().')
['This', 'is', 'a', 'test', 'string', 'of', 'split', '']
re.split('([\W]+)','This is a test string of split().')
['This', ' ', 'is', ' ', 'a', ' ', 'test', ' ', 'string', ' ', 'of', ' ', 'split', '().', '']
re.split('[\W]+','This is a test string of split().',3)
['This', 'is', 'a', 'test string of split().']

2.替换 sub() 和subn()

  • 正则表达式中的方法

import re

p = re.compile('(blue|white|red)')
p.sub('color','blue socks and red shoes')
'color socks and color shoes'
p.sub('color','blue socks and red shoes',count = 1)
'color socks and red shoes'

subn()的作用类似,但是会返回一个包括新字符串和替换次数的元组

import re

p = re.compile('(blue|white|red)')
p.subn('color','blue socks and red shoes')
('color socks and color shoes', 2)
p.sub('color','no color at all')
('no colors at all', 0)

空匹配只有在紧邻的前面一个没有被替换时才会替换

import re

p = re.compile('x*')
p.sub('-','abxd')
'-a-b-d-'

如果用来替换的字符串中有反斜杠,都会被处理。如‘ \n’ 会被作为换行符。逆向引用也可以被使用。

3.re.findall(pattern, string[,flags]),搜寻string,以列表的形式返回全部能匹配的字符串

import re
p = re.compile(r'\d+')
print (re.findall(p,'one1two2three3four4'))
['1','2','3','4']

4.re.finditer(pattern, string[,flags]),搜寻string,返回一个顺序访问每一个匹配结果(match对象)的迭代器

import re
p = re.compile(r'\d+')
for item in re.finditer(p,'one1two2three3four4'):
    print (item.group())
1 2 3 4

六、小结

正则表达式' \(1)s ', ' \(2)s ', r' \(1)s '都是代表着空白字符,而只有r' \(2)s '才能匹配字符串中的' \(1)s ',而返回的匹配字符串是' \(2)s '。

if '\s' == '\\s':
    print (1)
1

这个说明想要不使用原始字符串匹配‘ \(1)s ’,就必须要用' \(4)s ',因为目标字符串看似是‘ \(1)s ’,其实是' \(2)s '。从' \(4) s '到r' \(2)s ',这就是原始字符的作用。另外,r'\(1)s' 就等于' \(2)s',因此它代表的也是' \(1)s ',这时r就显得多余了。

七、补充

1、?匹配前面一个表达式0次或多次,如果紧跟在量词 * + {} ?后 量词为非贪婪,匹配尽量少的字符。例如,对 "123abc" 应用 /\d+/ 将会返回 "123",如果使用 /\d+?/,那么就只会匹配到 "1"。

PreviousRedis存储Next2.4 解析库lxml

Last updated 6 years ago

Was this helpful?