限定符
?代表问号前面的字符出现0次或者1次
* 代表*前面的字符出现0次或者多次
+ 代表+前面的字符出现1次或者多次
{n} 代表{}前面的字符出现了n次
{n,} 代表{}前面的字符出现了n次或多次
{n,m} 代表{}前面的字符出现了n到m次
() 可以匹配多个字符的重复
运算符
| 或运算符
案例: a (cat|dog) 匹配了 a cat 或者a dog
字符类
[] 方括号的内容代表要求匹配的字符只能取自于它们,我们可以在[]中指定字符的范围
例如:[a-z]代表所有的小写英文字符 ;[A-Z]代表所有的大写英文字符 ;[0-9]代表所有的数字。
反义
^
尖号代表要求匹配除了尖号后面列出的以外的字符
例如:[^a-z] 非小写字母
\D 代表非数字字符
\W 代表非单词字符
\S 代表非空白符
元字符
\d 代表数字字符
\w 代表单词字符;
\s 代表空白符,包含tab字符以及换行符
\b 匹配单词的开始或结束
. 代表任意字符(不包含换行符)
^ 匹配行首
$匹配行尾
转义字符
如果你想查找元字符本身的话,比如你查找.,或者*,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使用\来取消这些字符的特殊意义。因此,你应该使用\.和\*。
贪婪与懒惰匹配
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。
以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。
有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:
a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。
案例
爬取网页中的岗位信息
1. content = ''' 2. <div class="el"> 3. <p class="t1"> 4. <span> 5. <a>Python开发工程师</a> 6. </span> 7. </p> 8. <span class="t2">南京</span> 9. <span class="t3">1.5-2万/月</span> 10. </div> 11. <div class="el"> 12. <p class="t1"> 13. <span> 14. <a>java开发工程师</a> 15. </span> 16. </p> 17. <span class="t2">苏州</span> 18. <span class="t3">1.5-2/月</span> 19. </div> 20. ''' 21. 22. import re 23. p = re.compile(r'class=\"t1\">.*?<a>(.*?)</a>', re.DOTALL) 24. for one in p.findall(content): 25. print(one)
正则表达式为:
class=\"t1\">.*?<a>(.*?)</a>
正常的情况下,正则表达式里的句号(.)是匹配任何除换行符之外的字符。但是有时你也想要求它连换行符也匹配,可以用DOTALL标志,就可以让它匹配所有字符,不再排除换行符了,这样 .*?就匹配了文本中的换行符和“span”相关的字符了
输出结果
Python开发工程师
java开发工程师