一、Requests聚焦批量爬取图片
import re
import requests
import os
import timeurl = 'https://www.douban.com/'
userAgent = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0'}#获取整个浏览页面
page_text = requests.get(url=url,headers=userAgent).text#提取图片链接,分两次特征提取并合并至一个列表中
ex1 = re.compile(r'<img src="(.*?)" data-origin="')
ex2 = re.compile(r'" data-origin="(.*?)" alt.*?')
img_data1 = ex1.findall(page_text)
img_data2 = ex2.findall(page_text)
#合并至一个列表中
for one in img_data2:img_data1.append(one)#设定图片存储路径,判断路径是否存在,不存在则自动创建
if not os.path.exists('E:/Reptile/douban'):os.mkdir('E:/Reptile/douban')#循环向列表中的图片链接发起请求并保存图片
for two in img_data1:ex3 = re.compile(r'^http')#判断以http开头的链接才会发起get请求if ex3.findall(two):#设定图片保存名字,以时间戳方式进行命名photo_time1 = time.time() + 1photo_time2 = str(photo_time1)#通过图片所在链接发起get请求,并伪装UAphoto_data = requests.get(two,headers=userAgent).content#提取原图片的后缀名,采用字符串分割方式photo_extension = two.split('.')[-1]#设定图片的最终文件名photo_names = photo_time2 + '.' + photo_extension#设定图片的最终保存位置photo_path = 'E:/Reptile/douban/' + photo_names#保存图片with open(photo_path,'wb') as fp:fp.write(photo_data)print(photo_names,"下载成功!!!")
print('爬取结束,over!!!')
二、批量爬取图片方式正则匹配解析
采用正则表达式,提取页面中所包含的所有图片链接,正则表达式采用re库,解析如下:
1、必备模块与基本调用
import re# 1. 一次性匹配
m = re.search(r'(\d{4})-(\d{2})-(\d{2})', '2025-08-05')
if m:print(m.group(0)) # 2025-08-05print(m.group(1)) # 2025# 2. 预编译(推荐,速度快、可复用)
pat = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})')
m = pat.search('2025-08-05')
print(m.groupdict()) # {'year': '2025', 'month': '08', 'day': '05'}# 3. 全局查找
pat.findall('2025-08-05, 2026-12-30') # [('2025','08','05'), ('2026','12','30')]# 4. 全局替换
new = pat.sub(r'\2/\3/\1', '2025-08-05') # 08/05/2025
2、常见函数对照表
需求 | 一次性 | 预编译对象方法 |
---|---|---|
搜索第一个匹配 | re.search() | p.search() |
从头开始必须完全匹配 | re.match() | p.match() |
找到所有匹配(列表/迭代器) | re.findall() | p.findall() |
找到所有 match 对象 | re.finditer() | p.finditer() |
拆分字符串 | re.split() | p.split() |
替换 | re.sub() / re.subn() | p.sub() / p.subn() |
3、重点语法速记 |
1.基本元字符
. 任意字符,^ 开头,$ 结尾,* 0 次或多次,+ 1 次或多次,? 0/1 次或“非贪婪”。
2.字符集与反义
[abc]、[^abc]、\d = [0-9]、\w = [A-Za-z0-9_]、\s 空白。
3.分组 / 捕获
(...) 捕获,(?:...) 不捕获,(?P<name>...) 命名组。
4.非贪婪
在 *, +, ?, {m,n} 后面加 ? 即可。
5.断言(零宽)
(?=...) 正向前瞻,(?!...) 负向前瞻,(?<=...) 正向后瞻,(?<!...) 负向后瞻。
6.修饰符(flag)
re.I 忽略大小写,re.M 多行,re.S 让 . 匹配换行,re.X 写注释。
4、场景示例
取 HTML 属性(之前你问的两个正则)
# 假设 html 是抓取到的网页源码
html = '<img src="a.jpg" data-origin="b.png" alt="pic">'ex1 = re.compile(r'<img src="(.*?)" data-origin="')
ex2 = re.compile(r'" data-origin="(.*?)" alt.*?')src = ex1.search(html).group(1) # a.jpg
data_origin = ex2.search(html).group(1) # b.png
更安全写法(防止属性顺序变化):
src = re.search(r'<img\b[^>]*\bsrc="([^"]*)"', html).group(1)
data_orig = re.search(r'<img\b[^>]*\bdata-origin="([^"]*)"', html).group(1)
校验手机号
phone_re = re.compile(r'^1[3-9]\d{9}$')
phone_re.fullmatch('13800138000') # <re.Match object>
解析日志
log = '2025-08-05 12:00:01 ERROR module.py:42 division by zero'
pattern = re.compile(r'(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) 'r'(?P<level>\w+) 'r'(?P<file>\S+):(?P<line>\d+) 'r'(?P<msg>.+)'
)
m = pattern.match(log)
print(m.groupdict())
# {'time': '2025-08-05 12:00:01',
# 'level': 'ERROR',
# 'file': 'module.py',
# 'line': '42',
# 'msg': 'division by zero'}
替换文本中的邮箱为 [EMAIL]
re.sub(r'\b[\w.-]+@[\w.-]+\.\w+\b', '[EMAIL]', 'Contact: foo@bar.com')
# 'Contact: [EMAIL]'
切割不规则空白
re.split(r'\s+', 'a b\tc\n d') # ['a', 'b', 'c', 'd']
多行模式提取代码块
code = '''
```python
print('hi')
5、调试技巧
-
re.DEBUG
看编译过程:
re.compile(r'(a|b)*c', re.DEBUG)
-
在线可视化:regex101.com(选 Python flavor)
-
在 Python 中打印 pattern:
print(pat.pattern)
查看原始表达式。
6. 常见坑提醒
-
贪婪 vs 非贪婪:
.*?
只在需要时才加,否则可能匹配过度或性能差。 -
反斜杠地狱:
在普通字符串里需写\\d
,推荐用原始字符串r'\d'
。 -
多行字符串用
re.S
:
否则.
匹配不到换行。 -
大文本慎用
findall()
,用finditer()
迭代器更省内存。
7. 一句话总结
“先 import re,再 compile,search/match 取 group,findall 得列表,sub 做替换,flag 调行为。”
—— 背住这 30 秒口诀,90 % 的正则问题都能快速拆掉。