【Python爬虫】体验正则表达式的魅力

高效文本处理 - 1

原始文本

张伟 13497113770 \n
    王伟        18848534265    \n
   王芳   14055574177     \n
   李伟         18778349318    \n
 王秀英        17868446857 \n
  李秀英         13837762154   \n
  李娜         14251562703     \n
    张秀英         17734621265 \n
   刘伟  13758327790    \n
   张敏    14427564623  \n
 李静          13566484867     \n
    张丽       14344816212 \n
    王静     14051265514   \n
 王丽  15584308325    \n
   李强     17529536074   \n
  张静    17758961128  \n
  李敏       13266778621  \n
  王敏       13568158219    \n
  王磊        13725567211   \n
   李军         15897558217     \n
 刘洋 17672244822  \n

提取所有 11 位数字电话号码

\d{11}

结果:

13497113770
18848534265
14055574177
18778349318
17868446857
13837762154
14251562703
17734621265
13758327790
14427564623
13566484867
14344816212
14051265514
15584308325
17529536074
17758961128
13266778621
13568158219
13725567211
15897558217
17672244822

提取所有 18 或 13 开头的电话号码

(18|13)\d{9}

结果:

13497113770
18848534265
18778349318
13837762154
13758327790
13566484867
13266778621
13568158219
13725567211

提取所有“王”姓同学的名字

王\S*

结果:

王伟
王芳
王秀英
王静
王丽
王敏
王磊

提取所有“张”姓同学的电话号码

(张\S*) *(\d{11})  $1 的电话是 $2

结果:

张伟 的电话是 13497113770
张秀英 的电话是 17734621265
张敏 的电话是 14427564623
张丽 的电话是 14344816212
张静 的电话是 17758961128

重新排版

(\S*) *(\d{11})   $1 - $2

结果:

张伟 - 13497113770
王伟 - 18848534265
王芳 - 14055574177
李伟 - 18778349318
王秀英 - 17868446857
李秀英 - 13837762154
李娜 - 14251562703
张秀英 - 17734621265
刘伟 - 13758327790
张敏 - 14427564623
李静 - 13566484867
张丽 - 14344816212
王静 - 14051265514
王丽 - 15584308325
李强 - 17529536074
张静 - 17758961128
李敏 - 13266778621
王敏 - 13568158219
王磊 - 13725567211
李军 - 15897558217
刘洋 - 17672244822

几乎所有的 IDE、编程语言、稍高级文本编辑器都支持使用正则表达式进行以上提取和替换操作

高效文本处理 - 2

原始文本

 张伟      1993-2-5    
   王伟     1994.7.1   
  王芳     1997-6-28     李伟  1993-12-26  
    王秀英  1999-11-16        李秀英   1991年12月27日   
   李娜        1996.6.25    
  张秀英  1993.8.26     刘伟        1992-4-28    张敏    1998年5月24日    
  李静     1996年8月21日    张丽  1999年5月15日     王静        1994.6.2        王丽  1995-6-13   
    李强   1999.6.19      张静   1998年11月4日     李敏    1990.9.19    
  王敏  1999.12.8    王磊       1999.5.22     
 李军      1992-4-25   
    刘洋    1994.3.16 

提取所有日期

\d{4}\S\d{1,2}\S\d{1,2}\S?

结果:

1993-2-5
1994.7.1
1997-6-28
1993-12-26
1999-11-16
1991年12月27日
1996.6.25
1993.8.26
1992-4-28
1998年5月24日
1996年8月21日
1999年5月15日
1994.6.2
1995-6-13
1999.6.19
1998年11月4日
1990.9.19
1999.12.8
1999.5.22
1992-4-25
1994.3.16

提取所有 1996 年以前出生的学生

(\S*) *199[0-5]\S\d{1,2}\S\d{1,2}\S?

结果:

张伟      1993-2-5
王伟     1994.7.1
李伟  1993-12-26
李秀英   1991年12月27日
张秀英  1993.8.26
刘伟        1992-4-28
王静        1994.6.2
王丽  1995-6-13
李敏    1990.9.19
李军      1992-4-25
刘洋    1994.3.16

重新排版

(\S*) *(\d{4})\S(\d{1,2})\S(\d{1,2})\S?    $1: $2 年 $3 月 $4 日

结果:

