Python编程学习-基础笔记09

十一、数据提取

11.1 正则提取

1,正则表达式的定义:
正则表达式是对字符串(包括普通字符a-Z和特殊字符:元字符)操作的一种逻辑公式,就是用实现定义好的一些特定字符及符组合,组成一个“规则的字符串”
正则表达式,又称正规表示式,正规表示法,正规表达式,规则表达式,常规表示法,英文:Regular Expression,简写为 Regex,或 Regexp
2,正则表达的作用和特点:
给定一个正则表达式和一个字符串,可以达到如下目的
1,给定的字符串是否符合正则表达式的过滤逻辑,称作“匹配”
2,通过正则表达,可以从字符串中获取我们想要的部分
正则表达的特点:
1,灵活性、逻辑性和功能性非常强
2,可以迅速第用极简单的方式达到字符串的复杂控制
3,使用场景:
1,如何判断字符串是手机号
2,判断邮箱地址是126或163的
3,网页爬虫,爬取想要的数据

import re
#使用正则模块re的方法:match
s = '普京大大如来'
result = re.match('普京',s) #从开头进行匹配,如果不成功就返回None
print(result) #<re.Match object; span=(0, 2), match='普京'> span--》匹配的位置
result = re.match('如来',s) #从开头进行匹配,如果不成功就返回None
print(result) #None
result = re.search('如来',s) #从开头进行匹配,向后搜索,匹配的是整个字符串
print(result) #<re.Match object; span=(4, 6), match='如来'>
print(result.span()) # 返回位置(4, 6)
print(result.group()) # 使用group来提取匹配到的内容:如来
print(result.span()) # (4, 6)

4,总结

'''
总结:
    . 任意字符,除\n
    ^ 开头
    $ 结尾
    [] 范围 [abc] [a-zA-Z*&#]
    正则预定义:
        \s 匹配任意空白字符 空格 等价于[\t \n \t \f]
        \S 匹配任意非空格
        \b 匹配一个单词边界,也就是单词和空格间的位置
        \B 匹配非单词边界
        \d 匹配任意数字,等价于[0-9]
        \D 匹配任意非数字字符,等价于[^\d]
        \w word 匹配任意字母数字及下划线,等价于[0-9a-zA-Z]
        '\w[0-9]' --> \w [0-9] 只能匹配一个字母
        \\ 匹配原意的反斜杠\
    量词:
        * >= 0
        + >=1
        ? 0,1
    手机号码的 正则:
        re.matah('1[3456789]\d{9}$',phone)
        {m} : 固定m位
        {m,} : >=m位
        {m,n} : >=m,<=n
'''

正则模式讲解1

#分组
#判断数字是0-100之间的数字
import re
n = '05'
result = re.match(r'[1-9]?\d',n)
print(result)

n= '100'
result = re.match(r'[1-9]?\d?$|100$',n)
print(result)

#验证输入的邮箱是 126 163 qq
# (word|word|word)--》表示的是整个单词 区别 [abc] --》表示的是单个字符
email = 'python123@126.com'
result = re.match(r'\w{6,20}@(126|163|qq)\.(com|cn)$',email)
print(result)

#[] 表示一个范围
s = 'haha5d'
result = re.search('[0-9][a-z]',s) #数字+字母
print(result.group())

s1 = 'haha5ms6sh46bmla21sdfge'
result = re.search('[a-z][0-9][a-z]',s1) #字母+数字+字母, 只要找到匹配的就不会继续查找
print(result.group()) #a5m
result = re.findall('[a-z][0-9][a-z]',s1) #字母+数字+字母,匹配整个字符串,找到一个后会继续查到结尾
print(result)   #['a5m', 's6s']

#a7b a88a a889a 查这样的规则
msg = 'a7bdra88a56wea889a'
result = re.findall('[a-z][0-9]+[a-z]',msg) #+ 表示其前面的数字出现 >=1 次
print(result) #['a7b', 'a88a', 'a889a']

正则模式讲解2

import re

#起名的方式: (?P<名字>正则) (?P=名字)

msg = '<html><h1>abc</h1></html>'
result = re.match(r'<(?P<name1>\w+)><(?P<name2>\w+)>(.+)</(?P=name2)></(?P=name1)>',msg)
print(result) #<re.Match object; span=(0, 25), match='<html><h1>abc</h1></html>'>
print(result.group(1)) #html
print(result.group(2)) #h1
print(result.group(3)) #abc

