Chenerdy的幻想乡
首页文章归档风说书笔记说说友链项目相册关于
← 全部科目

Python爬虫

课次目录

00开篇01爬虫简介02Requests请求03正则04数据解析05selenium自动化06DrissionPage自动化
笔记/Python爬虫/第 03 课

Python爬虫笔记(03):正则

2026-09-13 19:00:00

03-正则

什么是正则

正则(Regular Expression)是一套文本匹配规则

比如网页里一堆文字,你想一次性提取所有手机号、所有链接、所有数字,用正则一行代码搞定

正则表达式通过 re 内置模块实现

常用正则表达式符号

  • \w 匹配字母数字及下划线
  • \W 匹配非字母数字下划线 [^0-9a-zA-Z]
  • \s 匹配任意空白字符, 等价于 [\t\n\r\f]
  • \S 匹配任意非空字符
  • \d 匹配任意数字 [0-9]
  • \D 匹配任意非数字
  • \n 匹配一个换行符
  • \t 匹配一个水平制表符: 通常用于在文本中插入固定间隔的空白
  • [] 匹配集合, 示例[a-z]
  • . 匹配除换行符(\n)以外的任意字符

元字符

^ 匹配字符串的开头或取反

实例
import restr =re.match(r'^abc', 'abcdef')  # 匹配成功(字符串以 'abc' 开头)str =re.match(r'^abc', '123abc')  # 匹配失败(字符串开头不是 'abc')​re.findall(r'[^0-9]', 'a1b2')  # 匹配所有非数字字符,结果 ['a', 'b']re.search(r'[^aeiou]', 'apple') # 匹配第一个非元音字母 'p'

$ 匹配字符串的末尾

实例
import rere.search(r'abc$', '123abc')    # 匹配成功(字符串以 'abc' 结尾)re.search(r'abc$', 'abc123')    # 匹配失败(字符串结尾不是 'abc')

管道符 |

实例
import rere.findall(r'cat|dog', 'I have a cat and a dog.')  # 匹配 ['cat', 'dog']

量词 {}

实例
# 控制前面的字符匹配重复的次数{m}:精确匹配 m次。{m,}:至少匹配 m次(无上限)。{m,n}:匹配 m到 n次(贪婪模式,尽可能多匹配)。​特殊写法- {1,}  最少匹配一次,最多无限制  		 可通过+代替- {0,}  有就匹配,不存在也不会报错  		可通过*代替- {0,1} 最少0次,最多1次  				可通过?代替

分组或捕获子串(提取数据)

实例
match = re.search(r'(\d{3})-(\d{4})', 'Phone: 123-4567')print(match.group(1))  # 输出 '123'(第一个分组)print(match.group(2))  # 输出 '4567'(第二个分组)

方法

Search匹配

用于查找整个字符串的任何位置, 只要匹配成功一个结果就返回,而不是查找所有匹配的结果,它的一般使用形式如下:

实例
re.search(pattern, string[, flags=0])
  • pattern:匹配的正则表达式
  • string: 要匹配的字符串
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
    • re.search(r'a.b', '"a\nb', re.S) 设置.可以匹配\n
    • re.S . 匹配换行符
    • re.M 多行模式
    • re.I 忽略大小写
  • 匹配成功 → 返回一个 Match对象(包含匹配信息)。 匹配失败 → 返回 None。

示例: r 用于简化正则表达式的编写。它的作用是避免 Python 字符串的转义规则与正则表达式的转义规则冲突

添加上r之后: 以正则规则为主

Python 实例
import restr = "phone: 123-4567"exg =  "23"newStr = re.search(exg, str)print(newStr.group())  # 获取匹配的数据 23​str = 'file txt'# 不加r时会出现问题, 程序不确定你是否需要进行转义; 在python正常的字符串中\代表转义,  在正则中\s表示匹配空字符串# 程序无法判断, 设置r之后以正则规则为主体newStr = re.search(r'file\stxt', str)  # 输出: 'file txt'print(newStr.group())​print(newStr.span())  # 查看匹配长度

match

用于查找字符串的头部,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果

re.match(pattern, string[, flags=0])

  • pattern:匹配的正则表达式
  • string: 要匹配的字符串
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
  • 匹配成功 → 返回一个 Match对象(包含匹配信息)。 匹配失败 → 返回 None。
Python 实例
# 只检查字符串的开头,即使中间或结尾有匹配内容也会失败      newStr = re.match('file', 'file^txt')  # 输出: fileprint(newStr.group())​print(newStr) # 返回的是一个匹配对象print(newStr.group())  # .group()获取匹配内容print(newStr.span())  # 查看匹配长度​# 只检查字符串的开头,即使中间或结尾有匹配内容也会失败      newStr = re.match('txt', 'file^txt')  # 输出: file^txtprint(newStr.group())

findall

用于查找整个字符串, 是一个高效提取所有匹配项的函数,它会扫描整个字符串并返回所有匹配的结果

