Spider--补充--Re模块_1


# @ Author : Collin_PXY

# 正则表达式:

import re

# 1,分步写法:
# 1)rule.search(string)
pattern='各小区'
rule=re.compile(pattern)
tel=rule.search(string)      # 返回第一个匹配的 re.Match object对象
print(tel.group()) 或 print(tel.group(0))  # 返回匹配到的字符串

# 2)relue.findall(string)   
pattern='各小区'
rule=re.compile(pattern)
rule.findall(str)    # 以列表的形式返回结果,如果没找到就返回空列表, 对于使用了()分组的 pattern,则只返回 分组内的匹配结果列表。

# 2,简化写法:  # 其中flags可以省略.
target=re.search(pattern, string, flags)   # 返回第一个匹配的 re.Match object对象
target.group()                             # 返回匹配到的字符串  或:
target.group(0)
re.findall(pattern, string, flags)         # 以列表的形式返回结果,如果没找到就返回空列表, 对于使用了()分组的 pattern,则只返回 分组内的匹配结果列表。

# 3,使用'()'及 group()     对pattern字符串进行分组:
# r'\d\d\d\d-\d\d\d-\d\d\d'       或 r'\d{4}-\d{3}-\d{3}'
# 使用()后改写为:
# r'(\d\d\d\d)-(\d\d\d)-(\d\d\d)' 或 r'(\d{4})-(\d{3})-(\d{3})'

# 3-1) 对于search()来讲,使用()后,对此对象使用使用group([index])方法可获得分组结果。

# 【注意】:
# target.group() 效果等同于target.group(0) 返回匹配符合的整个目标字符串。
# target.group(1)才是分组内的第一组字符串,target.group(2)为分组内的第二组字符串。

# 示例 1:
import re

string="""大家好,请各小区工作过人员注意外来人口,对外来人口实行体温监测,如有外来人员
不服从工作安排,请立马与我处联系,工作电话0539-233-689."""

pattern=r'(\d{4})-(\d{3})-(\d{3})'
tel=re.search(pattern,string)  # re.Match object
print(tel)           # 
print(tel.group())   # 0539-233-685
print(tel.group(0))  # 0539-233-685  等同上面  返回真个匹配的字符串
print(tel.group(1))  # 0539          返回分组内的第一组字符串
print(tel.group(2))  # 233           返回分组内的第二组字符串
print(tel.group(3))  # 685           返回分组内的第三组字符串


# 3-2)对于findall()来讲,使用()后,返回值由之前的列表变为了以分组的字符串组成的元组为元素的列表。
# 示例:
import re

string="""大家好,请各小区工作过人员注意外来人口,0111-555-011对外来人口实行体温监测,如有外来人员
不服从工作安排,请立马与我处联系,工作电话0539-233-689."""

pattern=r'(\d{4})-(\d{3})-(\d{3})'
tel=re.findall(pattern,string)  # re.Match object
print(tel)           # [('0111', '555', '011'), ('0539', '233', '689')]




# 4, groups()
# 对于search()来讲,使用()后,其返回值由之前的匹配到的字符串变为了re.Match object对象。
# 此时,对返回对象使用groups()方法后,可【多重指定】到相应的变量。

# 示例:
import re

string="""大家好,请各小区工作过人员注意外来人口,对外来人口实行体温监测,如有外来人员
不服从工作安排,请立马与我处联系,工作电话0539-233-689."""

pattern=r'(\d{4})-(\d{3})-(\d{3})'
tel=re.search(pattern,string)  # re.Match object
print(tel)           # 
first_tel,mid_tel,last_tel=tel.groups()  # 多重指定
print(first_tel)     # 0539
print(mid_tel)       # 233
print(last_tel)      # 689


# 5,当括号也是我们要匹配的目标时:使用转义符号\   
# 如(0539)-233-689
pattern=r'(\(\d{4}\))-(\d{3})-(\d{3})'


