python 爬虫4 - re模块(正则表达式)

一、正则表达式

1.概念

正则表达式(Regular Expression,简称 Regex)是一种用于匹配字符串的模式。它可以用来搜索、替换、验证文本中的特定模式。Python 中的 re 模块提供了对正则表达式的支持。

2.语法

正则表达式的语法相对复杂,但理解其核心概念后,可以用非常简洁的方式来表达字符串匹配规则

符号 解释
. 匹配任意单个字符(除换行符)。
^ 匹配字符串的开头。
$ 匹配字符串的结尾。
* 匹配前面的字符 0 次或多次。
+ 匹配前面的字符 1 次或多次。
? 匹配前面的字符 0 次或 1 次。
{n} 匹配前面的字符恰好 n 次
{n,} 匹配前面的字符至少 n 次
{m,n} 匹配前面的字符至少 m 次,至多 n 次。
[] 匹配方括号中的任意一个字符(字符类)。
\ 转义字符,用于匹配一些特殊字符,例如 \. 匹配句点。
() 分组,标记一个子表达式。
| 或运算符,匹配左边或右边的模式

3.常用字符

表达式 说明
\d 匹配任何十进制数字,等价于 [0-9]
\D 匹配任何非数字字符。
\w 匹配任何字母数字字符,等价于 [a-zA-Z0-9_]
\W 匹配任何非字母数字字符。
\s 匹配任何空白字符(空格、制表符等)。
\S 匹配任何非空白字符。

二、re 模块

re模块使得python拥有全部的正则表达式功能。

1.作用

通过使用正则表达式,可以:

  • 测试字符串内的模式。
  • 替换文本。
  • 基于模式匹配从字符串中提取子字符串。

2.re 模块函数

(1)re.match( )

字符串开头进行匹配,如果匹配成功则返回 Match 对象,否则返回 None

语法:

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

参数:

参数 解释
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等

返回值:

匹配对象和方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
import re
 
line = "Cats are smarter than dogs"

# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
 
if matchObj:
   print ("matchObj.group() : ", matchObj.group())
   print ("matchObj.group(1) : ", matchObj.group(1))
   print ("matchObj.group(2) : ", matchObj.group(2))
else:
   print ("No match!!")

(2)re.search()

在整个字符串中搜索,返回第一个成功匹配Match 对象。

 语法:

re.search(pattern, string, flags=0)

参数:

参数 解释
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等

返回值:

匹配对象和方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
import re

result = re.search(r"world", "hello world")
if result:
    print(result.group())  # Output: world

match 和 rearch 的区别:

方法 区别
re.match 字符串开头进行匹配,如果开始不匹配,则匹配失败
re.rearch 匹配整个字符串,直到找到一个匹配

(3)re.findall()

返回字符串中所有非重叠的匹配项,结果为列表。

语法:

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

参数:

参数 解释
pattern 匹配的正则表达式
string 要匹配的字符串。
pos 可选参数,指定字符串的起始位置,默认为 0。
endpos  可选参数,指定字符串的结束位置,默认为字符串的长度。
注意: match 和 search 是匹配一次 findall 匹配所有。
import re

result = re.findall(r"\d+", "My numbers are 123 and 456")
print(result)  # Output: ['123', '456']

(4)re.finditer()

返回所有匹配项的迭代器,每个匹配项为一个 Match 对象,返回值为迭代器

语法:

re.finditer(pattern, string, flags=0)

参数:

参数 解释
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re

result = re.finditer(r"\d+", "My numbers are 123 and 456")
for match in result:
    print(match.group())  # Output: 123, 456

(5)re.sub()

替换匹配的字符串,可以控制替换次数。

语法:

re.sub(pattern, repl, string, count=0, flags=0)

参数:

参数 描述
pattern  正则中的模式字符串。
repl  替换的字符串,也可为一个函数。
string  要被查找替换的原始字符串。
count  模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags  编译时用的匹配模式,数字形式。

import re

result = re.sub(r"apple", "orange", "apple pie and apple juice")
print(result)  # Output: orange pie and orange juice

repl是一个函数:

#!/usr/bin/python
 
import re
 
# 将匹配的数字乘以 2
def double(matched):
    value = int(matched.group('value'))
    return str(value * 2)
 
s = 'A23G4HFD567'
print(re.sub('(?P\d+)', double, s))

(6)re.split()

使用匹配的子串来分割字符串,返回列表。

语法:

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

参数:

描述
pattern 匹配的正则表达式
string 要匹配的字符串。
maxsplit 分割次数,maxsplit=1 分割一次,默认为 0,不限制次数。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
result = re.split(r"\s+", "This is a test")
print(result)  # Output: ['This', 'is', 'a', 'test']

