初识正则表达式

正则表达式的探索与发现-爬虫项目系列博客

​ 因为要实现爬虫的功能,正则表达式是必须要掌握和简单应用的。那么这对于从来没看到过正则表达式的小白来说,它无疑是头痛的,因为它的长这个样子

1
2
var url_reg = /\/(\d{4})\/(\d{2})-(\d{2})\/(\d{7}).shtml/;
var regExp = /((\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2})|(\d{4}年\d{1,2}月\d{1,2}日)/
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
* 正则表达式:也叫规则表达式,按照一定的规则组成的一个表达式,这个表达式的作用主要是匹配字符串的,
* "我的电话:10086,他的电话:10010,你的电话:10000" 正则表达式,把这个字符串中的所有的数字找到
*
* 正则表达式的作用:匹配字符串的
*
* 在大多数编程语言中都可以使用
*
* 正则表达式的组成:是由元字符或者是限定符组成的一个式子
*
*
* 元字符:
*
* . 表示的是:除了\n以外的任意的一个字符 "fdsfs238"
*
* [] 表示的是:范围, [0-9] 表示的是0到9之间的任意的一个数字, "789" [0-9]
* [1-7] 表示的是1到7之间的任意的一个数字
* [a-z] 表示的是:所有的小写的字母中的任意的一个
* [A-Z] 表示的是:所有的大写的字母中的任意的一个
* [a-zA-Z] 表示的是:所有的字母的任意的一个
* [0-9a-zA-Z] 表示的是: 所有的数字或者是字母中的一个
* [] 另一个含义: 把正则表达式中元字符的意义干掉 [.] 就是一个.
* | 或者 [0-9]|[a-z] 表示的是要么是一个数字,要么是一个小写的字母
* () 分组 提升优先级 [0-9]|([a-z])|[A-Z]
* ([0-9])([1-5])([a-z]) 三组, 从最左边开始计算
* (()(()))有几个左括号就有几组
*
*
* 都是元字符,但是也可以叫限定符,下面的这些
* * 表示的是:前面的表达式出现了0次到多次
* [a-z][0-9]* 小写字母中的任意一个 后面是要么是没有数字的,要么是多个数字的
* "fdsfs3223323" [a-z][0-9]* 这是能匹配的,s3223323能够匹配
* 只要某一节字符串匹配,那么整个字符串都匹配
*
* + 表示的是:前面的表达式出现了1次到多次
* [a-z][9]+ 小写字母一个后面最少一个9,或者多个9
* "fesfewww9fefds" 这也是可以匹配的,w9 能够匹配
*
* ? 表示的是:前面的表达式出现了0次到1次,最少是0次,最多1次 ,另一个含义:阻止贪婪模式
* [4][a-z]? "1231234ij"
* 限定符:限定前面的表达式出现的次数
* {} 更加的明确前面的表达式出现的次数
* {0,} 表示的是前面的表达式出现了0次到多次,和 *一样的
* {1,} 表示的是前面的表达式出现了1次到多次,和 +一样的
* {0,1} 表示的是前面的表达式出现了0次到1次,和 ?一样的
* {5,10} 表示的是前面的表达式出现了5次到10次
* {4} 前面的表达式出现了4次
* {,10} 错误的========不能这么写
* ^ 表示的是以什么开始,或者是取非(取反)
* ^[0-9] 以数字开头
* ^[a-z] 以小写字母开始
* [^0-9] 取反,非数字
* [^a-z] 非小写字母
* [^0-9a-zA-Z_] _不是特舒符号
* $ 表示的是以什么结束 [0-9][a-z]$ 必须以小写字母结束
* ^[0-9][a-z]$ 相当于是严格模式 "3f2432e" "4f" ^限定开始,$限定结束 。有了^$,表示严格模式
* \d 数字中的任意一个,
* \D 非数字中的一个
* \s 空白符中的一个
* \S 非空白符
* \w 非特殊符号
* \W 特殊符号
* \b 单词的边界
* "what are you no sha lei"
*
*
*
*
*
*
* . 除了\n以外的任意一个单个字符
* [] 范围
* () 分组,提升优先级
* | 或者
* * 0-多次
* + 1-多次
* ? 0-1次
* {0,} 和*一样
* {1,} 和+
* {0,1} 和?
*
* \d 数字中的一个
* \D 非数字
* \s 空白符
* \S 非空白符
* \W 特殊符号
* \w 非特殊符号 _ 等价于[A-Za-z0-9 ]
* ^ 取反,以什么开始
* $ 以什么结束
* \b 单词边界
*/


