正则表达式

通配符的使用

* : 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']

"""
import  glob

正则表达式常用逻辑及方法


#     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())

正则表达式特殊字符类

字符类:
    [pP]ython :p或P
    westos[pP]
    [aeiou]
    [a-z]
    [A-Z]
    [a-zA-Z0-9]
    [^aeiou] :匹配aeiou以外字符
    [^0-9]:匹配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&'))

在这里插入图片描述

指定字符出现次数

匹配字符出现次数:

*: 代表前一个字符出现0次或者无限次;    d*,  .*
+: 代表前一个字符出现一次或者无限次;     d+
?: 代表前一个字符出现1次或者0次;   假设某些字符可省略, 也可以不省略的时候使用

第二种方式:

{m}: 前一个字符出现m次;
{m,}: 前一个字符至少出现m次;  * == {0,}; + ==={1,}
{m,n}: 前一个字符出现m次到n次; ? === {0,1}
import re

print(re.findall(r'd*', ''))
print(re.findall(r'd*', 'ddd'))
print(re.findall(r'd*', 'dwww'))
print(re.findall(r'.*', 'westos'))



print(re.findall(r'd+', ''))
print(re.findall(r'd+', 'ddd'))
print(re.findall(r'd+', 'dwww'))
print(re.findall(r'd+', 'westos'))


print(re.findall(r'188-?', '188 6543'))
print(re.findall(r'188-?', '188-6543'))
print(re.findall(r'188-?', '148-6543'))

在这里插入图片描述

匹配不同格式电话号码

pattern = r'\d{3}[\s-]?\d{4}[\s-]?\d{4}'
print(re.findall(pattern,'188 6754 7645'))
print(re.findall(pattern,'18867547645'))
print(re.findall(pattern,'188-6754-7645'))

在这里插入图片描述

匹配qq邮箱

练习: 匹配一个qq邮箱;(xdshcdshvfhdvg@qq.com)  --- 
如果想在正则里面匹配真实的. , \.xdshcdshvfhdvg
(可以由字母数字或者下划线组成, 但是不能以数字或者下划线开头; 位数是6-12之间)
import re

pattern = r'[A-z]\w{5,11}@qq\.com'

s = """

你好,各种格式的邮箱入下所示:

    kevintian126@126.com 

2. 1136667341@qq.com 

westos1131@qq.com 
westos1131@qq.com 

3. meiya@cn-meiya.com 


4. wq901200@hotmail.com 
westfen31@qq.com 
5. meiyahr@163.com

6. meiyuan@0757info.com 

7. chingpeplo@sina.com 

8. tony@erene.com.com

9. melodylu@buynow.com

具体释义入下:

1.163邮箱 




提供以@163.com为后缀的免费邮箱,3G空间,支持超大20兆附件,280兆网盘。精准过滤超过98%的垃圾邮件。 


2.新浪邮箱 




提供以@sina.com为后缀的免费邮箱,容量2G,最大附件15M,支持POP3。 



3.雅虎邮箱 




提供形如@yahoo.com.cn的免费电子邮箱,容量3.5G,最大附件20m,支持21种文字。 


4.搜狐邮箱 



提供以@sohu.com结尾的免费邮箱服务,提供4G超大空间,支持单个超大10M附件。强大的反垃圾邮件系统为您过滤近98%的垃圾邮件。 


5.QQ邮箱 

提供以@qq.com为后缀的免费邮箱,容量无限大,最大附件50M,支持POP3,提供安全模式,内置WebQQ、阅读空间等。 

"""
dataLi = re.findall(pattern, s)
with open('email.txt', 'w') as f:
    for email in dataLi:
        f.write(email + '\n')

在这里插入图片描述

匹配所有的IP地址

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)$'


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')

在这里插入图片描述

用户名,QQ号,身份证号

#   匹配用户名:  必须是由字母数字或者下划线及-和中文组成, 必须是大于一个字符的;
#   [A-Za-z0-9_\-\u4e00-\u9fa5]+
#   [\w\-\u4e00-\u9fa5]+
#   [\w\-\u4e00-\u9fa5]{4,12}


# QQ号: 6-12位
# [1-9]([0-9]{5,11})
# [1-9](\d{5,11})



# 身份证号: 610 112 20001001  345x  (匹配新的身份证和老的身份证号)
# \d{17}[\d|x]|\d{15}

获取贴吧总页数

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])

在这里插入图片描述


s1 = 'http://www.westos.org/linux/book/'
pattern = 'http://[\w\.]+/(?P<courseName>\w+)/(?P<courseType>\w+)/'
# print(re.findall(pattern, s1))

#
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 = '610897199004154534'
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')

在这里插入图片描述

爬取单个照片

from urllib.request import urlopen

url = 'http://imgsrc.baidu.com/forum/w%3D580/sign=e23a670db9b7d0a27bc90495fbee760d/38292df5e0fe9925f33f62ef3fa85edf8db17159.jpg'


# 1. 获取图片的内容
content = urlopen(url).read()


#  2. 写入本地文件
with open('hello.jpg', 'wb') as f:
    f.write(content)

在这里插入图片描述

爬取指定贴吧图片

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))

在这里插入图片描述

伪装浏览器

from urllib.request import urlopen
from urllib import  request

url = "http://www.cbrc.gov.cn/chinese/jrjg/index.html"
# 如何伪装成浏览器访问?
# 1. 定义一个真实浏览器的代理名称
user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
# 2. 写到请求页面的header里面去
req = request.Request(url,headers={'User-Agent': user_agent} )
#  3. 打开网页, 获取内容
print(urlopen(req).read().decode('utf-8'))
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值