张伟: 1993 年 2 月 5 日
王伟: 1994 年 7 月 1 日
王芳: 1997 年 6 月 28 日
李伟: 1993 年 12 月 26 日
王秀英: 1999 年 11 月 16 日
李秀英: 1991 年 12 月 27 日
李娜: 1996 年 6 月 25 日
张秀英: 1993 年 8 月 26 日
刘伟: 1992 年 4 月 28 日
张敏: 1998 年 5 月 24 日
李静: 1996 年 8 月 21 日
张丽: 1999 年 5 月 15 日
王静: 1994 年 6 月 2 日
王丽: 1995 年 6 月 13 日
李强: 1999 年 6 月 19 日
张静: 1998 年 11 月 4 日
李敏: 1990 年 9 月 19 日
王敏: 1999 年 12 月 8 日
王磊: 1999 年 5 月 22 日
李军: 1992 年 4 月 25 日
刘洋: 1994 年 3 月 16 日


把所有 1996 年以前出生的学生出生年份改为 1996

(\S*) *(199[0-5])\S(\d{1,2})\S(\d{1,2})\S?   $1: 1996 年 $3 月 $4 日

结果:

张伟: 1996 年 2 月 5 日
王伟: 1996 年 7 月 1 日
李伟: 1996 年 12 月 26 日
李秀英: 1996 年 12 月 27 日
张秀英: 1996 年 8 月 26 日
刘伟: 1996 年 4 月 28 日
王静: 1996 年 6 月 2 日
王丽: 1996 年 6 月 13 日
李敏: 1996 年 9 月 19 日
李军: 1996 年 4 月 25 日
刘洋: 1996 年 3 月 16 日

提取生日

(\S*) *(\d{4})\S(\d{1,2})\S(\d{1,2})\S?     $1的生日是$3月$4号🎂

结果:

张伟的生日是2月5号🎂
王伟的生日是7月1号🎂
王芳的生日是6月28号🎂
李伟的生日是12月26号🎂
王秀英的生日是11月16号🎂
李秀英的生日是12月27号🎂
李娜的生日是6月25号🎂
张秀英的生日是8月26号🎂
刘伟的生日是4月28号🎂
张敏的生日是5月24号🎂
李静的生日是8月21号🎂
张丽的生日是5月15号🎂
王静的生日是6月2号🎂
王丽的生日是6月13号🎂
李强的生日是6月19号🎂
张静的生日是11月4号🎂
李敏的生日是9月19号🎂
王敏的生日是12月8号🎂
王磊的生日是5月22号🎂
李军的生日是4月25号🎂
刘洋的生日是3月16号🎂

正则表达式的可读性 非常差,但写起来并没有那么困难,上面每个正则表达式,仅花了十几秒就写完了

代码重构

原始文本 

def fib():
    return ((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))

def subfib(start, end):
    for cur in fib():
        if cur > end: return
        if cur >= start:
            print cur
            yield cur

def foo(a, b):
   return a + b

调整缩进,将四空格缩进重构为八个空格

^(\s+)    $1$1

结果:

def fib():
        return ((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))


def subfib(start, end):
        for cur in fib():
                if cur > end: return
                if cur >= start:
                        print cur
                        yield cur


def foo(a, b):
      return a + b


print 'fibonacci 10~100:'
print subfib(10, 100)


重构 Python2 的 print 语法为 Python3 的 print() 函数

print *(.*)$   print($1)

结果:

def subfib(start, end):
    for cur in fib():
        if cur > end: return
        if cur >= start:
            print(cur)
            yield cur

def foo(a, b):
   return a + b

print('fibonacci 10~100:')
print(subfib(10, 100))

所有函数声明添加 func_ 前缀

def *(.*)   def func_$1

结果:

def func_subfib(start, end):
    for cur in fib():
        if cur > end: return
        if cur >= start:
            print cur
            yield cur

def func_foo(a, b):
   return a + b

print 'fibonacci 10~100:'
print subfib(10, 100)

交换函数声明中的参数位置

def (.*?)\((\w+), *(\w+)\)   def $1($3, $2)

结果:

def subfib(end, start):
    for cur in fib():
        if cur > end: return
        if cur >= start:
            print cur
            yield cur

def foo(b, a):
   return a + b

print 'fibonacci 10~100:'
print subfib(10, 100)

为所有函数添加注释模板

def *(.*):  def $1:   """    函数描述:    参数:    返回值:  """

结果:

def fib():
   """
    函数描述:
    参数:
    返回值:
  """
    return ((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))

def subfib(start, end):
   """
    函数描述:
    参数:
    返回值:
  """
    for cur in fib():
        if cur > end: return
        if cur >= start:
            print cur
            yield cur

def foo(a, b):
   """
    函数描述:
    参数:
    返回值:
  """
   return a + b

print 'fibonacci 10~100:'
print subfib(10, 100)

正则表达式在代码分析方面有广泛应用,编辑器代码高亮都是用正则表达式实现的。