(7)re.compile()

语法:

re.compile(pattern[, flags])

参数:

参数 描述
pattern  一个字符串形式的正则表达式
flags  可选,表示匹配模式,比如忽略大小写,多行模式等

import re
pattern = re.compile(r'\d+')                    # 用于匹配至少一个数字
m = pattern.match('one12twothree34four')        # 查找头部,没有匹配
 print( m )
m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配
print( m )
m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
print( m )                                        # 返回一个 Match 对象
m.group(0)   # 可省略 0
m.start(0)   # 可省略 0
m.end(0)     # 可省略 0
m.span(0)    # 可省略 0
  • group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
  • span([group]) 方法返回 (start(group), end(group))。

3.标志位

标志 描述 示例
re.IGNORECASE 或 re.I 使匹配对大小写不敏感
import re
pattern = re.compile(r'apple', flags=re.IGNORECASE)
result = pattern.match('Apple')
print(result.group())  # 输出: 'Apple'
re.MULTILINE 或 re.M 多行匹配,影响 ^ 和 $,使它们匹配字符串的每一行的开头和结尾。
import re
pattern = re.compile(r'^\d+', flags=re.MULTILINE)
text = '123\n456\n789'
result = pattern.findall(text)
print(result)  # 输出: ['123', '456', '789']
re.DOTALL 或 re.S: 使 . 匹配包括换行符在内的任意字符。
import re
pattern = re.compile(r'a.b', flags=re.DOTALL)
result = pattern.match('a\nb')
print(result.group())  # 输出: 'a\nb'
re.ASCII 使 \w, \W, \b, \B, \d, \D, \s, \S 仅匹配 ASCII 字符
import re
pattern = re.compile(r'\w+', flags=re.ASCII)
result = pattern.match('Hello123')
print(result.group())  # 输出: 'Hello123'
re.VERBOSE 或 re.X 忽略空格和注释,可以更清晰地组织复杂的正则表达式。
import re
pattern = re.compile(r'''
    \d+  # 匹配数字
    [a-z]+  # 匹配小写字母
''', flags=re.VERBOSE)
result = pattern.match('123abc')
print(result.group())  # 输出: '123abc'

三、示例

1.提取电子邮件地址

import re

text = "Contact us at [email protected] or [email protected]"
emails = re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text)
print(emails)  # Output: ['[email protected]', '[email protected]']

2.替换电话号码

import re

text = "My old phone number was 123-456-7890."
new_text = re.sub(r"\d{3}-\d{3}-\d{4}", "XXX-XXX-XXXX", text)
print(new_text)  # Output: My old phone number was XXX-XXX-XXXX.

3.分割字符串

import re

text = "apple, orange; banana: grape"
fruits = re.split(r"[,;:\s]+", text)
print(fruits)  # Output: ['apple', 'orange', 'banana', 'grape']

4..* 贪婪匹配示例

print(re.findall("a.*d","a11b222d2d33"))

5..*? 非贪婪匹配示例

print(re.findall("a.*?d","a11b222d2d33"))

6.爬虫中的示例

获取豆瓣top250的电影信息

# 拿到页面源代码   requests
# 使用re模块提取
import requests
import re
import csv
url = "https://movie.douban.com/top250"
head = {
    "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
}

for j in range(0, 300, 25):
    param = {
        "start": j
    }
    res = requests.get(url, headers=head, params=param)
    pageContent = res.text

    # 解析数据
    obj = re.compile(r'
  • .*?
    .*?(?P.*?)' r'.*?

    .*?
    (?P.*?) .*' r'/ (?P.*?).*?' r' (?P.*?).*?' r'(?P.*?)' r'.*?(?P.*?)人评价.*?', re.S) # 打开文件,指定newline=''(对于Unix系统)或newline='\n'(对于Windows系统) f = open("豆瓣top250.csv","a+",encoding="utf-8", newline="\n") csvWriter = csv.writer(f) for i in obj.finditer(pageContent) : # print(i.group("moveName"),i.group("year").strip(),i.group("average"),i.group("num")) dict = i.groupdict() dict['year'] = dict['year'].strip() dict['num'] = dict['num'].strip() # dict['type'] = dict['type'].strip() print(dict) csvWriter.writerow(dict.values()) f.close()

  • 更多示例:

    Python之re模块详解 (超级无敌宇宙灭霸详细)_python re-CSDN博客

    你可能感兴趣的:(python,爬虫,正则表达式,python)