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

正则表达式

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

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

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

文章目录

  • 正则表达式
    • 转义字符、限定符、特殊字符
    • re.match
    • re.search
    • re.findall
    • re.sub
    • re.compile
    • 实例演示

下面实例均为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

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('
.*?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冲冲冲!

你可能感兴趣的:(网络爬虫笔记)