正则表达式(下)

正则表达式元字符、预定义字符、重复匹配总结

import re
def fun(ftn,lst):
    for n in lst:
        result = re.match(ftn,n)
        if result:
            print(n,'匹配正确',result.group())
        else:
            print(n,'匹配不正确')
#匹配.元字符
ftn='p.t'
lst=['python','pacdoc','peade','patonm']
fun(ftn,lst)
运行结果:
python 匹配正确 pyt
pacdoc 匹配不正确
peade 匹配不正确
patonm 匹配正确 pat
#匹配|逻辑或
ftn='p|t'
lst=['python','pacdoc','tpeade','patonm']
fun(ftn,lst)
运行结果:
python 匹配正确 p
pacdoc 匹配正确 p
tpeade 匹配正确 t
patonm 匹配正确 p
#匹配[]字符集一个字符
ftn='p[yt]'
lst=['python','pacdoc','tpeade','ptonmy']
fun(ftn,lst)
python 匹配正确 py
pacdoc 匹配不正确
tpeade 匹配不正确
ptonmy 匹配正确 pt
#转义\.(转义后只是普通的.标点符号)
ftn=r'p\w\.'
lst=['py.thon','pa.cdoc','pes.ade','pt.onmy']
fun(ftn,lst)
运行结果
py.thon 匹配正确 py.
pa.cdoc 匹配正确 pa.
pes.ade 匹配不正确
pt.onmy 匹配正确 pt.
#\w预定义可匹配字符及(m)重复m次以上
ftn=r'p\w{3}'
lst=['python','pacdoc','pe','ptonmy']
fun(ftn,lst)
运行结果
python 匹配正确 pyth
pacdoc 匹配正确 pacd
pe 匹配不正确
ptonmy 匹配正确 pton
#\w预定义可匹配字符及(m,n)重复m次以上n次以下
ftn=r'p\w{3,4}'
lst=['python','pacdoc','pe','ptonmy']
fun(ftn,lst)
运行结果
python 匹配正确 pytho
pacdoc 匹配正确 pacdo
pe 匹配不正确
ptonmy 匹配正确 ptonm
#\w预定义可匹配字符及(m,)重复m次以上
ftn=r'p\w{6,}'
lst=['python','pacdoc5','pe','ptonmy']
fun(ftn,lst)
运行结果
python 匹配不正确
pacdoc5 匹配正确 pacdoc5
pe 匹配不正确
ptonmy 匹配不正确
#.*?
ftn=r'.*?'
lst=['python','pacdoc5','pe','ptonmy']
fun(ftn,lst)
运行结果
python 匹配正确 
pacdoc5 匹配正确 
pe 匹配正确 
ptonmy 匹配正确 

re 常用方法

  • compile(pattern, flags=0)
    用于将字符串形式的正则表达式编译为Pattern模式对象,可以实现更加效率的匹配。
import re
pat = re.compile(r'abc')
result = pat.match('abc123abc456abc789').group()
result1 = pat.search('abc123abc456abc789').group()
result2 = pat.findall('abc123abc456abc789')
result2 = pat.search('abc123abc456abc789').group()
print(result)
s = '<div>abc</div><div>efg</div><div>hij</div>'
pat = re.compile(r'<div>(.*?)</div>')
result = pat.findall(s)
print(result)
运行结果
['abc', 'efg', 'hij']
import re
pat = re.compile(r'Abc',re.I)
result = pat.match('abc123abc456abc789').group()
print(result)
运行结果
abc

总结:re.I 不区分大小写匹配

  • search()和match()方法基本上使用一样,区别在于它查找位置不同, search()查找不区分开头字符。
import re

result = re.search(r'abc','afe123abc1r3',re.I).group()
print(result)
运行结果
abc
  • findall(pattern, string, flags=0)
    作为re模块的三大搜索函数之一,findall()和match()、search()的不同之处在于,前两者都是单值匹配,找到一个就忽略后面,直接返回不再查找了。而findall是全文查找,它的返回值是一个匹配到的字符串的列表。这个列表没有group()方法,没有start、end、span,更不是一个匹配对象,仅仅是个列表!如果一项都没有匹配到那么返回一个空列表
