爬虫笔记(三):正则表达式的使用

常见的匹配模式

\w      匹配字母数字及下划线
\W      匹配f非字母数字下划线
\s      匹配任意空白字符,等价于[\t\n\r\f]
\S      匹配任意非空字符
\d      匹配任意数字
\D      匹配任意非数字
\A      匹配字符串开始
\Z      匹配字符串结束,如果存在换行,只匹配换行前的结束字符串
\z      匹配字符串结束
\G      匹配最后匹配完成的位置
\n      匹配一个换行符
\t      匹配一个制表符
^       匹配字符串的开头
$       匹配字符串的末尾
.       匹配任意字符,除了换行符,re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
[....]  用来表示一组字符,单独列出:[amk]匹配a,m或k
[^...]  不在[]中的字符:[^abc]匹配除了a,b,c之外的字符
*       匹配0个或多个的表达式
+       匹配1个或者多个的表达式
?       匹配前面的子表达式零次或一次。当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。
{n}     精确匹配n前面的表示
{m,m}   匹配n到m次由前面的正则表达式定义片段,贪婪模式
a|b     匹配a或者b
()      匹配括号内的表达式,也表示一个组

Python中的正则表达式工具封装在re模块中

re.match

该方法尝试在字符串的起始位置开始匹配一个模式,如果不是起始位置开始,函数返回None

比较详细的匹配
import re

content= "hello 123 4567 World_This is a regex Demo"
result = re.match('^hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content) #加了$结束符,只能完全匹配content,不然就是None
print(result)
print(result.group()) #获取匹配的结果
print(result.span()) #获取匹配字符串的长度

content= "12123hello 123 4567 World_This is a regex Demo"
print(result) #None,不是从起始位置匹配
泛匹配

由于 . 表示任意字符,然后 * 表示匹配任意个表达式(包括零个),所有用 .* 可以简化掉匹配模式中不重要的部分

import re

content= "hello 123 4567 World_This is a regex Demo"
result = re.match("^hello.*Demo$",content)
print(result)
print(result.group())在这里插入图片描述
print(result.span())
匹配目标

有的时候目的不是匹配一个字符串,而是匹配上一个字符串后获取里面的目标,这时需要用到括号()

import re
content= "hello 1234567 World_This is a regex Demo"
result = re.match('^hello\s(\d+)\sWorld.*Demo$',content) #()中的内容是目标内容,获取目标的前提是re.match能匹配上
print(result)
print(result.group())
print(result.group(1)) #当匹配模式中有多个括号时,1表示第一个目标,不是0
print(result.span())
默认贪婪匹配

在正则匹配中,默认是采用贪婪匹配机制,比如 .* 会尽可能的匹配最多的字符

import re

content= "hello 1234567 World_This is a regex Demo"
result= re.match('^hello.*(\d+).*Demo',content)
print(result)
print(result.group(1)) #这里的结果是7,因为.*把123456都匹配过去了

如果想获取1234567,就在表达式*后面加个 ?,表示是非贪婪的

result= re.match('^he.*?(\d+).*Demo',content)
换行问题

当匹配的内容存在换行问题,需要用re.S来匹配换行的内容

import re
content= """hello 1234567 World_This is a regex Demo
            huanhang"""
result = re.match('^hello\s(\d+)\sWorld.*?huanhang$',content,re.S) #如果不加re.S,返回None
print(result)
print(result.group())
print(result.span())
转义

当匹配的内容存在特殊字符时,需要进行转义

import re
在这里插入图片描述
content= "price is $5.00"

result = re.match('price is \$5\.00',content)
print(result)
print(result.group())

re.search

re.search扫描整个字符串,返回第一个匹配的结果

import re

content = "extra things hello 123455 world_this is a Re Extra things"

result = re.search("hello.*?(\d+).*?Re",content)
print(result)
print(result.group())
print(result.group(1))

re.findall匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式

re.findall搜索字符串,以列表形式返回所有匹配结果

import re

html = '''<div id="songs-list">
    <h2 class="title">经典老歌</h2>
    <p class="introduction">
        经典老歌列表
    </p>
    <ul id="list" class="list-group">
        <li data-view="2">一路上有你</li>
        <li data-view="7">
            <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
        </li>
        <li data-view="4" class="active">
            <a href="/3.mp3" singer="齐秦">往事随风</a>
        </li>
        <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
        <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
        <li data-view="5">
            <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
        </li>
    </ul>
</div>'''

results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>', html, re.S)
print(results)
print(type(results))
for result in results:
    print(result)
    print(result[0], result[1], result[2])

re.sub

把模式匹配成功的子串替换成目标字符串

import re

content = "Extra things hello 123455 World_this is a regex Demo extra things"

content = re.sub('\d+','',content)
print(content) #Extra things hello  World_this is a regex Demo extra things

有的时候不想替换,而是补充内容,可以利用\1来表示匹配到的字符串

import re

content = "Extra things hello 123455 World_this is a regex Demo extra things"

content = re.sub('(\d+)',r'\1 7890',content) #不能少了r
print(content) #Extra things hello 123455 7890 World_this is a regex Demo extra things

re.compile

将正则表达式编译成正则表达式对象,方便复用正则表达式

import re
content= """hello 12345 world_this
123 fan
"""

pattern =re.compile("hello.*fan",re.S)

result = re.match(pattern,content)
print(result)
print(result.group())

豆瓣书籍实战

目标链接:https://book.douban.com
目标:获取该网页的所有书籍的封面图片,并以书籍的名字保存图片

#encoding=utf-8

import requests
import re
import os

root = "./douban"

url = "https://book.douban.com"

header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
}

response = requests.get(url, headers=header) #得加header
# print(response.status_code)
# print(response.content.decode("utf-8"))
content = response.content.decode("utf-8")

#把div、a这些标签也写出来是为了更准确的定位,不然假如网页有不需要的img,则会把不需要的img一直到需要的img那一大段都截下来
#比如func = '<img src.*?(http.*?jpg).*?alt="(.*?)".*?>'
#content = "<img src="http**没有用.jpg">\n<div class="cover">\n<a hrep=***>\n<img src="http://有用的.jpg" alt="xxx">"
#截取出来的是  http**没有用.jpg">\n<div class="cover">\n<a hrep=***>\n<img src="http://有用的.jpg
func = '<div class="cover">\s*?<a .*?>\s*?<img src.*?(http.*?jpg).*?alt="(.*?)".*?>'

results = re.findall(func, content, re.S)

for result in results:
    print(result[0])
    print(result[1])
    path = os.path.join(root, result[1] + '.jpg')
    with open(path, 'wb') as f:
        response = requests.get(result[0], headers=header)
        f.write(response.content)

结果:
在这里插入图片描述
注意:在Ubuntu上,有的图片打不开,因为下载的图片原本应该是png的格式,但他直接改后缀成jpg了,在Windows上能看(不是我改的,而是网页提供的就是改过了的)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值