精华内容
下载资源
问答
  • python爬虫正则表达式
    2022-02-12 19:57:25

    python爬虫—正则表达式的使用
    “”"
    ^匹配字符串的开头
    $匹配字符串的结尾
    .匹配任意字符除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行的任意字符
    […]用来表示一组字符,单独列出,[adas]匹配’a’‘d’;‘a’‘s’
    [^…]匹配不在[]中的字符
    re* 匹配0和或多和表达式
    re+ 匹配一个或多个的表达式
    re? 匹配0或1个由前面的正则表达式定义的片段,非贪婪方式
    re{n}
    re{n,} 精确匹配N个前面表达式
    re{n,m} 匹配n到m次由前面的正则表达式定义的片段,贪婪方式
    a b
    (re) G匹配括号内的表达式,也表示一个组
    (?imx) 正则表达式包含三种可选标志:i,m或x 之影响括号内的区域
    (?#.)注释
    \w 匹配字母数字及下划线
    \W 匹配非字母数字及下划线
    \s 匹配任意空白字符,等价于【\t\n\r\f】
    \S 匹配任意非空字符
    \d 匹配任意数字,等价于[1-9]
    \D 匹配任意非数字
    \A 匹配字符串开始
    \Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
    \z 匹配字符串结束
    \G 匹配最后完成匹配的位置
    \b 匹配一个单词边界,也就是之单词和空格键的位置例如:er\b 可以匹配never 中的er 但是不可以匹配verb的er
    \n,\t 匹配一个换行符,匹配一个制表符
    \1…\9 匹配第n个分组的内容、
    \10 匹配第n个分组的内容,如果经匹配,否则指的是八进制字符码的表达式
    [\u4e00-\u9fa5] 中文

    贪婪模式:总是匹配尽量多的字符】默认是贪婪的,非贪婪模式加个?
    例如:正则表达式ab如果用于查找"abbbc" ,将找到’abbb’3而如果使用非贪婪模式ab?,将找到’a’

    常用方法:
    re.match() 尝试从字符串的起始位置
    re.search
    re.search扫描整个字符串并成功返回第一个成功的匹配
    函数语法:re.search(pattern,string,flags=0)
    re.sub
    re.sub替换字符串re.sub(pattern,replace,string)
    re.findall
    re.findall查找全部 re.findall(pattern,string,flags=0)
    “”"

    实例演示:

    import re
    str1  = "I Study Python3.7 Everyday "
    print("*****match****")
    m1 = re.match(r'I',str1)
    m2 = re.match(r"\w",str1)
    m3 = re.match(r".",str1)
    m4 = re.match(r"\D",str1)
    m5 = re.match(r"i",str1,re.I)
    m6 = re.match(r"\S",str1)
    print(m1.group())
    print(m4.group())
    print(m5.group())
    
    m = re.match(r"Study",str1)#匹配不到,因为match是从左开始匹配
    print(m)
    print("****re.search()*******")
    m1 = re.search(r"Study",str1)
    m3 = re.search(r"S\w+",str1)
    m2 = re.findall(r"Study",str1)
    
    print(m2[0])
    
    m1 = re.search(r"P\w+.\d",str1)
    print(m1.group())
    
    
    f1 = re.findall(r"y",str1)#findall是一个列表
    print(f1)
    import re
    str2 = '<div><a herf ="https://www.baidu.com/">bjsxt百度</a></div>'
    # f1 = re.findall(r"[\u4e00-\u9fa5]\w+",str2)
    # f2 = re.findall(r'<a herf ="https://www.baidu.com/">(.+)</a>',str2)
    f3 = re.findall(r'a herf ="(.+)">',str2)
    print(f3)
    
    str2 = '<div class = "info" id = "info"><a herf ="https://www.baidu.com/">bjsxt百度</a></div>'
    import re
    str2 = '<div><a herf ="https://www.baidu.com/">bjsxt百度</a></div>'
    sul = re.sub(r"<div>(.+)</div>",r"<span>\1</span>",str2)#\1一个分组
    print(sul)
    
    
    更多相关内容
  • 这篇文章主要介绍了python爬虫 正则表达式解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 – re.I # 忽略大小写 – re.M # 多行匹配,将正则作用到源数据...
  • 刚开始学python,记录下问题。 代码如下: #coding:utf-8 import re,urllib2 def getHTML(url): ...if __name__=='__main__': ... print getHTML(url).replace('\n','').replace('\...以上所述是小编给大家介绍的python爬虫
  • 下面小编就为大家带来一篇python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 本文实例讲述了Python爬虫正则表达式基本用法。分享给大家供大家参考,具体如下: 一、简介 正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常...
  • 正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。得益于这一点,在提供了正则表达式的语言里,...
  • 文章目录Python爬虫(二十一)—— 正则表达式应用详解 ——1. 简介2. 语法 1. 简介 正则表达式:regular expression,也称regex,简称 RE 正则表达式是用来简洁表达一组字符串的表达式 通用的字符串表达框架 简洁...
  • 主要介绍了Python 正则表达式爬虫使用案例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 1. 为什么要使用正则表达式? 首先,大家来看一个例子。一个文本文件里面存储了一些市场职位信息,格式如下所示: Python3 高级开发工程师 上海互教教育科技有限公司上海-浦东新区2万/月02-18满员 测试开发工程师...
  • 初学python爬虫,今天用正则表达式提取网页内的图片地址 ''' 正则表达式模块提取网页图片地址 面向过程式编程 ''' #导入第三方库 import re import requests #请求头 headers = {'User-Agent':'Mozilla/5.0 (Windows...
  • 本文讲述了python实现的正则表达式功能。分享给大家供大家参考,具体如下: 前文: 首先,什么叫正则表达式(Regular Expression)? 例如我们要判断字符串”adi_e32fv,Ls”里面是否含有子串”e32f”,又例如我们在...
  • Python爬虫正则表达式

    千次阅读 2022-03-10 15:16:45
    Python正则表达式爬虫学习内容之一

    正则表达式

    正则表达式就是规则表达式,在接触爬虫前,正则表达式就是用来过滤的。接触爬虫后发现真的就是过滤用的hhh。正则表达式在爬虫中的作用就是过滤出想要的字符,然后获取,如果不用正则表达式,那么就会将网页中大量信息全部爬出,造成大量内存浪费,亦不是我们最初想要爬取某些东西的初衷。

    正则表达式原理

    通过正则表达式我们可以实现

    1. 给定的字符串是否符合正则表达式的过滤逻辑(匹配

    2. 通过正则表达式,从文本字符串中获取我们想要的特定部分(过滤

    语法介绍

    正则表达式室友普通字符(a-z)以及特殊字符(“元字符”)组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。

    真个则表达式的组件可以是单个字符、字符合集、字符范围、字符间的选择或者所有这些组件的任意组合。正则表达式中的字符一般分为普通字符、非打印字符、特殊字符、限定符、定位符等。

    普通字符

    正常能够被打印的字符

    包括没有显示指定为元字符的所有可打印何不可打印字符。这包括所有大写和小写字母,所有数字,所有标点符号和一些其他符号。

    正则表达式在线测试:在线正则表达式测试

    注意字符串集合和字符串的区别(图一是集合,图二是字符串

    非打印字符

    非打印字符是打印出来,但实际看不到

    \cx匹配由x指明的控制字符,如\cM匹配一个Control-M1或者回车符。X值必须为A-Z或a-z之一。否则c将是一个原意的'c'字符。
    \f匹配一个换页符,等价\x0c和\cI。
    \n匹配一个换行符,等价\x0d和\cJ。
    \r匹配一个回车符,等价\x0d和\cM。
    \s匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\v\r\t\v]
    \S匹配任何非空白字符。等价于\f\v\r\t\v
    \t匹配一个制表符,等价\x09个\cI
    \v匹配垂直制表符,等价\x0b和\cK

    特殊字符

    有特殊含义的字符。如果要匹配这些元素需要在字符前面加转义符,即反斜杠字符[]。

    $匹配输入字符串结尾位置(有几行
    []标记一个子表达式的开始和结束位置,子表达式可以获取供后面使用
    *匹配前面的子表达式0次或多次
    +匹配前面的子表达式1次或多次
    .匹配除换行符\n之外的任何单个字符
    [标记一个中括号表达式的开始
    ?匹配前面的子表达式0次或1次,或指明一个非贪婪限定符。
    \讲下一个字符标记为或特殊字符、或原意字符、或向后引用、或八进制转义符。
    ^匹配输入字符串的开始位置、除非在方括号表达式中使用,此时它表示排除该字符的集合
    {标记限定符表达式的开始。
    |指明两项之间的一个选择

    和+的用法要比较来看,+比的要求更加严格 

    ?用法和Windows中文件搜索的?一样

    管道符可以实现同时匹配,可以理解为或

    限定符

    *匹配前面的子表达式0次或多次。例如,zo能匹配"z"以及"zoo",等价于{0,}
    +匹配前面的子表达式1次或多次,例如,'zo+'能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}
    匹配前面的子表达式0次或1次.例如"do[es]?"可以匹配"do"或"does"中的do。?等价于{0,1}
    {n}n是一个非负整数,匹配确定的n次。例如,'o{2}'不能匹配"BOb"中的o,但能匹配'fooooood'中所有的o。
    {n,}n是一个非负整数。至少匹配n次。例如'0{2,}'不能匹配"BOb"中的'o',但能匹配"foooooood"中所有的o。'0{1,}'等价于'0+'。'o{0,}'则等价于"o"
    {n,m}m和n均为非负整数,其中n<=m。最少匹配n次且做多匹配m次。例如,"o{1,3}"将匹配"foooooood"中的前三个o。'o{0,1}'等价于'0?'。注意在逗号和两个数之间不能有空格

    常用函数

    • re.findall[]                 最常用

    • re.conpile[]

    • re.match[]                最常用

    • re.search[]               最常用

    • re.finditer[]

    • re.sub[]                    最常用

    • re.subn[]

    • re.split[]

    re.findall[]函数

    语法:re.findall[pattern,string,flags=0]-->list[列表]

    列出字符串模式中的u送头匹配项,并作为列表储存在list列表中

    与re.search[]不一样的地方:

    re.findall返回的是列表

    re.search返回的是文本

    re.findall返回的是列表,re.search返回文本

    re.findall匹配多个值,re.search只要匹配到就返回,只匹配一个值

    re.compile[]函数

    语法:re.compile[pattern,flags=0]--->pattern object

    根据包含正则表达式的字符串创建模式对象,可以实现更有效率的匹配!用了re.compile以后,正则对象会得到保留,这样在需要多次运用这个正则对象的时候效率会有较大的提升

    此外,re.compile[]可以接受可选属性,常用来实现不同的特殊功能和语法变更。

    MatchObject(匹配对象)方法

    group[]:返回被正则匹配的字符串;

    start[]:返回匹配开始的位置;

    end[]:返回匹配结束的位置;

    span[]:返回一个元组包含匹配(开始,结束)的位置。

    re.match[]函数

    语法:re.match[pattern,string,flags=0]----->match object or None

    在字符串的开始位置匹配正则!如果无匹配,返回None

    re.search[]函数

    语法:re.search[pattern,string,flags=0]----->match object or None

    re.search 函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None

    re.match与re.search的区别:re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失效,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

    re.finditer[]函数

    语法:re.finditer[pattern,string,flags=0]----->iterator

    列出字符串中模式的所有匹配项,并作为一个迭代器(可以被for循环,可以被next遍历)返回。

    re.sub[]函数

    语法:re.sub[pattern,repl,string,sount=0,flags=0]--------->string

    将字符串中所有pattern的匹配项用repl替换

    re.subn[]函数

    语法:re.subn[pattern,repl,string,count=0,flags=0]

    与sub[]实现相同的替换作用,但是subn[]返回一个元组,其中包含新字符串和替换次数!

    re.split[]函数

    语法:re.split[pattern,string,maxsplit=0,flags=0]----->list

    根据模式的匹配项来分割字符串!

    展开全文
  • 主要介绍了Python爬虫包Beautiful Soup中用正则表达式来搜索的技巧,包括使用正则表达式去搜索多种可能的关键字以及查找属性值未知的标签等,需要的朋友可以参考下
  • 此次课程我们会系统的学习一下 python正则表达式以及可以根据自己的需 求写出正确的正则表达式2 学习此次课程需要多久15-20 分钟建议每个 表达式跟着实践一下加深印象 3 课程内容 Python 中正则表达式 在 re 模块...
  • 学习笔记:Python爬虫正则表达式.docx
  • 如此庞大的一个电商网站,上面的商品信息是海量的,小编今天就带小伙伴利用正则表达式,并且基于输入的关键词来实现主题爬虫。 首先进去京东网,输入自己想要查询的商品,小编在这里以关键词“狗粮”作为搜索对象,...
  • 学习笔记:Python爬虫正则表达式.doc
  • 在用正则表达式匹配网址信息的时候,经常会匹配到空的列表。还在这个地方卡了两三天的时间。 最后通过问朋友的方式得以解决。 正则表达式匹配的会经常有隐含符的情况,所以在所选标签匹配不到的情况下,应该先匹配...

    在用正则表达式匹配网址信息的时候,经常会匹配到空的列表。这个问题确实很烦,我当初也在这个地方卡了好长时间,所以就打算写一个博客来好好整理一下正则表达式匹配为空的一些状况。
    一:选取正则表达式的方式不对
    并不建议在网页上按F12然后选中自己想爬的内容,直接写正则表达式,因为网页的源代码和返回给我们请求的html是不一样的,源代码里会夹杂着一些隐含符,/n或者/r/n…要是没有这些隐含符就会导致匹配到空的字符串。
    解决办法:在def_analysis(self,htmls):里设置断点,然后进行调试
    在这里插入图片描述

    圆的为断点,长方形的为调试,等待一会后出现
    在这里插入图片描述

    然后右边就会出现你匹配到的情况,在里面找到htmls,点view然后把里面的内容复制到一个word文档里,放在word文档里的好处就是不用匹配一个调试一下了,而且可以在word文档里用ctrl+H来进行查找,会方便很多。在这里就可以直接匹配到你想要的内容。

    二:你爬取的内容是动态的,返回的html里没有相应的信息,例如京东的价格,评论,这样就不能用正则表达式来匹配,你需要从接口里爬取。
    关于从接口里爬取动态的内容,我们到以后在进行讲解。

    三:以上两种可能都没有的话,就只有可能你爬的网址有十分强大的反爬虫,就是不让你爬。可以试试更换ip地址,User-Agent,cookies,怎么更ip,user-agent 会在以后再进行讲解

    至此,如果你的问题还没有解决,就在下方评论或者私信,那我们就下次再见吧

    展开全文
  • 正则表达式Python爬虫中的作用就像是老师点名时用的花名册一样,是必不可少的神兵利器。 一、 正则表达式基础 1.1.概念介绍 正则表达式是用于处理字符串的强大工具,它并不是Python的一部分。 其他编程语言中也有...
  • 正则表达式匹配括号外的符号 [\\?!/\\.,\\s]+(?=[^\\)]*(\\(|$)) 将括号外的?!/.,和空格(连续多个时同时)匹配 如 String string1 = sdfsdf sdlfksd sdf,fsdf&sdf(s:1,g:1) sdfsd sdf! ? . sdfl asdf ; String...
  • 这个页面的案例,其实代码已经在页面上有了,这个只是方便哪些复制都不想复制的人。不过,这个东西拿到后就可以运行了,运行前记得导入相应模块 python -m pip install requests 这个是Python3
  • 正则表达式是用来匹配字符串非常强大的工具,在其他编程语言中同样有正则表达式的概念,Python同样不例外,利用了正则表达式,我们想要从返回的页面内容提取出我们想要的内容就易如反掌了。 正则表达式的大致匹配...
  • 主要给大家介绍了关于Python爬虫运用正则表达式的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Python具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • Python爬虫,除了使用大家广为使用的scrapy架构外,还有很多包能够实现一些简单的爬虫,如BeautifulSoup、Urllib、requests,在使用这些包时,有的网络因为比较复杂,比较难以找到自己想要的代码,在这个时候,如果...
  • 在学编程的过程中,我们可能听过正则表达式,但是不知道它是什么,我一开始听到正则表达式时,我在想正则表达式是啥?它用来干嘛的?学起来难不难的?可能很多人和我想的一样。学完之后,我很认真负责地告诉你们,...

    前言

    在学编程的过程中,我们可能听过正则表达式,但是不知道它是什么,我一开始听到正则表达式时,我在想正则表达式是啥?它用来干嘛的?学起来难不难的?可能很多人和我想的一样。学完之后,我很认真负责地告诉你们,正则表达式不难!!!

    正则表达式

    百度百科里写到:

    正则表达式又称规则表达式,计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本,是对字符串操作的一种逻辑公式,是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

    我们来打开开源中国提供的正则表达式测试工具https://tool.oschina.net/regex#,输入待匹配的文本,然后选择要匹配的表达式,这样就可以得出结果了,如下图所示:

    简单来说,正则表达式是处理字符串的强大工具,它有自己特定的语法结构,有了它,实现字符串的检索、替换、匹配验证、在HTML里提取想要的信息都是简简单单的事。

    有人可能会说下面这个是啥东西,看不懂。

    [a-zA-z]+://[^\s]*
    

    那个就是正则表达式的特定语法规则组合,通过这些组合,我们就可以得到我们想要的字符,例如,\s表示匹配任意的空白字符,*代表匹配前面的字符任意多个等等。常用的匹配字符规则如下表:

    模式描述
    \w匹配字母、数字及下划线
    \W匹配不是字母、数字及下划线的字符
    \s匹配任意空白字符,相当于{\t\n\r\f}
    \S匹配任意非空白字符
    \d匹配任意数字,等价于[0-9]
    \D匹配任意非数字字符
    \A匹配字符串开头
    \Z匹配字符串的结尾,如果存在换行,只匹配到换行前的字符串
    \z匹配字符串的结尾,如果存在换行,同时还会匹配换行符
    \G匹配最后完成匹配的位置
    \n匹配换行符
    \t匹配制表符
    ^匹配一行字符串的开头
    $匹配一行字符串的结尾
    .匹配除换行符外的任意字符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
    […]用来表示一组字符单独列出,比如[amk]匹配a,m,k
    [^…]不在[]中的字符,比如^abc,表示匹配除了a,b,c之外的字符
    *匹配0个或多个表达式
    +匹配1个或多个表达式
    匹配0个或1个前面正则表达式定义的片段(非贪婪匹配)
    {n}精确匹配n个前面的表达式
    {n,m}匹配n到m次,由前面正则表达式匹配的片段(贪婪匹配)
    a|b匹配a或b
    ( )匹配括号内的表达式,也表示一个组

    看到上面的表是不是有点害怕了,在爬虫中,我们用得最多的匹配字符有下面几个:

    • .:匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符;

    • *:匹配0个或多个表达式;

    • ?:匹配0个或1个前面的正则表达式定义的片段;

    • ():匹配括号内的表达式 ,也表示一个组;

    • \d:匹配任意数字,等价于[0-9];

    • {n}:精确匹配n个前面的表达式;

    • $:匹配一行字符串的结尾。

    大家先记住上面最常用的匹配字符,在接下来的学习中,我们遇到其他匹配字符的话,会做简单的讲解。

    re库——常用方法

    查找一个匹配项

    match():从字符串起始位置开始匹配,如果匹配不成功就返回None。

    search():匹配整个字符串并返回第一个匹配成功的值,否则返回None;

    fullmatch():匹配整个字符串是否与正则完全相同,否则返回None。

    其语法格式为:

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

    其中:

    • pattern表示匹配的正则表达式或字符串;

    • string表示匹配的字符串;

    • flags表示标准位,用于控制正则表达式的匹配方式也可以忽略不写,如:是否区分大小写。

    具体代码如下所示:

    import re
    print(re.match('Hello,Word','Hello,WOrd'))
    print(re.search('e.*?$','hello Word'))
    print(re.fullmatch('e.*?$','Hello Word'))
    
    

    运行结果为:

    None
    <re.Match object; span=(1, 10), match='ello Word'>
    None
    

    re.match()方法中,第一个参数是字符串,第二个参数是要匹配的字符串,由于两个字符串中的字母o不同,所以匹配不成功,返回的值为None;

    re.search()方法中,第一个参数是正则表达式,该表达式表示从字母e开始匹配0个或多个任意字符前面正则表达式定义的片段匹配到字符串末尾,第二个参数是要匹配的字符串,在输出结果中,object是输出对象类型,span=(1,10)表示该匹配的范围是1到9,match='ello Word’表示匹配的内容;

    re.fullmach()方法与re.match()方法差不多,第一个参数是正则表达式,第二个参数是要匹配的字符串,由于要匹配的字符串与正则表达式不匹配,所以返回的值为None。

    注意:查找一个匹配项,返回的都是一个匹配对象。

    查找多个匹配项

    re.findall:在字符串任意位置中找到正则表达式所匹配字符,并返回一个列表,如果没有找到匹配的,则返回空列表;

    re.finditer:在字符串任意位置中找到正则表达式所匹配字符,并返回一个迭代器;

    语法格式为:

    re.findall(pattern, string, flags=0)   或   pattern.findall(string , n,m)
    re.finditer(pattern, string, flags=0)
    

    其中:

    • string表示待匹配字符串;
    • n,m是可选参数,指定字符串的起始位置n(默认值为0)和结束位置m(默认为字符串的长度);
    • pattern表示匹配的正则表达式或字符串;
    • flags表示标志位,用于控制正则表达式的匹配方式,如:是否区分大小写。

    具体代码如下所示:

    import re
    fd1 = re.findall('\D+','11a33c4word34f63')
    pattern = re.compile('\D+')
    fd2 = pattern.findall('11a33c4word34f63', 0, 10)
    fi=re.finditer('\D+','11a33c4word34f63')
    print(fd1)
    print(fd2)
    print(fi)
    

    运行结果为:

    ['a', 'c', 'word', 'f']
    ['a', 'c', 'wor']
    <callable_iterator object at 0x00000193BD2C5F10>
    

    在第二行代码中,我们使用了re.findall(pattern, string, flags=0) 语法,第一个参数是由\D+简单匹配字符组合起来的正则表达式,其意思是匹配1个或多个任意非数字的字符,第二个参数是要匹配的字符串,所以匹配的内容是acwordf,没有被匹配的字符作为列表的分割点,所以返回的内容是[‘a’, ‘c’, ‘word’, ‘f’];

    在第三行代码中,我们使用了re.compile()方法将正则字符串编译成正则表达式对象(这个re.compile()方法后面会介绍),第四行代码中,在pattern对象中调用了findall()方法,第一个参数是要匹配的字符串,后面两个数字是匹配字符串的始末位置,所以返回的内容是[‘a’, ‘c’, ‘wor’];

    在第五行代码中,我们使用了re.finditer()方法,第一个参数是正则表达式,第二个参数是要匹配的字符串,返回的内容中的callable_iterator代表是迭代器。我们用个for循环打印输出匹配的成功的字符串有哪些?

    fi=re.finditer('\D+','11a33c4word34f63')
    for i in fi:
        print(i)
    

    运行结果为:

    <re.Match object; span=(2, 3), match='a'>
    <re.Match object; span=(5, 6), match='c'>
    <re.Match object; span=(7, 11), match='word'>
    <re.Match object; span=(13, 14), match='f'>
    

    匹配的内容和findall方法的一样,在可能存在大量的匹配项的情况下,我们推荐使用finditer方法,因为findall方法是返回列表,列表是一次性生成在内存中,而finditer方法是返回迭代器,迭代器是需要使用时一点一点生成出来的,内存使用更优。

    分割

    re.split():按照能够匹配的子串将字符串分割后返回列表。

    语法格式为:

    re.split(pattern, string ,maxsplit=0, flags=0)
    

    其中:

    • pattern表示匹配的正则表达式或字符串;
    • string表示要匹配的字符串;
    • maxsplit表示分隔次数,maxsplit=1分隔一次,默认为 0,不限制次数;
    • flags表示标志位,用于控制正则表达式的匹配方式,如:是否区分大小写。

    具体代码如下所示:

    sp1=re.split('\d+','I5am5Superman',maxsplit=0)
    sp2=re.split('\d+','I4am5Superman',maxsplit=1)
    sp3=re.split('5','I4am5Superman',maxsplit=0)
    print(sp1)
    print(sp2)
    print(sp3)
    

    运行结果为:

    ['I', 'am', 'Superman']
    ['I', 'am5Superman']
    ['I4am', 'Superman']
    

    在第二、三、四行代码中,我们使用了re.split()方法,我们使用了正则表达式或者数字作为分割点,并设置了分割次数。

    注意:str模块也有个split方法,主要区别是str.split不支持正则分割,re.split支持正则;

    替换

    re.sub():用于替换字符串中的匹配项;

    re.subn():用于替换字符串中的匹配项,返回一个元组。

    语法格式为:

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

    其中:

    • pattern表示匹配的正则表达式或字符串;
    • repl表示字符串或函数,当repl表示字符串时,则处理其中的任何反斜杠转义,当repl表示函数时,只能有一个入参:Match匹配对象。
    • string表示要被查找替换的原始字符串;
    • count表示匹配后替换的最大次数,默认为0表示替换所有的匹配;
    • flags表示表示时用到的匹配模式。

    具体代码如下所示:

    import re
    def loo(matchobj):
        if matchobj.group(0)=='1':
            return '*'
        else:
            return '+'
    print(re.sub('\w+',loo,'1-23-123-ds-fas23221'))
    print(re.sub('\d+','1','1-23-123-ds-fas23221',count=2))
    print(re.subn('\w+','1','1-23-123-ds-fas23221adsa2'))
    

    运行结果为:

    *-+-+-+-+
    1-1-123-ds-fas23221
    ('1-1-1-1-1', 5)
    

    首先我们定义了一个loo函数其作用是根据字符来返回特定的字符,第七、八行使用了re.sub(),其中repl传入的参数分别为函数和字符,第一个sub()没有传入count数据,所以替换所有的匹配,第二个sub()传入count数据为2,所以替换了匹配前两个数据;

    第九行代码,我们使用了re.subn()方法其返回的是一个元组,传入的第一个参数为正则表达式,其作用是匹配字母、数字及下划线,第二个参数为替换成的字符,第三个参数为要被查找替换的原始字符串,由于我们替换了5次,所以返回的是(‘1-1-1-1-1’, 5)。

    正则表达式对象

    re.compile():将正则字符串编译成正则表达式对象。

    其语法格式为:

    re.compile(pattern,flags)
    

    其中:

    • pattern表示正则表达式;
    • flags表示匹配模式,比如忽略大小写,多行模式等。

    具体代码实例如下所示:

    import re
    pattern=re.compile('\w+')
    content='I-am-superman'
    result=re.findall(pattern,content)
    print(result)
    

    运行结果为:

    ['I', 'am', 'superman']
    

    首先我们调用compile方法来创建一个正则表达式对象,定义一个content变量来存放字符串,再调用findall()方法,将匹配的字符串以列表的形式输出。compile()方法是给正则表达式做了一层封装,以便我们更好地复用,这样我们在调用search()方法、findall()等方法中就不需要重新在写正则表达式了。

    re库——修饰符

    正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I 和 re.M 被设置成 I 和 M 标志,还有一些修饰符,在必要的情况下也可以使用,如下表所示:

    修饰符描述
    re.I或re.IGNORECASE使匹配对大小写不敏感
    re.L或re.LOCALE做本地化识别(locale-aware)匹配
    re.M或re.MULTILINE多行匹配,影响 ^ 和 $
    re.S或re.DOTALL使 . 匹配包括换行在内的所有字符
    re.A或re.ASCII只匹配ASCII,而不是Unicode
    re.X或re.VERBOSE该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

    我们网页匹配比较常用的re.I和re.S来举例说明。

    具体代码实例一如下:

    import re
    #修饰符re.I
    print(re.findall('SUPERMAN','i am superman'))
    print(re.findall('SUPERMAN','i am superman',re.I))
    #修饰符re.S
    print(re.findall('.*?','\nman',))
    print(re.findall('.*?','\nman',re.S))
    

    运行结果为:

    []
    ['superman']
    ['', '', 'm', '', 'a', '', 'n', '']
    ['', '\n', '', 'm', '', 'a', '', 'n', '']
    

    没有添加re.I和re.S修饰符时,

    由于大小写的原因,第一个输出为空;

    由于匹配时自动忽略特殊符的匹配,所以第三个输入没有换行符(\n)。

    小技巧

    匹配目标

    如何中一段文本中提取一部分内容呢,我们可以使用()括号将想提取的子符串括起来,它标记了一个子表达式的开始和结束位置,被标记的每个子表达式会依次对应每个分组,调用group()方法传入分组的索引即可获得提取的结果。

    具体实例代码如下所示:

    import re
    content='I am superman,It is cool123'
    result=re.match('^I\s(\w+)\ssup.*?is\scool(\d+)',content)
    print(result.group(0))
    print(result.group(1))
    print(result.group(2))
    

    运行结果为:

    I am superman,It is cool123
    am
    123
    

    首先我们我们调用了re.match()方法进行查找匹配,然后调用group()方法传入分组的索引,这里我们使用了两个(),所以最大索引为2。

    • 当索引为0时,输出的是整个匹配的结果;
    • 当索引为1时,输出的是第一个目标匹配;
    • 当索引为2时,输出的是第二个目标匹配;

    假如正则表达式后面还有()括号的内容,那么可以依次使用group(3)、group(4)来获取。

    贪婪与非贪婪匹配

    .*:贪婪匹配是尽可能匹配多的字符;

    .*?:非贪婪匹配是尽可能匹配少的字符。

    它们之间的区别是多了一个问号,我们通过具体代码来感受一下它们之间的差别。

    具体代码如下:

    import re
    content='I am 123superman,It is cool'
    
    #贪婪匹配.*
    result=re.match('^I .*(\d+).*cool',content)
    print(result)
    print(result.group(1))
    
    #非贪婪匹配.*?
    result1=re.match('^I .*?(\d+).*?cool',content)
    print(result1)
    print(result1.group(1))
    

    运行结果为:

    <re.Match object; span=(0, 27), match='I am 123superman,It is cool'>
    3
    <re.Match object; span=(0, 27), match='I am 123superman,It is cool'>
    123
    

    匹配内容中,贪婪匹配与非贪婪匹配的整个匹配内容一样,但贪婪匹配的目标匹配内容会缺少一部分,这是因为贪婪匹配会尽可能匹配多的内容。

    • 当贪婪匹配.*后面是\d+,也就是至少匹配一个数字,但没具体几个数字,所以贪婪匹配就把12匹配了,只给\d+留了一个数字,导致最后得到的内容只有数字3了;
    • 当非贪婪匹配.*?匹配到I 时,在往后就是数字了,与\d+刚好匹配,非贪婪匹配就不再进行匹配,交给\d+去匹配后面的数字,所以最后得到的内容是123了。

    在匹配的时候,尽量使用非贪婪匹配,以免出现匹配结果缺失的情况。

    实战演练

    现在我们来点实战,尝试爬取QQ音乐中热歌榜的排名、图片链接、歌名、歌手和播放时间等信息,并将信息存放在csv文件中。

    本次爬取的基本思路:

    1. 页面分析;
    2. 抓取页面源代码;
    3. 正则提取我们想要的信息;
    4. 保存信息到csv文件中。

    页面分析

    首先我们在chrome浏览器打开QQ音乐中热歌榜,并打开开发者工具,如下图所示:

    我们观察发现,存放排行榜信息的容器是在上图中的div中,展开这个div,观察里面的信息,如下图所示:

    展开后,我们发现里面有两个ul,其中第二个ul里面有很多个li,每个li对应着一首歌的信息,这些信息正是我们待会构造正则表达式的依据。

    抓取页面源代码

    首先我们定义了一个get_page()方法用来获取页面源代码,具体代码如下所示:

    import re
    import requests
    import csv
    
    #获取页面源代码
    def get_page():
        headers={
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36'
        }
        response=requests.get('https://y.qq.com/n/ryqq/toplist/26',headers=headers)
        if response.status_code==200:
            html=response.text
            parse_page(html)
        return None
    

    在上述代码中,首先导入re、requests、csv库,然后我们构造了一个请求头headers,再调用requests.get()方法,并给它传入了我们所需要获取的源代码的网址,如果网页的响应状态码为200时,就调用parse_page()方法,其方法我们给它传入的参数为Unicode型的数据。这样我们就成功把QQ音乐热歌榜源代码抓取下来并将源代码传输出去了。

    正则提取

    在上一步中,我们已经成功提取了源代码,接下来就要构造正则表达式把我们想要的内容提取出来存放在字典中,这里我们使用了非贪婪匹配。

    首先我们先获取排名,打开开发者工具,寻找排名信息源代码所在的地方,如下图所示:

    在上图中,我们可以看到排名代码的信息,我们根据这个信息来构造排名的正则表达式,由于一个li对应一首歌,所以我们正则表达式开头是

    • ,如下所示:
    • <li>.*?songlist__item.*?songlist__number.*?">(.*?)
      

      成功匹配排名后,我们根据下图的代码构造图片链接和歌名的正则表达式,

      经过查找后,我们图片链接存放在上图的img节点中,我们提取src属性,由于歌名也在img节点中,我们顺便把歌名提取出来,我们在排名的正则表达式基础上添加图片链接和图片的正则表达式:

      <li>.*?songlist__item.*?songlist__number.*?">(.*?)</div>.*?<img.*?src="(.*?)".*?alt="(.*?)".*?</li>
      

      成功匹配图片链接和歌名后,我们开始匹配歌手和播放时间了,我们根据下图的代码构造歌手和播放时间的正则表达式:

      经过查找后,我们歌手存放在上图的a节点中,我们提取title属性,歌名在div节点中,我们提取该节点的文本,我们在原有的正则表达式的基础上添加歌手和播放时间的正则表达式:

      <li>.*?songlist__item.*?songlist__number.*?">(.*?)</div>.*?<img.*?src="(.*?)".*?alt="(.*?)".*?<a.*?playlist__author.*?title="(.*?)".*?<div.*?songlist__time">(.*?)</div>.*?</li>
      

      好了,正则表达式已经写好了,我们调用re.compile()方法构造正则表达式对象,以便复用,具体代码如下:

      pattern=re.compile(
              '<li>.*?songlist__item.*?songlist__number.*?">(.*?)</div>.*?<img.*?src="(.*?)".*?alt="(.*?)".*?<a.*?playlist__author.*?title="(.*?)".*?<div.*?songlist__time">(.*?)</div>.*?</li>',re.S
          )
      

      在re.compile()方法中,我们传入了re.S参数,其作用是使 . 匹配包括换行在内的所有字符。

      提取我们想要的信息内容后,我们接下来把信息存放在字典中,并调用saving_song()方法并给其传入字典参数,具体代码如下:

      items=re.findall(pattern,html)
          for item in items:
              song= {
                  '排名':item[0],
                  '图片链接':'https:'+item[1],
                  '歌名':item[2],
                  '歌手':item[3],
                  '播放时间':item[4]
              }
              saving_song(song)
      

      保存信息

      提取信息后,我们接下来开始保存信息,首先我们先创建一个csv文件,并写入表头,具体代码如下:

      with open('Song.csv','a',newline='')as csvfile:
          writer=csv.writer(csvfile)
          writer.writerow(['排名','图片链接','歌名','歌手','播放时间'])
      

      然后定义saving_song()方法,将字典写入csv文件中,具体代码如下:

      def saving_song(song):
          with open('Song.csv','a',newline='')as csvfile:
              writer=csv.writer(csvfile)
              writer.writerow([song.get('排名'),song.get('图片链接'),song.get('歌名'),song.get('歌手'),song.get('播放时间')])
      

      这样就把数据存放在csv文件中了。

      结果展示

      最后

      好了,正则表达式就讲解到这里了,需要源码的小伙伴可以私信博主。
      感谢观看!!!

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,535
精华内容 17,814
关键字:

python爬虫正则表达式