import re
s = '<div>abc</div><div>efg</div><div>hij</div>'
result1 = re.findall(r'<div>(.*?)</div>',s)
print(result1[2])
运行结果
hij
  • split(pattern, string, maxsplit=0, flags=0)
    re模块的split()方法和字符串的split()方法很相似,都是利用特定的字符去分割字符串。但是re模块的split()可以使用正则表达式,因此更灵活,更强大
    split有个参数maxsplit,用于指定分割的次数

    • 思路将以下字符串number=4+57/2分割成数字
      用findall()方法
      number='4+5
      7/2'
      result = re.findall(r'[^+*/]',number)
      print(result)
      ['4', '5', '7', '2']
      用split()方法
      number='4+5*7/2'
      result = re.split(r'[+*/]',number)
      print(result)
      ['4', '5', '7', '2']
      result1 = re.split(r'[+*/]',number,maxsplit=2)
      print(result1)
      ['4', '5', '7/2']
  • sub(pattern, repl, string, count=0, flags=0)
    sub()方法类似字符串的replace()方法,用指定的内容替换匹配到的字符,可以指定替换次数.

import re
str1='i am very good,i am very nice'
result = re.sub('i','I',str1)
print(result)
运行结果
I am very good,I am very nIce

重点部分:分组功能(匹配与提取)

Python的re模块有一个分组功能。所谓的分组就是去已经匹配到的内容再筛选出需要的内容,相当于二次过滤。实现分组靠圆括号(),而获取分组的内容靠的是group()、groups(),其实前面我们已经展示过。re模块里的积个重要方法在分组上,有不同的表现形式,需要区别对待
如下例match方法下取得分组功能应用

import re
s = '<div>abc</div><div>efg</div><div>hij</div>'

result1 = re.match(r'<div>(.*?)</div><div>(.*?)</div><div>(.*?)</div>',s).groups()
print(result1)
result2 = re.match(r'<div>(.*?)</div><div>(.*?)</div><div>(.*?)</div>',s).group(2)
print(result2)
运行结果:
('abc', 'efg', 'hij')
efg

如下例findall方法下取得分组功能应用

import re
s = '<div>abc</div><div>efg</div><div>hij</div>'
result1 = re.findall(r'<div>(.*?)</div>',s)
print(result1)
print(result1[1])
运行结果
['abc', 'efg', 'hij']
efg

思考:将下列字符串'apple price is 66,banana price is24'实现分组功能提取66,24'
思路一:

import re
str1 = 'apple price is $66,banana price is $24'
result = re.findall(r'.*?(\$\d{2})',str1)
print(result)
['$66', '$24']

思路二:

import re
str1 = 'apple price is $66,banana price is $24'
result = re.match(r'.*?(\$\d{2,}).*?(\$\d{2,})',str1).groups()
print(result)
('$66', '$24')

csv快速入门

  • 什么是csv?

是一种常用的文本格式,用以存储表格数据,包括数字或者字符。很多程序在处理数据时都会碰到csv这种格式的文件。python自带了csv模块,专门用于处理csv文件的读取

  • csv模块的使用

    • 写入csv文件

[列表法]通过创建writer对象,主要用到2个方法。一个是writerow,写入一行。另一个是writerows写入多行

import csv
headers = ['姓名','性别','年龄']
content = [('李明','男','16'),('李小明','男','26'),('李大 明','男','36'),('李老明','男','46')]
with open('examp.csv','w',encoding='utf-8',newline='')as obj_file:
    writer = csv.writer(obj_file)
    writer.writerow(headers)
    writer.writerows(content)
import csv
headers = ['姓名','性别','年龄']
content = [('李明','男','16'),('李小明','男','26'),('李大 明','男','36'),('李老明','男','46')]
with open('examp.csv','w',encoding='utf-8',newline='')as obj_file:
    writer = csv.writer(obj_file)
    writer.writerow(headers)
    for data in content:
        writer.writerow(data)

[字典法]使用DictWriter 可以使用字典的方式把数据写入进去

headers = ('name','age','height')
persons = [
    {'name':'笔记本','age':18,'height':175},
    {'name':'张同学', 'age': 18,'height':175},
    {'name':'杨同学', 'age': 18,'height':175},
]
with open('examp.csv','w',encoding='utf-8',newline='')as obj_file:
    writer = csv.DictWriter(obj_file,headers)
    writer.writeheader()
    writer.writerows(persons)

读取文件

