zoukankan      html  css  js  c++  java
  • 爬虫基础:正则表达式

    什么是正则表达式

    正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、以及这些特定字符的组合,组成一个“规则字符串”,这个规则字符串用来表达对字符串的一种过滤逻辑

    Python用re模块实现

    在线正则表达式工具

    其中有许多常用的正则表达式,非常好用。

    一般的网页可以用beautifulsoup等解析库来提取,不过有的网页卸载js的变量中,只能使用正则表达式来提取。正则表达式可以用来筛选和清洗。非常有用。

    python中的正则表达式讲解

    • 常见匹配模式
    模式描述
    w 匹配字母数字及下划线
    W 匹配非字母数字下划线
    s 匹配任意空白字符、等价于[ f]
    S 匹配任意非空字符
    d 匹配任意数字,等价于[0-9]
    D 匹配任意非数字
    A 匹配字符串的开始
     匹配字符串结束,如果存在换行,只匹配到换行前的结束字符串
    z 匹配字符串结束
    G 匹配最后匹配完成的位置
    匹配一个换行符
    匹配一个制表符
    ^ 匹配字符串的开头
    $ 匹配字符串的结尾
    . 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
    [...] 用来表示一组字符,单独列出:[osi]匹配‘o’,'s','j'
    [^...] 匹配除括号中内容之外的字符
    * 匹配0个过多个表达式
    + 匹配1个或多个表达式
    匹配0个或者1个表达式
    {n} 精确匹配n个前面的表达式
    {n,m} 匹配n到m此有前面的正则表达式定义的片段,贪婪方式
    a|b 匹配a或b
    () 匹配括号内的表达式,也表示一个组
    • re.match

    re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

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

    sample

    1.常规的匹配

    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    print(len(content))
    result = re.match('^Hellosd{4}sd{4}sw{10}.*mo$',content)
    print(result)
    print(result.group())#匹配结果
    print(result.span())#匹配结果在content中的范围

    2.泛匹配--用.* 表示任意字符

    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    result = re.match('^Hello.*mo$',content)
    print(result)
    print(result.group())
    print(result.span())

    3.匹配目标

    一般我们把匹配目标用小括号括起来,然后指定左右端点,才能找到。

    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    result = re.match('^Hellos(d{4})s(d+)s.*mo$',content)
    print(result)
    print(result.group(1))#第一个小括号括起来匹配的内容
    print(result.group(2))#第二个小括号括起来的内容
    print(result.span())

    4.贪婪匹配

    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    result = re.match('^He.*(d+).*mo$',content)
    print(result)
    print(result.group(1))
    print(result.span())

    *结果是4,因为.*表示任意字符,默认贪婪模式会匹配尽量多的任意字符,而d+至少要匹配一个数字,所以就一直匹配到最后一个数字之前。

    5.非贪婪模式

    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    result = re.match('^He.*?(d+).*mo$',content)
    print(result)
    print(result.group(1))
    print(result.span())

    .*?是非贪婪模式,匹配尽可能少字符。

    6.匹配模式

    import re
    content = "Hello 3232 4324 World_This 
    is a Regex Demo
    "
    result = re.match('^He.*?(d+).*mo$',content)
    print(result)

    *结果为none,原因是.不能匹配换行符,修改之后可以匹配

    import re
    content = "Hello 3232 4324 World_This 
    is a Regex Demo
    "
    result = re.match('^He.*?(d+).*mo$',content,re.S)
    print(result)

    添加re.S后即可

    7.转义

    正则表达式中的许多特殊字符如果不做转义就无法匹配,会被认为是关键字使用,比如*.[]等等。以下就是不转义的例子

    import re
    content = 'price $50.09'
    result = re.match('price $50.09',content)
    print(result)

    结果返回none,没匹配到。

    转义之后才能匹配

    import re
    content = 'price $50.09'
    result = re.match('price $50.09',content)
    print(result)

    最常见用法总结,尽量使用泛匹配模式,使用括号得到匹配目标,尽量使用非贪婪模式,使用re.S,因为HTML中有大量的换行符这样.就能匹配任意字符了。

    • re.search

    re.match从字符串的开头匹配,比如pattern无法匹配content的第一个字符,那么直接返回none。而re.search会搜索整个字符串,只要搜索到符合pattern的内容就返回第一个成功的匹配。以下是sample。

    import re
    content = "jlljjljh Hello 1234 World_This is a Regex Demo,Don't forget!$"
    result = re.match('Hello.*?(d+).*?',content)
    print(result)#用match的话,result返回none
    result = re.search('Hello.*?(d+).*?',content)
    print(result)#可以匹配
    print(result.group(1))#返回1234

    总结,尽量用re.search方法,尽量使用re.S,用非贪婪模式

    练习

    import re
    html = '<div class="songList songList960 clearfix"><ol id="f1"><li><input type="checkbox" value="11417@" name="Url" class="check"> <span class="songNum topRed">01.</span> <a target="_1" href="/play/11417.htm" class="songName cBlue">大海</a></li><li><input type="checkbox" value="64541@" name="Url" class="check"> <span class="songNum topRed">02.</span> <a target="_1" href="/play/64541.htm" class="songName">天路</a></li><li><input type="checkbox" value="65937@" name="Url" class="check"> <span class="songNum topRed">03.</span> <a target="_1" href="/play/65937.htm" class="songName">再回首</a></li><li><input type="checkbox" value="59930@" name="Url" class="check"> <span class="songNum">04.</span> <a target="_1" href="/play/59930.htm" class="songName cBlue">突然的自我</a></li><li><input type="checkbox" value="1462@" name="Url" class="check"> <span class="songNum">05.</span> <a target="_1" href="/play/1462.htm" class="songName">甘心情愿</a></li></ol></div>'
    result = re.search('songName.*?>(.*?)</a>.*',html,re.S)
    print(result)
    print(result.group(1))

    匹配结果:大海

    • re.findall--搜索字符串,以列表形式返回全部能匹配的子串
    import re
    html = '<div class="songList songList960 clearfix"><ol id="f1"><li><input type="checkbox" value="11417@" name="Url" class="check"> <span class="songNum topRed">01.</span> <a target="_1" href="/play/11417.htm" class="songName cBlue">大海</a></li><li><input type="checkbox" value="64541@" name="Url" class="check"> <span class="songNum topRed">02.</span> <a target="_1" href="/play/64541.htm" class="songName">天路</a></li><li><input type="checkbox" value="65937@" name="Url" class="check"> <span class="songNum topRed">03.</span> <a target="_1" href="/play/65937.htm" class="songName">再回首</a></li><li><input type="checkbox" value="59930@" name="Url" class="check"> <span class="songNum">04.</span> <a target="_1" href="/play/59930.htm" class="songName cBlue">突然的自我</a></li><li><input type="checkbox" value="1462@" name="Url" class="check"> <span class="songNum">05.</span> <a target="_1" href="/play/1462.htm" class="songName">甘心情愿</a></li></ol></div>'
    result = re.findall('songName.*?>(.*?)</a>.*?',html)
    print(result)

    返回值:['大海', '天路', '再回首', '突然的自我', '甘心情愿'] *

    •  re.sub---替换字符串中每一个匹配的子串后返回替换后的字符串。
    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    content = re.sub('d+','',content)#把数字替换为空
    print(content)
    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    content = re.sub('d+','Replacement',content)#数字部分都替换成‘replacement’
    print(content)

    如果替换的结果包含想替换的内容怎么办,比如像把这2段数字前面加上No.,但数字要保留,怎么办?

    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    content = re.sub('(d+)',r'No.1',content)#用r''中间的是原生字符串不用转义了。先把patten小括号括起来,替换内容加
    .这个n表示第几个小括号的内容替换成这样。
    print(content)

    结果:Hello No.3232 No.4324 World_This is a Regex Demo

    • re.compile---将正则字符串编译成正则表达式对象

    将正则字符串编译成正则表达式对象,便于复用该匹配模式

    import re
    content = 'Hello 3232 4324 World_This is a Regex Demo'
    result = re.match('^He.*?(d+).*mo$',content,re.S)#用正则字符串匹配
    myPatten = re.compile('^He.*?(d+).*mo$',re.S)#编译正则表达式对象。
    result = re.match(mypatten,content)#2种方法一样
    print(result)
    • 例子

    爬取豆瓣读书

    读取 https://book.douban.com 新书速递中的书名、作者、出版社

    import requests
    import re
    content = requests.get('https://book.douban.com/').text
    #print(content)
    pattern = re.compile('<li.*?cover.*?href="(.*?)".*?title="(.*?)".*?more-meta.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>',re.S)
    #print(pattern)
    results = re.findall(pattern,content)
    print(results)
  • 相关阅读:
    魔法跳舞链 51Nod
    反射
    JDBC---后端服务器与数据库交互的桥梁
    多线程
    IO流
    继承与重写
    java.util包
    多态
    Java.lang包
    异常
  • 原文地址:https://www.cnblogs.com/x00479/p/14249703.html
Copyright © 2011-2022 走看看