Python逆向爬虫之正则表达式
字符串是我们在编程的时候很常用的一种数据类型,检查会在字符串里面查找一些内容,对于比较简单的查找,字符串里面就有一些内置的方法可以处理,对于比较复杂的字符串查找,或者是有一些内容经常变化的字符串里面查找,那么字符串内置的查找方法已经不好使了,满足不了我们的要求,这个时候就得用正则表达式了,正则表达式就是用来匹配一些比较复杂的字符串。
正则表达式在线练习工具:https://tool.oschina.net/regex
一、正则表达式
符号 |
解释 |
示例 |
说明 |
元字符 |
|
|
|
. |
匹配任意字符 |
b.t |
可以匹配bat / but / b#t / b1t等 |
\w |
匹配字母/数字/下划线 |
b\wt |
可以匹配bat / b1t / b_t等 但不能匹配b#t |
\s |
匹配空白字符(包括\r、\n、\t等) |
love\syou |
可以匹配love you |
\d |
匹配数字 |
\d\d |
可以匹配01 / 23 / 99等 |
\b |
匹配单词的边界 |
\bThe\b |
|
^ |
匹配字符串的开始 |
^The |
可以匹配The开头的字符串 |
$ |
匹配字符串的结束 |
.exe$ |
可以匹配.exe结尾的字符串 |
\W |
匹配非字母/数字/下划线 |
b\Wt |
可以匹配b#t / b@t等 但不能匹配but / b1t / b_t等 |
\S |
匹配非空白字符 |
love\Syou |
可以匹配love#you等 但不能匹配love you |
\D |
匹配非数字 |
\d\D |
可以匹配9a / 3# / 0F等 |
\B |
匹配非单词边界 |
\Bio\B |
|
[] |
匹配来自字符集的任意单一字符 |
[aeiou] |
可以匹配任一元音字母字符 |
[^] |
匹配不在字符集中的任意单一字符 |
[^aeiou] |
可以匹配任一非元音字母字符 |
* |
匹配0次或多次 |
\w* |
|
+ |
匹配1次或多次 |
\w+ |
|
? |
匹配0次或1次 |
\w? |
|
|
匹配N次 |
\w |
|
|
匹配至少M次 |
\w |
|
|
匹配至少M次至多N次 |
\w |
|
| |
分支 |
foo|bar |
可以匹配foo或者bar |
(?#) |
注释 |
|
|
(exp) |
匹配exp并捕获到自动命名的组中 |
|
|
(?exp) |
匹配exp并捕获到名为name的组中 |
|
|
(?:exp) |
匹配exp但是不捕获匹配的文本 |
|
|
(?=exp) |
匹配exp前面的位置 |
\b\w+(?=ing) |
可以匹配I'm dancing中的danc |
(?<=exp) |
匹配exp后面的位置 |
(?<=\bdanc)\w+\b |
可以匹配I love dancing and reading中的第一个ing |
(?!exp) |
匹配后面不是exp的位置 |
|
|
(?<!exp) |
匹配前面不是exp的位置 |
|
|
*? |
重复任意次,但尽可能少重复 |
a.b a.?b |
将正则表达式应用于aabab,前者会匹配整个字符串aabab,后者会匹配aab和ab两个字符串 |
+? |
重复1次或多次,但尽可能少重复 |
|
|
?? |
重复0次或1次,但尽可能少重复 |
|
|
{M,N}? |
重复M到N次,但尽可能少重复 |
|
|
{M,}? |
重复M次以上,但尽可能少重复 |
|
|
说明:如果需要匹配的字符是正则表达式中的特殊字符,那么可以使用\进行转义处理。
二、进行逐个详解
2.1 匹配多种可能
| |
| res = re.search(r'r[au]n','dog runs to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 7), match='run'> |
| |
| res = re.search(r'r[au]n','dog rans to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 7), match='ran'> |
| |
| |
| res = re.search(r'r[A-Z]n','dog rans to cat') |
| print(res) |
| >>> None |
| |
| res = re.search(r'r[a-z]n','dog rans to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 7), match='ran'> |
| |
| res = re.search(r'r[0-9]n','dog rans to cat') |
| print(res) |
| >>>None |
| |
| res = re.search(r'r[0-9a-z]n','dog rans to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 7), match='ran'> |
2.2 匹配数字 \d and \D
| |
| res = re.search(r'r\dn','run r9n') |
| print(res) |
| >>> <re.Match object; span=(4, 7), match='r9n'> |
| |
| |
| res = re.search(r'r\Dn','run r9n') |
| print(res) |
| >>> <re.Match object; span=(0, 3), match='run'> |
2.3 匹配空白 \s and \S
| |
| res = re.search(r'r\sn','r\nn r9n') |
| print(res) |
| >>> <re.Match object; span=(0, 3), match='r\nn'> |
| |
| |
| res = re.search(r'r\Sn','r\nn r9n') |
| print(res) |
| >>> <re.Match object; span=(4, 7), match='r9n'> |
2.4 匹配所有的字母和数字以及"_" \w and \W
| |
| res = re.search(r'r\wn','r\nn r9n') |
| print(res) |
| >>> <re.Match object; span=(4, 7), match='r9n'> |
| |
| |
| res = re.search(r'r\Wn','r\nn r9n') |
| print(res) |
| >>> <re.Match object; span=(0, 3), match='r\nn'> |
2.5 匹配空白字符 \b and \B
| |
| res = re.search(r'\bruns\b','dog runs to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 8), match='runs'> |
| res = re.search(r'\bruns\b','dogrunsto cat') |
| print(res) |
| >>> None |
| |
| |
| res = re.search(r'\Bruns\B','dog runs to cat') |
| print(res) |
| >>> None |
| res = re.search(r'\Bruns\B','dogrunsto cat') |
| print(res) |
| >>> <re.Match object; span=(5, 11), match=' runs '> |
2.6 匹配特殊字符 任意字符 \ and .
| |
| res = re.search(r'runs\\','dog runs\ to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 9), match='runs\\'> |
| |
| |
| res = re.search(r'r.ns','dog r;ns to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 8), match='r;ns'> |
| >res = re.search(r'r.ns','dog r\nns to cat') |
| print(res) |
| >>> None |
2.7 匹配句尾句首 $ and ^
| |
| res = re.search(r'^runs','dog runs to cat') |
| print(res) |
| >>> None |
| res = re.search(r'^dog','dog runs to cat') |
| print(res) |
| >>> <re.Match object; span=(0, 3), match='dog'> |
| |
| |
| res = re.search(r'runs$','dog runs to cat') |
| print(res) |
| >>> None |
| res = re.search(r'cat$','dog runs to cat') |
| print(res) |
| >>> <re.Match object; span=(12, 15), match='cat'> |
| |
2.8 是否匹配 ?
| |
| res = re.search(r'r(u)?ns','dog runs to cat') |
| print(res) |
| >>> <re.Match object; span=(4, 8), match='runs'> |
| |
| res = re.search(r'r(u)?ns','dog rns to cat') |
| print(res) |
| >>><re.Match object; span=(4, 7), match='rns'> |
| |
2.9 多行匹配 re.M
| |
| string = """ 123. |
| dog runs to cat. |
| You run to dog. |
| """ |
| res = re.search(r'^You',string) |
| print(res) |
| >>> None |
| |
| res = re.search(r'^You',string,re.M) |
| print(res) |
| >>> <re.Match object; span=(10, 13), match='run'> |
2.10 匹配零次或多次 *
| |
| res = re.search(r'ab*','a') |
| print(res) |
| >>> <re.Match object; span=(0, 1), match='a'> |
| |
| res = re.search(r'ab*','abbbbbbbbbb') |
| print(res) |
| >>> <re.Match object; span=(0, 11), match='abbbbbbbbbb'> |
2.11 匹配一次或多次 +
| |
| res = re.search(r'ab+','a') |
| print(res) |
| >>> None |
| |
| res = re.search(r'ab+','abbbbbbbbbb') |
| print(res) |
| >>> <re.Match object; span=(0, 11), match='abbbbbbbbbb'> |
2.12 可选次数匹配
| |
| res = re.search(r'ab{1,10}','a') |
| print(res) |
| >>> None |
| |
| res = re.search(r'ab{1,10}','abbbbbbbbbb') |
| print(res) |
| >>> <re.Match object; span=(0, 11), match='abbbbbbbbbb'> |
2.13 寻找所有匹配 findall
| |
| res = re.findall(r'r[ua]n','run ran ren') |
| print(res) |
| >>> ['run', 'ran'] |
| |
| |
| res = re.findall(r'(run|ran)','run ran ren') |
| print(res) |
| >>> ['run', 'ran'] |
2.14 替换匹配内容 sub
| |
| res = re.sub(r'runs','catches','dog runs to cat') |
| print(res) |
| >>> dog catches to cat |
| |
2.15 分裂内容 split
| |
| res = re.sub(r'runs','catches','dog runs to cat') |
| print(res) |
| >>> dog catches to cat |
2.16 包装正则表达式 compile
| |
| compile_re = re.compile(r'r[ua]n') |
| res = compile_re.findall('run ran ren') |
| print(res) |
| >>> ['run', 'ran'] |
| |
| |
| compile_re = re.compile(r'(?P<name>r[ua]n?)') |
| res = compile_re.finditer('run ran ren') |
| for i in res: |
| print(i.groupdict()) |
2.17 re.S
注意:不使用re.S时,则只在每一行内进行匹配,如果存在一行没有,就换下一行重新开始,使用re.S 参数以后,正则表达式会将这个字符串看做整体,在整体中进行匹配,一般在爬虫项目中会经常用到。
| import re |
| a = """sdfkhellolsdlfsdfiooefo:877898989 |
| |
| worldafdsf""" |
| b = re.findall('hello(.*?)world',a) |
| c = re.findall('hello(.*?)world',a,re.S) |
| print ('b is ' , b) |
| print ('c is ' , c) |
三、Python 爬取豆瓣电影排行榜
| import re |
| import requests |
| |
| def main(): |
| |
| head = { |
| "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" |
| } |
| |
| baseurl = "https://movie.douban.com/top250?start=" |
| |
| res = requests.get(url=baseurl, headers=head) |
| |
| connect = res.text |
| |
| obj = re.compile( |
| r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)</span>.*?<p class="">.*?<br>(?P<year>.*?) .*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?<span>(?P<num>.*?)人评价</span>', re.S) |
| |
| result = obj.finditer(connect) |
| |
| for it in result: |
| print(it.groupdict()) |
| |
| if __name__ == '__main__': |
| |
| main() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律