# 6, 使用管道 |  pipe
# 可以同时搜寻比对多个目标字符串,例如想要搜寻target1和target2两个字符串:
# pattern='target1|target2'
# 当target1和target2相同时,只会当作同一个target去搜寻。

# 示例1:
import re

msg = "1234567sdfghjiededd, 123,34567,dffgg"
pattern = 'sdf|3456'

target = re.search(pattern, msg)
print(target)  # <_sre.SRE_Match object; span=(2, 6), match='3456'>
print(target.group())   # 3456
print(target.group(0))  # 3456

target_list = re.findall(pattern, msg)
print(target_list)  # ['3456', 'sdf', '3456']


# 示例2:
import re
msg="1234567sdfghjiededd, 123,34567,dffgg"
pattern='\d{3}|sdf'
target_list=re.findall(pattern,msg)
print(target_list)  # ['123', '456', 'sdf', '123', '345']

# 示例3:
import re
msg="1234567sdfghjiededd, 123,34567,dffgg"
pattern='sdf|sdf'
target_list=re.findall(pattern,msg)
print(target_list)  # ['sdf']


# 7, 使用多个 | 管道搜寻

# 示例 1 search:
import re
msg="我爱中国我爱薇薇我爱我家我爱生活"   实际顺序是:中国 薇薇 生活
pattern = '我爱(薇薇|中国|生活)'  # 将()分组也用上   寻找--   我爱中国 我爱薇薇 我爱我家 我爱生活  
target=re.search(pattern,msg)
print(target)           # 
print(target.group())   # 我爱中国    传回搜寻到的第一次匹配到的整个字符串。
print(target.group(0))  # 我爱中国    效果同上 传回搜寻到的整个字符串。
print(target.group(1))  # 中国        传回分组内的第一组字符串  因为匹配到的是 我爱中国  所以分组内只搜寻到了 中国
print(target.group(2))  # 报错   因为 target里只包含了 ‘我爱中国’,括号内只有 中国


# 示例 2  findall:
import re
msg="我爱中国我爱薇薇我爱我家我爱生活"
pattern='我爱(薇薇|中国|生活)'      
target_list=re.findall(pattern,msg)
print(target_list)  # ['中国', '薇薇', '生活'] 

# 注意:使用findall时不可以使用group()方法,因为findall 返回的时列表,且只返回分组内的内容。
# 再如:
string="""大家好,请各小区工作过人员注意外来人口,对外来人口实行体温监测,如有外来人员
不服从工作安排,请立马(0539)-233-689与我处联系,工作电话0539-233-689."""

pattern=r'\d{4}-(\d{3})-(\d{3})'
tel=re.findall(pattern,string) 
print(tel)           # [('233', '689')]


# 8, 使用 ?号做搜寻
# 语法: (target)? 表示要搜寻的这个target字符串或者正则表达式表示的目标可有可无。

# 示例 1 (使用search())
import re

msg = "这个程序的重点是1介绍表达式的各种使用方法和使用情景,嗯2介绍正则表达式的示例"
pattern = "介绍(正则)?表达式"
target = re.search(pattern, msg)
print(target)  # 
print(target.group())   # 介绍表达式
print(target.group(0))  # 介绍表达式
print(target.group(1))  # None  1是指 括号内的  正则

# 示例 2 (使用search())
import re

msg = "这个程序的重点是1介绍正则表达式的各种使用方法和使用情景,嗯2介绍正则表达式的示例"
pattern = "介绍(正则)?表达式"
target_list = re.search(pattern, msg)
print(target_list)  # 
print(target_list.group())     # 介绍正则表达式
print(target_list.group(0))    # 介绍正则表达式
print(target_list.group(1))    # 正则

# 示例 2 (使用 findall)
import re
msg="这个程序的重点是1介绍表达式的各种使用方法和使用情景,嗯2介绍正则表达式的示例"
pattern="介绍(正则)?表达式"
target_list=re.findall(pattern,msg)
print(target_list)      # ['', '正则']    意义不大