re.findall(pattern, string[, flags=0])

  • pattern:匹配的正则表达式
  • string: 要匹配的字符串
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
  • 匹配成功 → 返回一个列表 。 匹配失败 → 返回 []。
Python 实例
import retext = "苹果 12元, 香蕉 5元, 橙子 8元"prices = re.findall(r'\d+元', text)print(prices)  # 输出: ['12元', '5元', '8元']  匹配多个

sub

用于替换字符串中所有匹配正则表达式的部分的函数

re.sub(pattern,replace,Sting)

  • pattern:要匹配的正则表达式(字符串或预编译对象)。
  • repl:替换的内容(可以是字符串或函数)。
  • string:被搜索的目标字符串。
  • count(可选):最多替换次数(默认 0表示全部替换)。
  • flags(可选):控制匹配行为的标志(如 re.I忽略大小写)
Python 实例
content = 'Extra stings Hello 1234567 World_This is 123 a Regex Demo Extra stings'content = re.sub(r'\d+', '666', content)print(content)  # 匹配到的数字全部会被替换​​content = 'Extra stings Hello 1234567 World_This is 123 a Regex Demo Extra stings'content = re.sub(r'\d+', '666', content, count=1)print(content)  # 只替换一次  

贪婪匹配

.* 会尽可能多地匹配任意字符(除换行符) 必须满足正则的整体需求

Python 实例
import re# 匹配尽可能多的字符   content = 'Hello 1234567 World_This is a Regex Demo'​result = re.match(r'^He.*(\d+)\s(.*)Demo$', content)  print(result)print(result.group(1)) # 7print(result.group(2)) # World_This is a Regex ​# 匹配整个字符串中的最后一个 content = 'Hello 1234567 World_This 8 is a Regex Demo'result = re.match(r'^He.*(\d+)\s.*Demo$', content)  print(result.group(1)) #  8# .* 匹配了 llo 1234567 World_This  因为后续还存在数字不影响整体

非贪婪匹配

.*?非贪婪匹配任意字符,遇到后续能匹配的内容就停止

Python 实例
import re# 匹配尽可能少的字符content = 'Hello 1234567 World_This is a Regex Demo'result = re.match(r'^He.*?(\d+).*Demo$', content)​print(result)print(result.group(1)) # 1234567

案例

  • Scrape电影: https://ssr1.scrape.center/

  • 豆瓣读书: https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8

  • 安装

    postman

    工具

    • 下载地址 https://www.postman.com/downloads/
Python 实例
# 获取Scrape电影网页,分页信息,以及每一项的详细信息import reimport requestsimport time​def spider():    res = requests.get(url, headers=headers)    if res.status_code == 200:        reg = '<a data-v-7f856186="" href="(.*?)" class="name">.*?<h2 data-v-7f856186="" class="m-b-sm">(.*?)</h2>'        data = re.findall(reg, res.text, re.S)        for item in data:            title_url = "https://ssr1.scrape.center/" + item[0]            title = item[1]            save_data(title_url, title)    pass​​def save_data(title_url,title):    r = requests.get(title_url, headers=headers)    if r.status_code == 200:        msg = re.findall(            r'<div data-v-63864230="" class="drama"><h3 data-v-63864230="">剧情简介</h3>.*?<p data-v-63864230="">(.*?)</p></div>',            r.text, re.S)        result = re.sub(r'\s+', ' ', msg[0])        with open("./01.txt", "a", encoding="utf-8") as f:            f.write(f'电影名称:{title}\n电影详情地址:{title_url}\n详情: {result}\n=================================\n\n')    pass​if __name__ == '__main__':    headers = {        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"    }    for i in range(1, 10):        url = f"https://ssr1.scrape.center/page/{i}"        spider()        time.sleep(2)
Python 实例
# 豆瓣读书设置翻页import reimport requests​def spider(url_info):    headers = {        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"    }    res = requests.get(url=url_info, headers=headers)    return res​def parse_data(res):    if res.status_code == 200:        data = re.findall(r'<h2 class="clearfix">.*?<a class="fleft" href="(.*?)">(.*?)</a>', res.text, re.S)        img = re.findall(r'<img class="subject-cover" align="left" src="(.*?)"/>', res.text, re.S)        for title,msg_img in zip(data,img):            title_msg = title[1]            title_Ulr = title[0]            saveData(title_msg,title_Ulr,msg_img)    passdef saveData(title_msg,title_Ulr,msg_img):    with open("./01.txt",'a',encoding='utf-8') as f:        f.write(f"{title_msg}   {title_Ulr}   {msg_img} \n=================\n")    # 存储图片    img_data = requests.get(msg_img, headers=headers).content    with open(f"./data/{title_msg}.jpg",'wb') as f:        f.write(img_data)    pass​if __name__ == '__main__':    headers = {        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"    }    for i in range(1,10):        print(f"第{i}页")        url_info = f"https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p={i}&updated_at="        result = spider(url_info)        parse_data(result)
← Python爬虫笔记(02):Requests请求Python爬虫笔记(04):数据解析 →

留言

目录