美文网首页Python爬虫从入门到放弃
python爬虫从入门到放弃之七:正则表达式

python爬虫从入门到放弃之七:正则表达式

作者: 52d19f475fe5 | 来源:发表于2019-07-28 14:16 被阅读2次

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

    正则、Xpath、BeautifulSoup对比
    正则表达式的语法

    正则的语法很多,这里列出常用的



    re模块的常用方法
    • match()方法用于从字符串的第一个字符开始匹配,如果匹配成功,则返回Match对象,否则返回None

    • search()方法用于在整个字符串中搜索第一个匹配的值,如果匹配成功,则返回Match对象,否则返回None

    • findall()方法用于在整个字符串中搜索所有符合正则表达式的字符串,如果匹配成功,返回包含匹配结构的列表,否则返回空列表

    • sub()方法用于替换字符串

    • split()方法用于根据正则表达式分割字符串,并以列表的形式



    范例代码一:

    import re 
    string = '小明:20岁,小红:19岁'
    pattern = '\d{2}'
    
    result = re.match(pattern,string)
    print(result)
    
    result = re.search(pattern,string)
    print(result)
    print(result.group())
    
    result = re.findall(pattern,string)
    print(result)
    

    运行结果

    None
    <re.Match object; span=(3, 5), match='20'>
    20
    ['20', '19']
    >>> 
    

    match()方法得到的结果是None,原因在于match()方法是从字符串第一个字符开始去匹配的,这里因string第一个字符不是数字,所以直接返回None,如果直接print(result.group())是会报错的。

    group()方法是Match对象获取匹配的内容


    范例代码二:

    import re
    
    content = '发布于2019/7/28,发布人:小明'
    result =re.match('.*?(\d.*\d).*:(.*)',content)
    print(result.group())
    print(result.group(0))
    print(result.group(1))
    print(result.group(2))
    print('')
    result =re.findall('.*?(\d.*\d).*:(.*)',content)
    print(result)
    print(result[0])
    print(result[0][0])
    print(result[0][1])
    

    运行结果:

    发布于2019/7/28,发布人:小明
    发布于2019/7/28,发布人:小明
    2019/7/28
    小明
    
    [('2019/7/28', '小明')]
    ('2019/7/28', '小明')
    2019/7/28
    小明
    >>> 
    

    可以发现,group是针对()来说的,group(0)就是指的整个字符串,group(1)指的是第一个括号里的内容,group(2)指的第二个括号里的内容。

    findall()方法匹配多个字符时,返回列表的元素为元组

    .*?非贪婪模式,它匹配到'于'之后就停止了

    把上面的代码修改一下,我们希望提取发布时间,即2019/7/28


    范例代码三:

    import re
    
    content = '发布于2019/7/28,发布人:小明'
    
    result =re.findall('.*?(\d.*\d)',content)
    print(result)
    
    result =re.findall('.*(\d.*\d)',content)
    print(result)
    
    result =re.findall('.*(\d.*?\d)',content)
    print(result)
    
    result =re.findall('.*?(\d.*?\d)',content)
    print(result)
    

    运行结果:

    ['2019/7/28']
    ['28']
    ['28']
    ['20', '19', '7/2']
    >>> 
    

    .*?是非贪婪模式,尽可能少量地去匹配

    .*是贪婪模式,尽可能大量地去匹配

    我们先看括号内的内容,前后都是\d,说明()内的匹配结果必须包含两个数字,并且一前一后,范围在2019/7/28之内

    对于规则字符串.*?(\d.*\d).*?只要满足它的后面有两个数字它就不管了,所以它取到字就停止了,因此.*?匹配为发布于,这样第一个\d匹配为20192.*是贪婪匹配,它只要满足它后面有一个数字就继续取值,所以.*匹配为019/7/2,所以第二个\d就是8

    对于规则字符串.*(\d.*\d),第一个.*实行贪婪匹配,它发现它直接取到发布于2019/7/,剩下28留给\d.*\d去匹配依然满足,所以它就这么干了

    对于规则字符串.*(\d.*?\d),和上面一样

    以上三条,由于整个规则字符串只能成功匹配一次,因此返回一个元素的列表

    对于规则字符串.*?(\d.*?\d),第一个.*?取到字就不管了,剩下\d.*?\d去匹配2019/7/28,而.*?是非贪婪匹配,也叫懒惰匹配,当第一个\d匹配为20192时,它发现它不去匹配字符也行(其实是匹配为空值,即*=0),所以第二个\d匹配为0,就是\d.*?\d第一次匹配为20,剩下19/7/28还可以继续匹配;因为findall()方法是要获取所有匹配成功的结果,所以还得继续匹配,第二次匹配为19,剩下/7/28,只能从7开始匹配,第三次匹配为7/2,剩下8,无法继续匹配了


    范例代码四:

    import re
    
    string = '香辣口水鸡        卤肉饭        蒜蓉烤生蚝'
    result = re.sub('\s+',' ',string)
    print(result)
    

    运行结果:

    香辣口水鸡 卤肉饭 蒜蓉烤生蚝
    >>> 
    



    范例代码五:

    import re
    
    url = 'https://zhidao.baidu.com/list?cid=110&fr=daohang'
    pattern = r'[?|&]'
    result = re.split(pattern,url)
    print(result)
    

    运行结果:

    ['https://zhidao.baidu.com/list', 'cid=110', 'fr=daohang']
    >>> 
    



    范例代码六:

    import re
    
    pattern = r'china_\w+'
    string = 'CHINA_666 china_666'
    reult  = re.match(pattern,string,re.I)
    print(reult.group())
    

    运行结果:

    CHINA_666
    >>> 
    

    上面,匹配字符串是否以"china_"开头,不区分大小写

    re.I是标志参数,表示执行不区分字母大小写的匹配

    常用的标志如下:

    re.I 表示执行不区分字母大小写的匹配

    re.S 匹配所有字符,包括换行符

    re.X 忽略规则字符串中未转义的空格和注释

    re通用匹配公式

    用这个通用匹配公式实现对html页面快速提取数据

    reult = re.findall(r'~~(.*?)~~',string,re.S)

    波浪线部分代表有标识型一串字符


    实例展示:

    目标网站:豆瓣图书 Top 250 https://book.douban.com/top250

    提取数据:书名、评分、推荐语、链接

    • 分析url:


    通过多次翻页发现:第i页对应的url = 'https://book.douban.com/top250?start='+str(i*25)

    • 分析网页:


    每本书的信息在<tr class="item">标签下,用re通用匹配公式得出单个html页面的所有书books = re.findall(r'<tr class="item">(.*?)</tr>',html,re.S)

    再用for语句遍历,for book in booksbook就是每本书所有信息,对book用re公式提取标签的内容,将返回包含一个元素的列表

    为了防止某个书的信息不全,可以写个if判断语句

    代码实现:

    import requests
    import re
    
    # 如果匹配不成功,返回空字符串,成功则取值
    def info(list_name):
        if list_name==[]:
            return ''
        else:
            return list_name[0]
    
    # 用正则提取数据
    def get_data(url,headers):
        html = requests.get(url,headers = headers).text
        books = re.findall(r'<tr class="item">(.*?)</tr>',html,re.S)
        for book in  books:
            title = re.findall(r'title="(.*?)"',book,re.S)
            num = re.findall(r'<span class="rating_nums">(.*?)</span>',book,re.S)
            introduce= re.findall(r'<span class="inq">(.*?)</span>',book,re.S)
            link = re.findall(r'class="nbg" href="(.*?)"',book,re.S)
            print(info(title),info(num),info(introduce),info(link))
    
    if __name__ == "__main__":
        for i in range(10):
            url = 'https://book.douban.com/top250?start='+str(i*25)
            headers = {'User-Agent': 'Mozilla/5.0'}
            get_data(url,headers)
    
    



    >>>阅读更多文章请点击以下链接:

    python爬虫从入门到放弃之一:认识爬虫
    python爬虫从入门到放弃之二:HTML基础
    python爬虫从入门到放弃之三:爬虫的基本流程
    python爬虫从入门到放弃之四:Requests库基础
    python爬虫从入门到放弃之五:Requests库高级用法
    python爬虫从入门到放弃之六:BeautifulSoup库
    python爬虫从入门到放弃之七:正则表达式
    python爬虫从入门到放弃之八:Xpath
    python爬虫从入门到放弃之九:Json解析
    python爬虫从入门到放弃之十:selenium库
    python爬虫从入门到放弃之十一:定时发送邮件
    python爬虫从入门到放弃之十二:多协程
    python爬虫从入门到放弃之十三:Scrapy概念和流程
    python爬虫从入门到放弃之十四:Scrapy入门使用

    相关文章

      网友评论

        本文标题:python爬虫从入门到放弃之七:正则表达式

        本文链接:https://www.haomeiwen.com/subject/fyyurctx.html