# 示例 3:
import re
# 测试 1
msg = 'Please call my secretary using 02-26669999ssss26669999'
pattern = r'(\d\d-)?(\d{8})'                 # 增加?号
phoneNum = re.search(pattern, msg)           
print("完整号码是: %s" % phoneNum.group())   # 完整号码是: 02-26669999

# 测试 2
msg = 'Please call my secretary using 26669999ssss02-26669999'
pattern = r'(\d\d-)?(\d{8})'                 # 增加?号
phoneNum = re.search(pattern, msg)   
print("完整号码是: %s" % phoneNum.group())   # 完整号码是: 26669999


# 9, 使用 * 号做搜寻
# 语法: (target)* 表示要搜寻的这个target字符串或者正则表达式表示的目标可以连续重复出现 0次-多次。

# 示例1: search()
import re

# 测试1
msg = 'Johnson will attend my party tonight.'
pattern = 'John((na)*son)'  # 字符串na可以0到多次
txt = re.search(pattern, msg)  # 传回搜寻结果
print(txt.group())  # Johnson
# 测试2
msg = 'Johnnason will attend my party tonight.'
pattern = 'John((na)*son)'
txt = re.search(pattern, msg)
print(txt.group())  # Johnnason
# 测试3
msg = 'Johnnananason will attend my party tonight.'
pattern = 'John((na)*son)'
txt = re.search(pattern, msg)
print(txt.group())  # Johnnananason

# 示例2: findall()
import re
# 测试1
# 对于findall,有多个嵌套括号的,返回的是以元组为元素的列表,元组的元素的数量取决于嵌套括号的数量,元组的元素的顺序是从外到内。看例子:
msg = 'Johnson will attend my party tonight.'
msg = 'Johnson will Johnnanason attend Johnna my party tonight.'
pattern = 'John((na)*son)'  # 字符串na可以0到多次 匹配到的字符串必须包含 ’John‘ 及 ‘son’. ‘na’可有可无
txt_list = re.findall(pattern, msg)  # 多个括号的,返回的是以元组为元素的列表,  [('son', ''), ('nanason', 'na')]
print(txt_list)
for i in txt_list:
    for j in i:
        if j !="":
            print("John"+j)  # Johnson

# 测试2
msg = 'Johnnason will attend my party tonight.'
pattern = 'John((na)*son)'
txt_list = re.findall(pattern, msg)
print(txt_list.group())  # Johnnason
# 测试3
msg = 'Johnnananason will attend my party tonight.'
pattern = 'John((na)*son)'
txt_list = re.findall(pattern, msg)
print(txt_list.group())  # Johnnananason


# 10, 使用 + 做搜寻  一般用于search()
# 语法: (target)+ 表示要搜寻的这个target字符串或者正则表达式表示的目标可以连续重复出现 1次 - 多次。

import re
# 测试1
msg = 'Johnson will attend my party tonight.'
pattern = 'John((na)+son)'        # 字符串na可以0到多次
txt = re.search(pattern,msg)      # 传回搜寻结果
print(txt.group())                # None
# 测试2
msg = 'Johnnason will attend my party tonight.'
pattern = 'John((na)*son)'
txt = re.search(pattern,msg)
print(txt.group())                # Johnnason
# 测试3
msg = 'Johnnananason will attend my party tonight.'
pattern = 'John((na)*son)'
txt = re.search(pattern,msg)
print(txt.group())                # Johnnananason


# 11, 搜寻时忽略大小写
# 给search()或findall()增加一个参数 re.I 或 re.IGNORECASE

import re
msg = 'john and TOM will attend my party tonight. JOHN is my best friend.'
pattern = 'John|Tom'                        # 搜寻John和Tom
txt = re.findall(pattern, msg, re.I)        # 传回搜寻忽略大小写的结果
print(txt)  # ['john', 'TOM', 'JOHN']
pattern = 'Mary|tom'                        # 搜寻Mary和tom
txt = re.findall(pattern, msg, re.I)        # 传回搜寻忽略大小写的结果


