Python 爬虫之正则表达

爬虫程序:请求网站并提取数据的自动化程序。

正则表达:Regular Expression(Regex)

  正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串。(摘自百度百科)其中元字符是指一个或一组用来代替一个或多个字符的字符,(这里表述不够准确,Python中并没有字符的概念,只有字符串(str)类型,正则表达也不是Python独有,莫得办法)。

Python正则表达必备:re库

  Signature: re.match(pattern, string, flags=0)

  Signature: re.sub(pattern, repl, string, count=0, flags=0)

  re.compile(pattern, flags=0)

1 import re
2 
3 #re.match()     # Try to apply the pattern at the start of the string, returning a Match object, or None if no match was found.
4 #re.search()    # Scan through string looking for a match to the pattern, returning a Match object, or None if no match was found.
5 #re.findall()   #Return a list of all non-overlapping matches in the string.
6 #re.sub()
7 # re.compile()  #Compile a regular expression pattern, returning a Pattern object.

  re库中常用的几个函数如上所示。注意各个函数的返回结果的类型。

  match()函数(Signature: re.match(pattern, string, flags=0))用于匹配一个目标,且只能从待匹配的字符串第一个字符开始匹配,字符串内部满足模式(pattern)的不会匹配成功。如下代码所示,字符串string中显然有‘BC’,却显示匹配失败,原因在于‘BC’并不在该字符串的开端。

 1 import re
 2 
 3 string = 'ABCDEF'
 4 
 5 result1 = re.match('AB',string)
 6 result2 = re.match('BC',string)
 7 if result1:
 8     print('AB匹配成功')
 9 else:
10     print('AB匹配失败')
11 if result2:
12     print('BC匹配成功')
13 else:
14     print('BC匹配失败')

AB匹配成功
BC匹配失败

  search()函数(Signature: re.search(pattern, string, flags=0)), 用于匹配满足pattern的字符串,返回第一个满足pattern 的字符串,查询即停止。测试代码如下,通过直接打印返回结果可从span参数得到匹配结果的位置。re.match 对象有内置函数 span()与 group()用于匹配结果的提取。span()函数用于得到匹配目标的位置,group()函数用于得到匹配结果。

 1 import re
 2 
 3 string = 'ABCDBCEF'
 4 
 5 result1 = re.search('AB',string)
 6 result2 = re.search('BC',string)
 7 
 8 print(result1)
 9 print(result2)
10 
11 print(result1.span())
12 print(result1.group())

---------------------------------------------------------------------------------------------------------------------
<re.Match object; span=(0, 2), match='AB'>
<re.Match object; span=(1, 3), match='BC'>
(0, 2)
AB

  re.findall()函数,(re.match(pattern, string, flags=0)),正则匹配中的大哥大。可以以列表的形式返回所有满足pattern的匹配结果,注意返回数据类型为列表。由于数据类型不再是 re.match 对象,因此不再支持 span()函数与 group()函数。

1 import re
2 
3 string = 'ABCDBCEBCF'
4 
5 result1 = re.findall('BC',string)
6 
7 print(result1)

-------------------------------------------------------------------
['BC', 'BC', 'BC']

  至此,已经有了正则匹配的能力(+_+),但是突然发现以上三个函数匹配的字符串并没有什么用,因为我们完全知道我们会得到什么字符串,并不神奇,这就关系到正则表达中的元字符的使用。

元字符:有哪些元字符

  (我与百度有合作,这里可以直接问百度。=_=!)

常用的元字符:

  ^:用于指定模式的开端

  [xyz] :[]用于匹配括号内的任意一个字符,注意 是一个,一个(醒目的红色,看到了吗),一个,字符

  [^xyz]:^用于取反,即用于匹配不包含 x,y,x的任意一个字符,一个,一个,一个。。。。(注意 区分 ^ 单独使用的情景)

  [a-z]:用于匹配a到 z的任意一个字符,一个

  [^a-z]:懒得解释

  +:匹配前面的子表达式,一次或多次,出现啦,多次,多个

  *:匹配前面的子表达式,零(大写的0)次或多次,注意与 + 的微妙区别(常用)

  ?:匹配前面的子表达式 零次 或一次(好烦啊,)

  {n}:确定匹配次数

  {n,}:至少出现次数为 n

  {n,m}:次数n-m次,注意‘,’后不能有空格

  ?:(是的还是我,不一样的烟火),当?在 限制符号之后时,用于非贪婪匹配。(常用)

  (pattern):匹配pattern并获取这以匹配   (常用)

  .:(能看到🐎,是个小点),用于匹配除换行符之外的任意字符

