一、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 % 的正則問題都能快速拆掉。