# 12, 贪婪和非贪婪模式
# pattern = '(son){3,5}?'    pattern分为3部分,第一部分是要匹配的字符串,第二部分是重复次数{m,n},*,+,第三部分缺省的时候是贪婪,?时为非贪婪。
# 12-1)(target){n},(target){n,m},(target){n,},(target){,m}

# 1)--(target){n}设定搜寻的目标的重复次数 n次
# (son){3}表示sonsonson, 此时sonson就不能被匹配到。

# 2)--(target){n,m}设定搜寻的目标的重复次数范围 n~m次
# (son){1,3}表示 (son)|(son){2}|(son){3}
# 此时 son  sonson sonsonson 就都能被匹配到。

# 1)贪婪模式 示例:
import re

def searchStr(pattern, msg):
    txt = re.search(pattern, msg)
    if txt == None:         # 搜寻失败
        print("搜寻失败 ",txt)
    else:                   # 搜寻成功
        print("搜寻成功 ",txt.group())

        
msg1 = 'son'
msg2 = 'sonson'
msg3 = 'sonsonson'
msg4 = 'sonsonsonson'       实际上sonsonsonson包含了 sonsonson
msg5 = 'jsonsonsonsonson'    实际上sonsonsonsonson包含了 sonsonsonson 和 sonsonson
pattern = '(son){3,5}'
# pattern = 'j(son)*'
searchStr(pattern,msg1)  # 搜寻失败  None
searchStr(pattern,msg2)  # 搜寻失败  None
searchStr(pattern,msg3)  # 搜寻成功  sonsonson
searchStr(pattern,msg4)  # 搜寻成功  sonsonsonson     贪婪模式下只列出最长的
searchStr(pattern,msg5)  # 搜寻成功  sonsonsonsonson  贪婪模式下只列出最长的
searchStr(pattern,msg5)  # 搜寻成功  sonsonsonsonson  贪婪模式下只列出最长的

# 3)--(target){n,}设定搜寻的目标的重复次数范围 n次及以上
# 4)--(target){,m}设定搜寻的目标的重复次数范围 m次及以下


# 12-2) 贪婪与非贪婪搜寻:
# pattern = '(son){3,5}'   默认模式:贪婪模式        列出最长的匹配的字符串
# pattern = '(son){3,5}?'  右侧加个?表示 非贪婪模式  列出最短的匹配的字符串
# pattern = 'j(son)*?'

# 非贪婪模式 示例:
import re

def searchStr(pattern, msg):
    txt = re.search(pattern, msg)
    if txt == None:         # 搜寻失败
        print("搜寻失败 ",txt)
    else:                   # 搜寻成功
        print("搜寻成功 ",txt.group())

msg1 = 'son'
msg2 = 'sonson'
msg3 = 'sonsonson'
msg4 = 'sonsonsonson'      # 实际上sonsonsonson包含了 sonsonson
msg5 = 'sonsonsonsonson'   # 实际上sonsonsonsonson包含了 sonsonsonson 和 sonsonson

pattern = '(son){3,5}?'    # 非贪婪模式
# pattern = 'j(son)*?'     # 非贪婪模式

searchStr(pattern,msg1)  # 搜寻失败  None
searchStr(pattern,msg2)  # 搜寻失败  None
searchStr(pattern,msg3)  # 搜寻成功  sonsonson
searchStr(pattern,msg4)  # 搜寻成功  sonsonson    非贪婪模式下只列出最短的
searchStr(pattern,msg5)  # 搜寻成功  sonsonson    非贪婪模式下只列出最短的


import re
msg="这个程序的重点是介绍表达式的各种使用方法和使用情景,嗯介绍正则表达式的示例"
pattern="介绍(正则)?表达式"
target_list=re.findall(pattern,msg)
print(target_list)      # ['', '正则']    意义不大

参考资料:《Python 王者归来》洪锦魁