不过正则表达式并非万能,比如第三步中为函数添加前缀时,并未对函数调用的地方添加前缀,还需要后续处理。

数据格式验证

数据格式验证是正则表达式的一个常用领域,网站通常使用正则表达式来判断用户提交的信息是否符合规范。

下面的正则表达式都相当复杂,幸运的是你不需要记忆这些常用的正则表达式,需要时通过任何搜索引擎都能够找到。

邮箱验证

^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$

输入数据

123@qq.com
asdf@gmail.com
surname@blah.com
name.name@123.com
1242135.com
@foo.com
a@a
name @bla.com

合法数据

123@qq.com
asdf@gmail.com
surname@blah.com
name.name@123.com

密码强度验证

(最少八个字符,至少一个大写字母,一个小写字母和一个数字)

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^\n]{8,}$

输入数据

123456
wdfqe#wefDdf123
wjleif932
8Ij12340
password
11111111ABc
hello
qweasdzxc

合法数据

wdfqe#wefDdf123
8Ij12340
11111111ABc

18 位身份证号验证

^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$

输入数据

23010519491231002X
33010517491231232X
67810519491331214X
22010519491232452X
123412195292349132
123412196712234932
a23rr23451235t123f
124123580913457102

合法数据

23010519491231002X
123412196712234932


IP 地址验证

^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$

输入数据

1.0.0.0
12.3.4.5
192.168.1.1
192.168.256.1
1.2.2.2
0.0.0.0
2.3.4
-1.2.3.4

合法数据

1.0.0.0
12.3.4.5
192.168.1.1
1.2.2.2
0.0.0.0

手机号验证

^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$

输入数据

12345678900
12354125235
15423423523
15123458654
8613890235892
017728384893
11111111111

合法数据

15123458654
8613890235892
017728384893

有一些网站提供了常用的正则表达式和测试环境,例如

  • regexr.com 一个非常棒的在线环境,我经常使用
  • regexlib.com 收录了很多严谨的正则表达式,不过也相当复杂

网络爬虫

网络爬虫提取数据也离不开正则表达式。

原始文本

<div class="hotnews">
<div class="imgview" id="imgView"><a href="https://xinwen.eastday.com/a/n181211075002407.html?qid=news.baidu.com" target="_blank"><img src="https://imgsa.baidu.com/news/q%3D100/sign=cdae0fb78a94a4c20c23e32b3ef51bac/cefc1e178a82b90151b62d8b7e8da9773912ef6b.jpg"></a></div><ul><li class="hdline0">
<a href="http://www.xinhuanet.com/politics/xxjxs/2018-12/11/c_1123834898.htm" target="_blank" class="a3">
XXX的改革之“喻” </a></li>
<li class="hdline1">
<a href="http://news.cri.cn/20181211/313376c7-77cc-abff-3a81-bd855c0a8577.html" target="_blank">
《必由之路》宣传片</a>
<i style="font-size: 12px">&nbsp;</i><a href="http://politics.gmw.cn/2018-12/11/content_32146726.htm" target="_blank">
主题歌《梦想阳光》发布 </a>
</li>
<li class="hdline2">
<img src="https://imgsa.baidu.com/news/q%3D100/sign=ab45ee53bbfd5266a12b38149b199799/f9198618367adab46063f9fb86d4b31c8601e4d3.jpg"><a href="http://politics.people.com.cn/n1/2018/1211/c1001-30458946.html" target="_blank" class="a3">
【央视快评】坚持中国特色人权发展道路</a></li>
<li class="hdline3">
<a href="http://news.cri.cn/20181210/384ab948-e36b-b455-9d97-8eb05172c179.html" target="_blank">同舟共济</a>
<i style="font-size: 12px">&nbsp;</i><a href="http://news.cctv.com/2018/12/10/ARTI9v2GwcDNkh8obJh2vnUy181210.shtml" target="_blank">
《改革开放 关键一招》第一集</a>
</li>
<li class="hdline4">
<a href="http://news.cctv.com/2018/12/10/ARTISzd4ekNLNB88EFFtMgB7181210.shtml" target="_blank" class="a3">
【数说改革开放40年】40年减贫7.4亿人</a></li>
<li class="hdline5">
<a href="http://news.ifeng.com/a/20181211/60188943_0.shtml?_zbs_baidu_news" target="_blank">王岐山出席的这个活动,有什么来头?</a>
</li>
</ul>
</div>

提取所有 HTML 标签

<("[^"]*"|'[^']*'|[^'">])*>

结果:

<div class="hotnews">
<div class="imgview" id="imgView">
<a href="https://xinwen.eastday.com/a/n181211075002407.html?qid=news.baidu.com" target="_blank">
<img src="https://imgsa.baidu.com/news/q%3D100/sign=cdae0fb78a94a4c20c23e32b3ef51bac/cefc1e178a82b90151b62d8b7e8da9773912ef6b.jpg">
</a>
</div>
<ul>
<li class="hdline0">
<a href="http://www.xinhuanet.com/politics/xxjxs/2018-12/11/c_1123834898.htm" target="_blank" class="a3">
</a>
</li>
<li class="hdline1">
<a href="http://news.cri.cn/20181211/313376c7-77cc-abff-3a81-bd855c0a8577.html" target="_blank">
</a>
<i style="font-size: 12px">
</i>
<a href="http://politics.gmw.cn/2018-12/11/content_32146726.htm" target="_blank">
</a>
</li>
<li class="hdline2">
<img src="https://imgsa.baidu.com/news/q%3D100/sign=ab45ee53bbfd5266a12b38149b199799/f9198618367adab46063f9fb86d4b31c8601e4d3.jpg">
<a href="http://politics.people.com.cn/n1/2018/1211/c1001-30458946.html" target="_blank" class="a3">
</a>
</li>
<li class="hdline3">
<a href="http://news.cri.cn/20181210/384ab948-e36b-b455-9d97-8eb05172c179.html" target="_blank">
</a>
<i style="font-size: 12px">
</i>
<a href="http://news.cctv.com/2018/12/10/ARTI9v2GwcDNkh8obJh2vnUy181210.shtml" target="_blank">
</a>
</li>
<li class="hdline4">
<a href="http://news.cctv.com/2018/12/10/ARTISzd4ekNLNB88EFFtMgB7181210.shtml" target="_blank" class="a3">
</a>
</li>
<li class="hdline5">
<a href="http://news.ifeng.com/a/20181211/60188943_0.shtml?_zbs_baidu_news" target="_blank">
</a>
</li>
</ul>
</div>

清洗所有 HTML 标签

<("[^"]*"|'[^']*'|[^'">])*>

结果:

同舟共济 
 &nbsp;  
《改革开放 关键一招》第一集 
 
 
 
【数说改革开放40年】40年减贫7.4亿人  
 
 王岐山出席的这个活动,有什么来头? 

提取所有 URL

(https?|ftp|file)(:/)?/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]

结果:

https://xinwen.eastday.com/a/n181211075002407.html?qid=news.baidu.com
https://imgsa.baidu.com/news/q%3D100/sign=cdae0fb78a94a4c20c23e32b3ef51bac/cefc1e178a82b90151b62d8b7e8da9773912ef6b.jpg
http://www.xinhuanet.com/politics/xxjxs/2018-12/11/c_1123834898.htm
http://news.cri.cn/20181211/313376c7-77cc-abff-3a81-bd855c0a8577.html
http://politics.gmw.cn/2018-12/11/content_32146726.htm
https://imgsa.baidu.com/news/q%3D100/sign=ab45ee53bbfd5266a12b38149b199799/f9198618367adab46063f9fb86d4b31c8601e4d3.jpg
http://politics.people.com.cn/n1/2018/1211/c1001-30458946.html
http://news.cri.cn/20181210/384ab948-e36b-b455-9d97-8eb05172c179.html
http://news.cctv.com/2018/12/10/ARTI9v2GwcDNkh8obJh2vnUy181210.shtml
http://news.cctv.com/2018/12/10/ARTISzd4ekNLNB88EFFtMgB7181210.shtml
http://news.ifeng.com/a/20181211/60188943_0.shtml?_zbs_baidu_news

提取所有 JPG 图片的 URL

(https?|ftp|file)(:/)?/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|].jpg

结果:

https://imgsa.baidu.com/news/q%3D100/sign=cdae0fb78a94a4c20c23e32b3ef51bac/cefc1e178a82b90151b62d8b7e8da9773912ef6b.jpg
https://imgsa.baidu.com/news/q%3D100/sign=ab45ee53bbfd5266a12b38149b199799/f9198618367adab46063f9fb86d4b31c8601e4d3.jpg

提取所有中文和中文标点

[\u4e00-\u9fa5\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b]+

结果:

XXX的改革之“喻”
《必由之路》宣传片
主题歌《梦想阳光》发布
央视快评
坚持中国特色人权发展道路
同舟共济
《改革开放
关键一招》第一集
数说改革开放
年
年减贫
亿人
王岐山出席的这个活动,有什么来头?

 

posted @ 2020-07-14 16:53  木子欢儿  阅读(606)  评论(0编辑  收藏  举报