其他的真的可以问百度了。

 1 import re
 2 
 3 string = 'yijingbengpanle,qishishiyigejienengzhuyi,yijingbengpanle,qishishiyigejienengzhuyi.aaaaaaaaaaaaaaaaaaaaaaaaaa111'
 4 
 5 result1 = re.findall('^yijingbengpanle',string)  # ^ 用来确定从字符串开头 开始搜索,注意与下一行的区别
 6 print(result1)
 7 result1 = re.findall('yijingbengpanle',string)
 8 print(result1)
 9 
10 result2 = re.findall('[^a-z]',string)           # ^ 此时表示 非, 非a-z的字符
11 print(result2)
12 
13 result3 = re.findall('a+',string)              #匹配 一个或多个
14 print(result3)
15 result3 = re.findall('a*', string)              # 匹配 0 个 或多个 0个 a就是空字符串
16 print(result3)
17 
18 result3 = re.findall('a{3}', string)           #匹配三个a, 
19 print(result3)
20 
21 result3 = re.findall('a{3,}', string)           #匹配至少3 个a, 
22 print(result3)

--------------------------------------------------------------------------------------------------------------------------
['yijingbengpanle']
['yijingbengpanle', 'yijingbengpanle']
[',', ',', ',', '.', '1', '1', '1']
['a', 'a', 'aaaaaaaaaaaaaaaaaaaaaaaaaa']
['', '', '', '', '', '', '', '', '', '', '', 'a', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'a', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'aaaaaaaaaaaaaaaaaaaaaaaaaa', '', '', '', '']
['aaa', 'aaa', 'aaa', 'aaa', 'aaa', 'aaa', 'aaa', 'aaa']
['aaaaaaaaaaaaaaaaaaaaaaaaaa'

 

好像还是不够神奇。。。。。。。。。。。。。。。。。。。。。。。。。。。咋办。那是因为只是用了单独的元字符啊。

以下是我瞎写的HTML 伪代码,我们现在使用以上所学将,背诵的课文给提取出来。

 1 <!DOCTYPE HTML>
 2 <head>
 3     
 4 </head>
 5 
 6 <body>
 7 
 8     <t1>课文背诵</t1>
 9     <ul>
10         <li>下雪啦</li>
11         <li>下雪啦</li>
12         <li>雪地里来了一群小画家</li>
13         <li>我忘记啦</li>
14     </ul>
15 
16 </body>    
 1 import re 
 2 
 3 string = '''<!DOCTYPE HTML>
 4 <head>
 5     
 6 </head>
 7 
 8 <body> 
 9     <t1>课文背诵</t1>
10     <ul>
11         <li>下雪啦</li>
12         <li>下雪啦</li>
13         <li>雪地里来了一群小画家</li>
14         <li>我忘记啦</li>
15     </ul>
16 </body>'''
17 
18 results = re.findall('<li>(.*?)</li>',string, re.S)
19 print(results)
20 for r in results:
21     print(r)

--------------------------------------------------------------------------------------------------------
['下雪啦', '下雪啦', '雪地里来了一群小画家', '我忘记啦']
下雪啦
下雪啦
雪地里来了一群小画家
我忘记

这就是简单的爬虫,简不简单,神不神奇, 一行代码就能得到我们想要的数据。

以上代码findall()中的pattern为较常用的类型,用确定的字符来明确的暗示,我就是要 <li></li>之间的内容,再通过与其他泛匹配,与非贪婪匹配的结合,得到想要的结果。其中?非贪婪的重要性将会在下次探讨。

posted @ 2019-02-27 20:40  已经崩盘了  阅读(386)  评论(0编辑  收藏  举报