python筆記-正則表示式
阿新 • • 發佈:2018-12-14
萬用字元的使用
* : 0個到無窮多個任意字元
? :一個必定存在的任意字元
. :當前路徑
.. :上一級路徑
[0-9]:0到9所有數字
[a-z]:a到z所有小寫字母
[A-Z]:A到Z所有大寫字母
[a-zA-Z]:所有字母
官方參考程式碼:
>>> import glob >>> glob.glob('./[0-9].*') ['./1.gif', './2.txt'] >>> glob.glob('*.gif') ['1.gif', 'card.gif'] >>> glob.glob('?.gif') ['1.gif'] >>> glob.glob('**/*.txt', recursive=True) ['2.txt', 'sub/3.txt'] >>> glob.glob('./**/', recursive=True) ['./', './sub/'] >>> import glob >>> glob.glob('*.gif') ['card.gif'] >>> glob.glob('.c*') ['.card.gif']
正則表示式常用邏輯及方法
# re: regular experssion ==== 正則表示式 # 作用: 對於字串進行處理, 會檢查這個字串內容是否與你寫的正則表示式匹配, 如果匹配, 拿出匹配的內容; 如果不匹配, 忽略不匹配內容; # 學習正則的規則: import re s = "kiosk/home/kiosk/westosanaconda2/envs/blog/bin/python3.6/home/kiosk/Desktop/day25" # s.find('westos') # ***************************findall方法******************************** # 1. 編寫正則的規則 pattern1 = r'westos' pattern2 = r'kiosk' # 2. 通過正則去查詢匹配的內容 print(re.findall(pattern1, s)) print(re.findall(pattern2, s)) # ************************match******************************** # match嘗試從字串的起始位置開始匹配, # - 如果起始位置沒有匹配成功, 返回一個None; # - 如果起始位置匹配成功, 返回一個物件; print(re.match(pattern1, s)) matchObj = re.match(pattern2, s) # 返回match匹配的字串內容; print(matchObj.group()) # **********************search********************** # search會掃描整個字串, 只返回第一個匹配成功的內容; # - 如果能找到, 返回一個物件, 通過group方法獲取對應的字串; match1Obj = re.search(pattern1, s) print(match1Obj.group()) match2Obj = re.search(pattern2, s) print(match2Obj.group())
正則表示式特殊字元類
字元匹配:
r'westos'
字元類:
[pP]ython
westos[pP]
[aeiou]
[a-z]
[A-Z]
[a-zA-Z0-9]
[^aeiou]
[^0-9]
特殊字元類:
.: 匹配除了\n之外的任意字元; [.\n] \d: digit--(數字), 匹配一個數字字元, 等價於[0-9] \D: 匹配一個非數字字元, 等價於[^0-9] \s: space(廣義的空格: 空格, \t, \n, \r), 匹配單個任何的空白字元; \S: 匹配除了單個任何的空白字元; \w: 字母數字或者下劃線, [a-zA-Z0-9_] \W: 除了字母數字或者下劃線, [^a-zA-Z0-9
import re
# 字元類:
print(re.findall(r'[^0-9]', 'westos123westos'))
print(re.findall(r'[0-9]', 'westos123westos'))
# 特殊字元類 .
print(re.findall(r'.', 'westos\n'))
# 特殊字元類\d
print(re.findall(r'\d', '當前文章閱讀量為8'))
# 等待學習匹配次數的規則
print(re.findall(r'\d', '當前文章閱讀量為8000'))
# 特殊字元類\D
print(re.findall(r'\D', '當前文章閱讀量為8'))
# 等待學習匹配次數的規則
print(re.findall(r'\D', '當前文章閱讀量為8000'))
# 特殊字元類\s, \S
print(re.findall(r'\s', '\n當前\r文章閱\t讀量為8'))
# 等待學習匹配次數的規則
print(re.findall(r'\S', '\n當前\r文章閱\t讀量為8'))
# 特殊字元類\w, \W
print(re.findall(r'\w', '12當前westos文章閱_讀量為8&'))
# 等待學習匹配次數的規則
print(re.findall(r'\W', '12當前westos文章閱_讀量為8&'))
匹配IP
匹配字元出現次數:
*: 代表前一個字元出現0次或者無限次; d*, .*
+: 代表前一個字元出現一次或者無限次; d+
?: 代表前一個字元出現1次或者0次; 假設某些字元可省略, 也可以不省略的時候使用
第二種方式:
{m}: 前一個字元出現m次;
{m,}: 前一個字元至少出現m次; * == {0,}; + ==={1,}
{m,n}: 前一個字元出現m次到n次; ? === {0,1}
import re
pattern = r'[1-9]\d{0,2}\.[1-9]\d{0,2}\.[1-9]\d{0,2}\.[1-9]\d{0,2}'
print(re.findall(pattern, '172.25.0.2'))
print(re.findall(pattern, '172.25.1.2'))
print(re.findall(pattern, '172.25.1.278'))
# | 代表或者的意思
pattern1 = r'^(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)$'
# print(re.findall(pattern1, '172.25.1.278'))
# print(re.findall(pattern1, '172.25.1.178'))
Obj = re.match(pattern1, '172.25.1.178')
if Obj:
print("查詢到匹配的內容:", Obj.group())
else:
print('No Found')
Obj = re.match(pattern1, '172.25.1.278')
if Obj:
print("查詢到匹配的內容:", Obj.group())
else:
print('No Found')
獲取貼吧總頁數
from itertools import chain
from urllib.request import urlopen
import re
def getPageContent(url):
"""
獲取網頁原始碼
:param url: 指定url內容
:return: 返回頁面的內容(str格式)
"""
with urlopen(url) as html:
return html.read().decode('utf-8')
def parser_page(content):
"""
根據內容獲取所有的貼吧總頁數;
:param content: 網頁內容
:return: 貼吧總頁數
"""
pattern = r'<span class="red">(\d+)</span>'
data = re.findall(pattern, content)
return data[0]
def parser_all_page(pageCount):
"""
根據貼吧頁數, 構造不同的url地址;並找出所有的郵箱
:param pageCount:
:return:
"""
emails = []
for page in range(int(pageCount)):
url = 'http://tieba.baidu.com/p/2314539885?pn=%d' %(page+1)
print("正在爬取:%s" %(url))
content = getPageContent(url)
# pattern = r'\w[-\w.+]*@[A-Za-z0-9][-A-Za-z0-9]+\.+[A-Za-z]{2,14}'
pattern = r'[a-zA-Z0-9][-\w.+]*@[A-Za-z0-9][-A-Za-z0-9]+\.+[A-Za-z]{2,14}'
findEmail = re.findall(pattern, content)
print(findEmail)
emails.append(findEmail)
return emails
def main():
url = 'http://tieba.baidu.com/p/2314539885'
content = getPageContent(url)
pageCount = parser_page(content)
emails = parser_all_page(pageCount)
print(emails)
with open('tiebaEmail.txt', 'w') as f:
for tieba in chain(*emails):
f.write(tieba + '\n')
main()
正則中需要轉義的字元
因為這些字元在正則中有特殊含義, 所有必須轉義: ., +, ?, * 表示分組: | : 匹配| 左右任意一個表示式即可; (ab): 將括號中的字元作為一個分組 \num: 引用分組第num個匹配到的字串 (?P): 分組起別名
import re
# 當使用分組時, findall方法只能獲取到分組裡面的內容;
print(re.findall(r'(westos|hello)\d+', 'westos1hello2'))
pattern = r'<span class="red">(\d+)</span>'
s = '<span class="red">31</span>'
print(re.findall(pattern, s))
#
pattern = r'(<span class="red">(\d+)</span>)'
s = '<span class="red">31</span>'
print(re.findall(pattern, s))
print(re.findall(r'((westos|hello)\d+)', 'westos1hello2'))
# findall不能滿足時, 考慮使用search 或者match
Obj = re.search(r'(westos|hello)(\d+)', 'westos1hello2')
if Obj:
print(Obj.group())
print(Obj.groups())
else:
print('Not Found')
# 匹配IP
pattern = r'(([1-9]\d{0,2}\.){3}[1-9]\d{0,2})'
print(re.findall(pattern, '172.25.0.3'))
print(re.findall(pattern, '172.25.3.3')[0][0])
# \num
s = '<html><title>正則</title></html>'
# 目前有三個分組, \1: 代指第一個分組的內容, \2: 代指第一個分組的內容,
pattern = r'<(\w+)><(\w+)>(\w+)</\w+></\w+>'
print(re.findall(pattern, s))
s = '<html><title>正則</tite></html>'
# 目前有三個分組, \1: 代指第一個分組的內容, \2: 代指第一個分組的內容,
pattern = r'<(\w+)><(\w+)>(\w+)</\2></\1>'
print(re.findall(pattern, s))
s1 = 'http://www.westos.org/linux/book/'
pattern = 'http://[\w\.]+/(?P<courseName>\w+)/(?P<courseType>\w+)/'
Obj = re.match(pattern, s1)
if Obj:
print(Obj.group())
print(Obj.groups())
print(Obj.groupdict())
else:
print('Not Found')
# 身份證號: 610 897 19900415 4534
s = '610000199001013456'
pattern = r'(?P<Province>\d{3})[\s-]?(?P<City>\d{3})[\s-]?(?P<Year>\d{4})[\s-]?' \
r'(?P<Month>\d{2})(?P<Day>\d{2})(\d{4})'
Obj = re.search(pattern, s)
if Obj:
print(Obj.groupdict())
else:
print('Not Found')
爬取指定貼吧圖片
import re
from urllib.request import urlopen
def get_content(url):
"""
獲取網頁內容
:param url:
:return:
"""
with urlopen(url) as html:
return html.read()
def parser_get_img_url(content):
"""
解析貼吧內容, 獲取所有風景圖片的url
:param content:
:return:
"""
pattern = r'<img class="BDE_Image".*?src="(http://.*?\.jpg)".*?>'
imgUrl = re.findall(pattern, content.decode('utf-8').replace('\n', ' '))
return imgUrl
def main():
url = 'http://tieba.baidu.com/p/5437043553'
content = get_content(url)
imgLi = parser_get_img_url(content)
for index,imgurl in enumerate(imgLi):
# 根據圖片的url獲取每個圖片的內容;
content = get_content(imgurl)
with open('img/%s.jpg' %(index+1), 'wb') as f:
f.write(content)
print("第%s個圖片下載成功...." %(index+1))
main()
批量替換和批量分隔符分離
# split()方法: 指定多個分隔符進行分割;
import re
ip = '172.25.254.250'
print(ip.split('.'))
s = '12+13-15/16'
print(re.split(r'[\+\-\*/]', s))
#
s = 'westos is a company'
print(s.replace('westos', 'fentiao'))
# 希望替換的時數字, 但數字的值不固定, 則通過正則來實現;
s = "本次轉發數為100"
print(re.sub(r'\d+', '0', s))
# 自動會給addNum傳遞一個引數, 引數時匹配到的SRE物件
def addNum(sreObj):
"""在原有基礎上加1"""
# 年末任情況字串中匹配到的內容還是字串
num = sreObj.group() # ‘100’ ‘99’
new_num = int(num) + 1
return str(new_num)
s1 = "本次轉發數為100, 分享數量為99"
print(re.sub(r'\d+', addNum, s1))