#number
result = re.match(r'<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)</\2></\1>',msg)
print(result) #<re.Match object; span=(0, 25), match='<html><h1>abc</h1></html>'>

'''
分组:() ---》 result.group(1) 获取组中的匹配内容
    分组的时候可以结合 | 来使用
    result = re.match(r'\w{6,20}@(126|163|qq)\.(com|cn)$',email)
        
不需要引用分组的内容:
    result = re.match(r'<[0-9a-zA-Z]+>(.+)</[0-9a-zA-Z]+>',msg)
    print(result) 
    print(result.group(1)) 
    print(result.group(2)) 
需要引用到分组中的内容:
    1,number: \mumber 表示引用第几组的数据
        result = re.match(r'<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)</\2></\1>',msg)
        
    2,?P(名字):
        result = re.match(r'<(?P<name1>\w+)><(?P<name2>\w+)>(.+)</(?P=name2)></(?P=name1)>',msg)
re模块中用到的:
    match   从开头匹配,只匹配一次
    search  只匹配一次
    findall 查找所有
    sub(正则表达式,新内容,string)   替换 
    split --》 result = re.split(r'[,:]','java:99,python:100'),在字符串中搜索,见冒号和逗号进行分隔

'''
result = re.sub(r'\d+','90','java:99,python:100')
print(result) #java:90,python:90

def func(temp):
    num = temp.group()
    num1 = int(num) + 1
    return str(num1)

result = re.sub(r'\d+',func,'java:99,python:100')
print(result)


result = re.split(r'[,:]','java:99,python:100') #见冒号和逗号切割
print(result) #['java', '99', 'python', '100']

#查找不是以4 / 7 结尾的手机号
phone = '18910110117'
result = re.match(r'1\d{9}[0-35689]$',phone)
print(result) #None

#爬虫相关标签
#分组
phone = '010-123456789'
result = re.match(r'(\d{3}|\d{4})-(\d{8,10})',phone)
#分别提取
print(result.group()) #010-123456789
#()表示分组,group(1) 表示提取到第一组的内容
print(result.group(1)) #010
print(result.group(2)) #123456789

#爬虫
msg = '<html>abcd</html>'
msg1 = '<h1>hello word</h1>'
# result = re.match(r'<[0-9a-z]+>(.+)</[0-9a-z]+>',msg)
result = re.match(r'<\w+>(.+)</\w+>',msg1)
print(result)
print(result.group(1))

11.2 贪婪匹配

'''
python里数量词默认是贪婪的,总是尝试匹配尽可能多的字符
非贪婪则相反,总数匹配尽可能少的字符
在 * ? + {m,n} 后面加上?,使贪婪变成非贪婪

'''
import re

#默认是贪婪匹配
msg = 'abc124abc'
result = re.match(r'abc(\d+)',msg)
print(result.group()) #abc124
#非贪婪,在贪婪模式上加?
result = re.match(r'abc(\d+?)',msg)
print(result.group()) #abc1

import requests

#从网页找一张图片,将其下载
path = '<img class="j_retract" id="big_img_1658651276742" src="https://imgsa.baidu.com/forum/w%3D580%3B/sign=b7c3532af003738dde4a0c2a8320b251/8b13632762d0f7039f4db9560efa513d2797c5b8.jpg" onerror="this.src="//tb2.bdstatic.com/tb/static-frs/img/v2/picerr.gif;this.width=82;this.height=75;" style="visibility: visible;">'
#提取图片路劲
# result = re.match(r'<img class="j_retract" id="big_img_1658651276742" src="(.+\.jpg)"',path)
result = re.match(r'<img class="j_retract" id="big_img_1658651276742" src="(.+?)"',path)
print(result.group(1))

imag_path = result.group(1) #https://imgsa.baidu.com/forum/w%3D580%3B/sign=b7c3532af003738dde4a0c2a8320b251/8b13632762d0f7039f4db9560efa513d2797c5b8.jpg
response = requests.get(imag_path)
with open('pic.jpg','wb') as wstream: 
    wstream.write(response.content) #将图片存本地
posted @ 2022-07-25 08:28  逆流的鱼2016  阅读(31)  评论(0编辑  收藏  举报