前言

趟过了网上各种大坑之后,我希望简单地写两个Python3的正则表达式小例子,区别几个函数的用法。

开始

由于扫描器需要,所以我想把一个网页上所有的URL提取出来。

首先,我下载一个网页的源代码,里面有一些URL:

可见,基本都是”<a href=”开头的,所以如果把以这个开头的都提取出来,获取URL就方便了。

于是我们采用正则表达式,这里我们使用两种方法进行正则匹配:

方法一 使用findall函数

1
2
3
4
5
6
7
8
9
10
11
import re
# 以utf-8编码,只读模式打开一个html源代码
file = open('view-source_www.sinomach.com.cn.html','r',encoding='utf-8')
# 使用findall函数来进行正则匹配
abc = re.findall(r'<a href=".*?"', file.read())
# 结果一个个打印出来
for i in range(len(abc)):
print(abc[i])

解释几点:

  1. 使用open函数后,打开的是一个文件对象,我们可以使用print(type(file))来看一下,运行后可看到:file为这种类型。
  2. file.read()后成为“str”类型。这里多说一句,file.read()后,指针就指到file对象的末尾了,你再在程序的其他位置使用file.read()就啥也读不出来了,所以建议及时把file.read()赋值给一个变量。
  3. 然后findall()函数的第一个参数,r'<a href=".*?"',这个是具体的正则表达式由r''引上的原因是r单引号中引上的东西是raw的:反斜杠就是反斜杠,不会转义,写啥就是啥。具体正则的含义就是,匹配以<a href="开头的,以"结尾的,中间按照正则规则.*?进行匹配的字符串。这里.*?是按照非贪婪模式匹配,如果想用贪婪模式的话,就是.*,这两个区别就是*匹配字符的多少,非贪婪就是尽量往少了匹配,贪婪就是尽量往多了匹配。
  4. file.read()是将这个文件变为“一个”字符串,他的类型是str;而file.readlines()是将文件按行取出,作为一个list,list的每一个元素都是str类型。
  5. re.findall()的结果也是一个list。

该程序最终输出结果:

方法二 使用search函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import re
# 显示一个对象的类型
def printType(a):
print(type(a))
# 打印出正则匹配结果
def printReg(pattern, string):
match = re.compile(pattern).search(string).group()
print(match)
# 正则表达式
pattern = '<a href=".*?"'
# 打开文件
file = open('view-source_www.sinomach.com.cn.html','r',encoding='utf-8')
# 按行读取成list
lists = file.readlines()
# 输出匹配结果
for i in range(len(lists)):
try:
printReg(pattern, lists[i])
except:
pass
#关闭文件
file.close()

几点说明:

  1. pattern里面写着正则表达式。
  2. 接下来三点主要围绕这句介绍:match = re.compile(pattern).search(string).group()
  3. 我们需要对正则表达式进行compile,生成一个模式对象,然后再使用该对象来匹配我们的目标string。
  4. 模式对象下有几个方法match(); fullmatch(); search() 。我一上午都在使用网上铺天盖地的match方法,结果查手册才知道,match只会从string的开头去匹配,如果要匹配string的任意位置,则需要使用search。另外,fullmatch要求更严,string得完全符合模式对象的正则匹配,才能有结果。具体文档如下:
  5. search过后,使用group进行结果输出。

该程序最终执行结果如下: