正则表达式是一种用于匹配字符串的模式
1.匹配字符串的模式
在爬虫项目中,想要获取特定的信息,需要精确定位其地址。
这个过程需要进行复杂的文本匹配操作。
以下是一些常用字符的用法:
.
:匹配任意单个字符(换行符除外)。
*
:匹配前面的元素零次或多次。
+
:匹配前面的元素一次或多次。
?
:匹配前面的元素零次或一次。
^
:匹配输入字符串的开始位置。
$
:匹配输入字符串的结束位置。
[]
:匹配方括号内的任意字符。
|
:逻辑或操作符,匹配两个(或多个)选项中的一个。
\s
:匹配任意的空白符(包括空格、制表符、换行符等)。
\S
:匹配任意的非空白符。
\d
:匹配任意数字,等同于 [0-9]
。
\w
:匹配任意字母数字字符,包括下划线。
\b
:匹配一个单词字符与一个非单词字符之间的边界。
2.正则表达式
1.re模块-compile测试
#导入re
import re
pattern = re.compile(r'\d+')
print(pattern)
2. match方法使用
match方法用于查找字符串的头部(也可以指定起始位置),找到了一个匹配的结果就返回。
m2中两个参数:('balabala',3,6)
3:匹配的起始位置,下标数包含
6:匹配的结束位置,下标数不包含
import re#导入re模块
pattern = re.compile(r"\d+")#设置正则表达式规则
m1 = pattern.match('one123two456three789')#匹配的目标文本,没有匹配到则终止匹配,由于o字母不是数字,因此无匹配数据
print(m1)
m2 = pattern.match('one123two456three789',3,6)
print(m2.group())#通过group查看匹配的数据
输出结果: None 123
3.search方法使用
search 方法用于查找字符串的任何位置。
它找到了一个匹配的结果就返回,不是查找所有匹配的结果。
import re
pattern = re.compile(r"\d+")
#search字符串中任意位置匹配,如果匹配失败则结束匹配
m1 = pattern.search("one123two456three789")
print(m1.group())
输出结果:123
4.findall方法使用
findall 以列表形式返回全部能匹配的子串。如果没有匹配,则返回一个空列表e。
只输出数字:
import re
pattern = re.compile(r"\d+")
#findall 方法用于搜索整个字符串,获得所有匹配的结果
result1 = pattern.findall('hello 123 world 456')
print(result1)
result2 = pattern.findall("one123two456three789")
print(result2)
输出结果:
['123', '456']
['123', '456', '789']
只输出字母:
import re
pattern = re.compile(r"\D+")
result1 = pattern.findall('hello 123 world 456')
print(result1)
result2 = pattern.findall("one123two456three789")
print(result2)
输出结果:
['hello ', ' world ']
['one', 'two', 'three']
5.split方法使用
split方法通常用于处理字符串数据
ta将字符串分割成子字符串,并返回一个列表。
import re
string1 = 'a,b,c'#字符串中split的使用
print(string1.split(','))
输出结果:['a', 'b', 'c']
import re
string2 = 'a,b;;c d'#正则表达式中split方法的使用
pattern = re.compile(r"[\s\,\;]+")#按照逗号、分号、空格进行拆分
print(pattern.split(string2))
输出结果:['a', 'b', 'c', 'd']
6.sub方法使用
1.替换:
sub
方法用于替换字符串中的匹配项。
import re
string = '</h1><h1 class="test"> HelloWorld </h1><h1>'
pattern = re.compile(r'\d')
print(pattern.sub('2',string)) #参数1:替换后的值 参数2:源字符串
print(pattern.sub('2',string,2)) #参数3:替换几个
输出结果:
</h2><h2 class="test"> HelloWorld </h2><h2>
</h2><h2 class="test"> HelloWorld </h1><h1>
2.分组
L3:为组声明一个名字,可通过名字调用该组
import re
string= '<h1 class="test"> HelloWorld </h1>'
pattern = re.compile(r'<(.\d)\sclass="(?P<classname>.*?)">.*?</(.1)>')
print(pattern.search(string).group('classname'))
输出结果:test
在正则表达式中,分组是通过圆括号 ()
来划分的。
当L4中group(1)时,输出第一个组--->h1;
group(2)时,输出第一个组--->test; group(3)时,输出第一个组--->h1
3.传入:
import re
string= '<h1 class="test"> HelloWorld </h1>'
pattern = re.compile(r'<(.\d)\sclass="(?P<classname>.*?)">.*?</(.1)>')
def func(m):
return "after sub:" +m.group('classname')
#sub方法中传入函数:参数1:函数名 参数2:目标字符串
print(pattern.sub(func,string))
输出结果:after sub:test
7.贪婪匹配:
1.贪婪匹配:
import re
string= '<h1 class="test"> HelloWorld </h1>'
pattern = re.compile(r'<.\d\sclass=.*>')
print(pattern.search(string).group())
输出结果:<h1 class="test"> HelloWorld </h1>
2.非贪婪匹配:
import re
string= '<h1 class="test"> HelloWorld </h1>'
pattern = re.compile(r'<.\d\sclass=.*?>')
print(pattern.search(string).group())
输出结果:<h1 class="test">
8.范例测试:
http://www.cmpedu.com/so.htm?&KEY=python
爬取范例网站的数据:如书籍标题及作者
import requests
import re
def handle_detail_re(content): //检索出书名与作者
# print(content) #可检查是否爬到网页数据
# 返回页面中所有的书名
item_search = re.compile(r'ts_solgcont_title">.*?<div class="ts_solistMrbot">', re.S)
# re.S支持换行查找
# 按照规则到页面字符串中进行匹配
all_item = item_search.findall(content)
title_search = re.compile('target="_blank">(.*?)</a>')
author_search = re.compile('<p>(.*?)</p>')
for item in all_item:
print({
'title': title_search.search(item).group(1),
'author': author_search.search(item).group(1),
})
def main(): //爬出页面所有信息,未检索
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
}
booktype = ['java', 'Python', 'c']
for type in booktype:
url = 'http://www.cmpedu.com/so.htm?&KEY={}'.format(type)
response = requests.get(url=url, headers=header)
handle_detail_re(response.text)
if __name__ == '__main__':
main()