python网络爬虫笔记-re正则表达式

正则表达式

什么是正则表达式? 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑

所以正则表达式并非某一编程语言所特有,它在不同的环境下有不同的用法。比如说shell脚本的awk命令或者是#、%分割字符等等,但是不管哪种方法,正则表达式都为我们解决文本匹配问题提供了巨大的帮助。

而应用到爬虫里,当我们获取了目标网页的html之后,往往需要批量地匹配目标字符串,这些字符串或许是网址,或许是网页的关键信息,但是指望人工手动地去复制粘帖是不现实的,因此就需要正则表达式去匹配和输出。


下面实例均为python脚本

转义字符、限定符、特殊字符

\w匹配字母数字及下划线
\W匹配非字母数字及下划线
\s匹配任意空白字符,等价于[\t\n\r\f]
\S匹配任意非空字符
\d匹配任意数字,等价于[0-9]
\D匹配任意非数字
\A匹配字符串开始
\Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
\z匹配字符串结束
\G匹配最后匹配完成的位置
\n匹配一个换行符
\t匹配一个制表符
^匹配字符串的开头
$匹配字符串的末尾
.匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
[…]用来表示一组字符,单独列出:[amk]匹配"a","m"或"k"
[^…]不在[]中的字符:[^abc]匹配除了a,b,c之外的字符
*匹配0个或多个的表达式
+匹配1个或多个的表达式
?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
{n}精确匹配n个前面表达式
{n,m}匹配n到m次由前面的正则表达式定义的片段,贪婪方式
a|b匹配a或b
()匹配括号内的表达式,也表示一个组

re.match

总是会从第一个字符开始匹配

import re
content = "Hello 123 4567 World_This is a Regex Demo"
result = re.match("^Hello\s\d{3}\s\d{4}\s\w{10}.*Demo$",content)
#参照上表,'^'匹配开头,'$'匹配结尾
#接受三个参数,正则表达式、目标字符串、匹配模式(可选)
print(len(content))
print(result)  ##打印结果,为对象
print(result.group())  #返回匹配结果,若有多个结果,使用索引获取
print(result.span()) #返回匹配长度

输出

41
<re.Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
Hello 123 4567 World_This is a Regex Demo
(0, 41) 

泛匹配

result = re.match("^Hello.*Demo$",content) 
#与上例匹配结果相同
#这里使用'.*'来匹配'Hello'和'Demo'中的所有内容

目标匹配

import re
content = "Hello 1234567 World_This is a Regex Demo"
result = re.match("^Hello\s(\d+)\s\w.*Demo$",content) 
#指定端点,左边\s,右边\s
print(result.group())
print(result.group(1))  
#若表达式里存在括号,则可以给group传递参数来提取第n个括号内的内容,
#括号也可以指定为一个整体进行操作

输出

Hello 1234567 World_This is a Regex Demo
1234567

贪婪匹配与非贪婪匹配

import re
content = "Hello 1234567 World_This is a Regex Demo"
result = re.match("^He.*(\d+).*Demo$",content) 
#贪婪匹配,'.*'匹配尽可能多的字符,因此(\d+)实际上只匹配到了1个数字
print(result.group())
print(result.group(1))
result1 = re.match("^He.*?(\d+).*Demo$",content) 
#'?'指定非贪婪匹配,匹配尽可能少的字符,指有或者没有
print(result1.group())
print(result1.group(1))

输出

Hello 1234567 World_This is a Regex Demo
7
Hello 1234567 World_This is a Regex Demo
1234567

匹配模式

import re
content = '''Hello 1234567 World_This \n is a Regex Demo'''
result = re.match("^He.*?(\d+).*?Demo$",content)
result1 = re.match("^He.*?(\d+).*?Demo$",content,re.S) 
#由于content中存在换行符,'\'正常情况下无法匹配,返回None
#指定匹配模式(re.S)后,'\'就可以匹配任意包括换行符的字符
print(result)
print(result1)

输出

None
<_sre.SRE_Match object; span=(0, 41), match='Hello 1234567 World_This \nis a Regex Demo'>

转义

import re
content = "price is $5.00"
#如果目标字符串中存在上表中的特殊字符串,则需要转义符'\'来进行特殊处理
result = re.match("price is \$5\.00", content)
#特殊字符采用换行符'\'
print(result.group())

输出

price is $5.00

re.match方法有一个缺陷,就是它只能够从第一个字符开始匹配,如果我们所提供的正则表达式和目标字符串的第一个字符不同,则匹配结果会返回None

比如

import re
content = "price is $5.00"
result = re.match("rice is \$5\.00", content)
#此时第一个字符不同
print(result)

输出

None

re.search

而re.search就是解决这个问题的方法

它会扫描整个字符串,返回第一个成功匹配的字符串

import re
content = "Extra stings Hello 1234567 World_This is a Regex Demo Extra stings"
result = re.match("Hello.*?(\d+).*?Demo",content) #第一个字符不匹配,返回None
result1 = re.search("Hello.*?(\d+).*?Demo",content)
print(result)
print(result1)

输出

None
<_sre.SRE_Match object; span=(13, 53), match='Hello 1234567 World_This is a Regex Demo'>

re.findall

原理类似,扫描整个字符串,返回符合条件的所有结果,返回结果可以用索引访问

re.sub

替换字符串中每一个匹配的子串后返回替换后的字符串

import re
content = "Extra stings Hello 1234567 World_This is a Regex Demo Extra stings"
result = re.sub("\d+","Re",content) #替换数字为'Re'
print(result)

输出

Extra stings Hello Re World_This is a Regex Demo Extra stings

或者想要在指定字符串后添加新的元素

import re
content = "Extra stings Hello 1234567 World_This is a Regex Demo Extra stings"
result = re.sub("(\d+)", r"\1 8910",content)  
#‘\1’ 代表取所要替换的字符的第一个组合,r代表使其成为原生字符,
#r"\1 8910"替换为"\\1 8910"效果相同
print(result)

输出

Extra stings Hello 1234567 8910 World_This is a Regex Demo Extra stings

re.compile

将正则字符串编译成正则表达式对象,以便复用

import re
content = '''Hello 1234567 World_This
is a Regex Demo'''
pattern = re.compile("Hello.*Demo",re.S)
result = re.match(pattern,content)
print(result.group())

输出

Hello 1234567 World_This
is a Regex Demo

实例演示

import re
import requests
content = requests.get("https://book.douban.com/").text
pattern = re.compile('<div class="title">.*?href="(.*?)".*?title="(.*?)"',re.S)
results = re.findall(pattern,content)
for result in results:
	url,name = result
	print(url,name) #运行时间较长
https://book.douban.com/subject/34778578/?icn=index-latestbook-subject 恐妻家
https://book.douban.com/subject/30432492/?icn=index-latestbook-subject 旅行
https://book.douban.com/subject/34454619/?icn=index-latestbook-subject 遗忘,刑警
https://book.douban.com/subject/30264052/?icn=index-latestbook-subject 西方通史:从古代源头到20世纪
https://book.douban.com/subject/33420970/?icn=index-latestbook-subject 绕日飞行
https://book.douban.com/subject/30420913/?icn=index-latestbook-subject 美国官僚体制
https://book.douban.com/subject/30435811/?icn=index-latestbook-subject 没有男人的公寓
https://book.douban.com/subject/34442426/?icn=index-latestbook-subject 纳粹猎人

输出影评网址和电影名

最近学校的事情有点多、、更新应该不会很频繁,另外,ig、fpx冲冲冲!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值