/*
*
*
* 写正则表达式,根据字符串来写正则表达式进行匹配
*
* 经验: 1.找规律 2.不要追求完美
*
*
* 身份证的正则表达式
*
* 15位或者18位
* ([1-9][0-9]{14})|([1-9][0-9]{16}[0-9xX])
*
*
* ([1-9][0-9]{14})([0-9]{2}[0-9xX])?//问号表示前面的()有没有出现过,0或1次
*
*
* 练习:
* 1.座机号码的正则表达式
* 010-19876754
* 0431-87123490
*
* [0-9]{3,4}[-][0-9]{8}
* \d{3,4}[-]\d{8}
*
* \d{3,4}[-][0-9]{8} 这种方式不工整
*
*
* 2.qq号码的正则表达式
*
* [1-9][0-9]{4,10}
* \d{5,11}
*
* 3.手机号码的正则表达式
*
* 130 131 132 133 134 135 136 137 138 139
* 143 147
* 150 151 152 153 154 155 156 157 158 159
* 170 171 173 176 177
* 180 181 182 183 184 185 186 187 188 189
* ([1][358][0-9][0-9]{8})|([1][4][37][0-9]{8})|([1][7][01367][0-9]{8})
* \d{11}
*
*
* 邮箱的正则表达式,必须要记住的
*
* sd2113_3.-fd@itcast.com.cn
*
*
*
* [0-9a-zA-Z_.-]+[@][0-9a-zA-Z_.-]+([.][a-zA-Z]+){1,2}有可能是.com 也有可能是.com.cn
* + 表示一次到多次
*
*
*
*[0-9a-zA-Z_.]+[@][0-9a-zA-Z._]+([.][a-zA-Z]+){1,2}
*
*
*
*
*
* */

翻阅了一下犀牛书,有看了几个网上的教学视频,总算有了点概念,接下来我先把书本的内容贴上来

示例

示例

示例

示例

示例

示例

示例

先来看看第一个正则表达式

我们要知道,正则表达式不是我们凭空捏造出来的,而是在我们找到目标网页后,根据源代码中子内容的编写规律对应着写下来的,老师的代码爬取的式中国新闻网的内容,所以我们先打开中国新闻网的源代码页面。

示例

我们看到了这一行行的新闻标题,心想:这不就是我想要的嘛!!!怎么才能获得呢!??

不慌,按F12进入坦克进入DevTools

示例

那么如何才能定位呢?我们点击左上方的那个小按钮,对,就是那个有鼠标一样的小按钮

新世界开启

我们只要把我们的鼠标移动到任何一处,图片,链接,窗口等等,devtools中就会自动显示对应的链接,太可了!

示例

这样看了几个新闻链接后,我们不难发现

http://www.chinanews.com/gn/2020/04-20/9162393.shtml

http://www.chinanews.com/gj/2020/04-20/9162621.shtml

http://www.chinanews.com/cj/2020/04-20/9162059.shtml

好吧事不过三,我们发现这三个基本上具有相同的格式,只是中间的gn/gj/cn不同,日期可能不同和后边的编码不同,好,那么我们需要用正则表达式去匹配前面的www.chinanews.com嘛?其实并不需要,我们只需要找到这类链接的不同之处即可,否则就是浪费时间。那么再来分析一下我们的正则表达式