1 通过reader()读取到的每一条数据是一个列表。可以通过下标的方式获取具体某一个值

2 通过DictReader()读取到的数据是一个字典。可以通过Key值(列名)的方式获取数据



with open('persons.csv','r',encoding='utf-8',newline='') as file_obj:
    reader = csv.reader(file_obj)
    for x in reader:
        print(x[2])


with open('persons.csv', 'r', encoding='utf-8', newline='') as file_obj:
    Dreader = csv.DictReader(file_obj)
    for x in Dreader:
        print(x['name'])

爬虫案例总结

  • 需求:爬取7天的 天气情况 日期 天气状况温度 风力--> 保存到CSV
  • 解决方法:正则表达式解析网页
  • URL网址:http://www.weather.com.cn/weather/101250101.shtml
  • 检查网页结构,是否是静态网页Elements网页喧染是否与网页源代码一致
    <ul class="t clearfix"标签在网页源代码对应的是
    ···
    </ul>
    <div id="7d" class="c7d">
    <input type="hidden" id="hidden_title" value="04月29日20时 周四 晴 16/32°C" />
    <input type="hidden" id="fc_24h_internal_update_time" value="2021042920"/>
    <input type="hidden" id="update_time" value="18:00"/>
    <ul class="t clearfix">
    <li class="sky skyid lv2 on">
    <h1>29日(今天)</h1>
    <big class="png40"></big>
    <big class="png40 n00"></big>
    <p title="晴" class="wea">晴</p>
    <p class="tem">
    <i>16℃</i>
    </p>
    <p class="win">
    <em>
    <span title="南风" class="S"></span>
    </em>
    <i><3级</i>
    </p>
    <div class="slid"></div>
    </li>
    ···
    通过对比发现网页喧染是否与网页源代码一致,所以可以利用正则、xpath对网页进行解析
  • 要对网页数据进行解析,首先我们知道<ul class="t clearfix">标签内的内容对应的就是我们要解析的数据,所以利用分组将其匹配提取出来,从而进一步缩小了要解析的范围.
  • 7天的数据都在UL标签下级LI标签里,所以我们可以进一步匹配7天的数据
  • 通过for语句,得到1天的数据,同时利用分组提取一天所需的元素,并将其放入列表中,同时通过append()得到七天的数据
  • 最后利用CSV模块将数据存储到CSV文件中
import re
import csv
import requests

class WeatherSpider():

    def __init__(self):
        self.headers = {'User-Agent':
                       'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}

    def Readurlsourse(self,url):
        response = requests.get(url,headers= self.headers)
        res = response.content.decode('utf-8')
        return res

    def Parsingpages(self,res):
        result = re.match(r'.*?(<ul class="t clearfix">.*?</ul>).*?',res,re.S).group(1)
        lis = re.findall(r'<li.*?>.*?</li>',result,re.S)
        pat = re.compile(r'<li.*?>.*?<h1>(.*?)</h1>.*?<p.*?>(.*?)</p>.*?<i>(.*?)</i>.*?<i>(.*?)</i>.*?</li>', re.S)
        lst_all=[]
        for li in lis:
            r = pat.match(li)
            lst_one = [r.group(1), r.group(2), r.group(3), r.group(4)]
            lst_all.append(lst_one)
        return lst_all

    def Datasave(self,lst_all):
        has = ['日期', '天气', '温度', '风力']
        with open('weather7day.csv', 'w', encoding='utf-8', newline='') as file_obj:
             writer = csv.writer(file_obj)
             writer.writerow(has)
             writer.writerows(lst_all)


    def main(self):
        url = 'http://www.weather.com.cn/weather/101250101.shtml'
        res = self.Readurlsourse(url)
        lst_all = self.Parsingpages(res)
        self.Datasave(lst_all)


if __name__ == '__main__':
    ws = WeatherSpider()
    ws.main()

得到最后结果是:
日期,天气,温度,风力
29日(今天),晴,16℃,<3级
30日(明天),晴,17℃,<3级
1日(后天),多云,18℃,<3级
2日(周日),多云转小雨,21℃,<3级
3日(周一),中雨转大雨,21℃,<3级
4日(周二),小雨转阴,19℃,<3级
5日(周三),阴,18℃,<3级
至此,正则表达式知识点总结完毕,还需多加练习!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容