1
2
3
4
5
6
7
8
9
10
11
12
var url_reg = /\/(\d{4})\/(\d{2})-(\d{2})\/(\d{7}).shtml/;
// 首尾两个/ 是在Js中的声明正则表达式的固定用法,可以略去
// 1.\ 是用来转义的 \/匹配的是/
// 2.(\d{4})分成两个部分 :\d 代表数字 {4}代表出现字数,这里很明显我们要匹配2020
// 3.\/ 又是匹配/
// 4.(\d{2}) 同理,这次我们来匹配月份,04
// 5. - 其实就是匹配04-20中的-
// 6. (\d{2})匹配的是日期
// 7. \/ 又是匹配/
// 8.(\d{7}) 匹配编号,不同网页都有独特的编号
// 9 .shitml就是匹配 .shtml
// 值得注意的是,在这里.的意思是非\n的任意字符,包括了. 如果我们只要匹配 . 需要写[.]

分析完毕,我们来测试一下他的具体性能吧

https://c.runoob.com/front-end/854 这是一个在线测试正则表达式的网站,在写爬虫的时候先跑一下看看到底能不能过滤出有效的信息来

示例

可以看到这个正则表达式还是蛮厉害的,匹配到了200多条网页链接

再来看看第二个正则表达式

  • 我们来看看第二个正则表达式索要匹配的目标
1
var regExp = /((\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2})|(\d{4}年\d{1,2}月\d{1,2}日)/
1
2
3
1.<span id="pubtime_baidu">2020-04-21 08:53:46</span>
2. <div class="left-t">2020年04月21日 09:08 来源:法制日报<a href="#zw_cyhd" target="_self">
3.也有可能是这种 20-03-11
  • 其实我们要匹配的是这个出版时间,因为新闻嘛,总要讲究出版时间,所以我们要把他们都找出来
  • 因为出版时间有多种形式,有可能是19-08-19类的,有可能是2020/03/20,也有可能是2020年04月21日
  1. \d{4} 出现四个数字,也就是匹配年份
  2. \d{2} 出现两个数字,也是年份,只不过可能是19-xx-xx也有可能是 2019-xx-xx 所以在中间加个|表示或
  3. ( \-|\/|\.)其实是最难的,因为信息量很大,其实她想说的就是中间连字符的种类,可能是 -,可能是/,可能是 . 中间两个| 就是表示或者的意思
  4. \d{1,2}是匹配月份的,有可能是 1,也有可能是01
  5. \3比较难理解,这个\3其实就是匹配左边开始数第三个左括号的,也就是( \-|\/|\.),其实也是月和日之间的连接符
  6. \d{1,2}匹配的是日期
  7. 前面完全是数字字符来表达年月日,不过也存在2020年4月21日这种情况,那么我们如何解决?| 就完事了
  8. | 后面匹配的就是2020年4月21日这类的日期表达

下图就是\3 这类\后面加上数字的作用

最后来看看我的爬虫中的正则表达式

1
var regExp =/\/.\/.{8}\//

我要爬取的网站是 https://www.smzdm.com/ 什么值得买网站(为了找我喜欢的咖啡具)

然后我们来看看子网页

示例

按照上面的方法,我们来找找看子网页的url

https://post.smzdm.com/p/alpwnzve/

https://post.smzdm.com/p/awxqrv02/

规律是很明显的,我们需要匹配的就是 /p/alpwnzve/

  1. \/匹配的就是/
  2. .匹配的是任何字符(除了\n),当然也可以用[a-zA-Z]代替
  3. \/又匹配的是/
  4. .{8} 匹配的就是 连续八个字符,这里匹配的就是alpwnzve之类的
  5. \/匹配的还是/

来看看我们的匹配结果

示例

总结

写到这里,我们对正则表达式都有了一个基本的概念了,学会了正则表达式,在爬虫的项目中就解决了一个很大的难题。

-------------本文结束,感谢您的阅读-------------