《零基础入门学习Python》第060讲:论一只爬虫的自我修养8:正则表达式4

这篇具有很好参考价值的文章主要介绍了《零基础入门学习Python》第060讲:论一只爬虫的自我修养8:正则表达式4。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

有了前面几节课的准备,我们这一次终于可以真刀真枪的干一场大的了,但是呢,在进行实战之前,我们还要讲讲正则表达式的实用方法和扩展语法,然后再来实战,大家多把持一会啊。

我们先来翻一下文档:

首先,我们要举的例子是讲得最多的 search() 方法,search() 方法 既有模块级别的,就是直接调用 re.search() 来实现,另外,编译后的正则表达式模式对象也同样拥有 search() 方法,我问问大家,它们之间有区别吗?

如果你的回答仅仅是 模块级别的search() 方法比模式级别的search() 方法要多一个正则表达式的参数,那你肯定没有去翻文档。

re.search(patternstringflags=0)

Scan through string looking for the first location where the regular expression pattern produces a match, and return a corresponding match object. Return None if no position in the string matches the pattern; note that this is different from finding a zero-length match at some point in the string.

这是模块级别的 search() 方法,大家注意它的参数,它有一个 flags 参数, flags 参数就我们上节课讲得 编译标志 位,作为一个模块级别的,它没办法复印,它直接在这里使用它的标志位就可以了。

pattern 是正则表达式的模式

string 是要搜索的字符串

我们再来看一下 如果是编译后的模式对象,它的 search() 方法又有哪些参数:

regex.search(string[, pos[, endpos]])

Scan through string looking for the first location where this regular expression produces a match, and return a corresponding match object. Return None if no position in the string matches the pattern; note that this is different from finding a zero-length match at some point in the string.

The optional second parameter pos gives an index in the string where the search is to start; it defaults to 0. This is not completely equivalent to slicing the string; the '^' pattern character matches at the real beginning of the string and at positions just after a newline, but not necessarily at the index where the search is to start.

The optional parameter endpos limits how far the string will be searched; it will be as if the string is endpos characters long, so only the characters from pos to endpos - 1 will be searched for a match. If endpos is less than pos, no match will be found; otherwise, if rx is a compiled regular expression object, rx.search(string, 0, 50) is equivalent to rx.search(string[:50], 0).

前面的 pattern, 模式对象的参数,就不需要了。

string 第一个参数就是待搜索的字符串

后面有两个可选参数是我们模块级别的 search() 方法没有的,它分别代表需要搜索的起始位置(pos)和结束位置(endpos)

你就可以像 rx.search(string, 0, 50) 或者 rx.search(string[:50], 0) 这样子去匹配它的搜索位置了。

还有一点可能被忽略的就是,search() 方法并不会立刻返回你所需要的字符串,取而代之,它是返回一个匹配对象。我们来举个例子:

 
  1. >>> import re

  2. >>> result = re.search(r" (\w+) (\w+)", "I love Python.com")

  3. >>> result

  4. <_sre.SRE_Match object; span=(1, 13), match=' love Python'>

我们看到,这个 result 是一个匹配对象( match object.),而不是一个字符串。它这个匹配对象有一些方法,你使用这些方法才能够获得你所需要的匹配的字符串:

例如:group()方法:

 
  1. >>> result.group()

  2. ' love Python'

我们就把匹配的内容打印出来了。首先是 一个空格,然后是 \w+ ,就是任何字符,这里就是love,然后又是一个空格,然后又是 \w+,这里就是Python。

说到这个 group()方法,值的一提的是,如果正则表达式中存在着 子组,子组会将匹配的内容进行 捕获,通过这个 group()方法 中设置序号,可以提取到对应的 子组(序号从1开始) 捕获的字符串。例如:

 
  1. >>> result.group(1)

  2. 'love'

  3. >>> result.group(2)

  4. 'Python'

除了 group()方法 之外,它还有 start()方法  、end()方法、 span() 方法,分别返回它匹配的开始位置、结束位置、范围。

match.start([group])

match.end([group])

Return the indices of the start and end of the substring matched by groupgroup defaults to zero (meaning the whole matched substring). Return -1 if group exists but did not contribute to the match. For a match object m, and a group g that did contribute to the match, the substring matched by group g (equivalent to m.group(g)) is

m.string[m.start(g):m.end(g)]

Note that m.start(group) will equal m.end(group) if group matched a null string. For example, after m = re.search('b(c?)', 'cba')m.start(0) is 1, m.end(0) is 2, m.start(1) and m.end(1) are both 2, and m.start(2) raises an IndexError exception.

An example that will remove remove_this from email addresses:

>>> email = "tony@tiremove_thisger.net"
>>> m = re.search("remove_this", email)
>>> email[:m.start()] + email[m.end():]
'tony@tiger.net'

match.span([group])

For a match m, return the 2-tuple (m.start(group), m.end(group)). Note that if group did not contribute to the match, this is (-1, -1)group defaults to zero, the entire match.

 
  1. >>> result.start()

  2. 1

  3. >>> result.end()

  4. 13

  5. >>> result.span()

  6. (1, 13)

 接下来讲讲 findall() 方法:

re.findall(patternstringflags=0)

Return all non-overlapping matches of pattern in string, as a list of strings. The string is scanned left-to-right, and matches are returned in the order found. If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result unless they touch the beginning of another match.

有人可能会觉得,findall() 方法很容易,不就是找到所有匹配的内容,然后把它们组织成列表的形式返回吗。

没错,这是在正则表达式里没有子组的情况下所做的事,如果正则表达式里包含了子组,那么,findall() 会变得很聪明。

我们来举个例子吧,上贴吧爬图:

例如我们想下载这个页面的所有图片:贴吧404

我们先来踩点,看到图片格式的标签:

《零基础入门学习Python》第060讲:论一只爬虫的自我修养8:正则表达式4,python零基础,python

我们就来直接写代码啦:

首先,我们写下下面的代码,来爬取 图片地址:

 
  1. import re

  2. p = r'<img class="BDE_Image" src="[^"]+\.jpg"'

  3. imglist = re.findall(p, html)

  4. for each in imglist:

  5. print(each)

打印的结果为:

 
  1. ============== RESTART: C:\Users\XiangyangDai\Desktop\tieba.py ==============

  2. <img class="BDE_Image" src="https://imgsa.baidu.com/forum/w%3D580/sign=65ac7c3d9e0a304e5222a0f2e1c9a7c3/4056053b5bb5c9ea8d7d0bdadc39b6003bf3b34e.jpg"

  3. <img class="BDE_Image" src="https://imgsa.baidu.com/forum/w%3D580/sign=d887aa03394e251fe2f7e4f09787c9c2/77f65db5c9ea15ceaf60e830bf003af33b87b24e.jpg"

  4. <img class="BDE_Image" src="https://imgsa.baidu.com/forum/w%3D580/sign=0db90d472c1f95caa6f592bef9167fc5/2f78cfea15ce36d34f8a8b0933f33a87e850b14e.jpg"

  5. <img class="BDE_Image" src="https://imgsa.baidu.com/forum/w%3D580/sign=abfd18169ccad1c8d0bbfc2f4f3f67c4/bd2713ce36d3d5392db307fa3387e950342ab04e.jpg"

很显然,这不是我们需要的地址,我们需要的只是后面的部分。我们接下来要解决的问题就是如何将里面的地址提取出来,不少人听到这里,可能就已经开始动手了。但是,别急,我这里有更好的方法。

只需要把图片地址用小括号括起来,即将:

 p = r'<img class="BDE_Image" src="[^"]+\.jpg"' 改为 p = r'<img class="BDE_Image" src="([^"]+\.jpg)"',

大家再来看一下运行后的结果:

 
  1. ============== RESTART: C:\Users\XiangyangDai\Desktop\tieba.py ==============

  2. https://imgsa.baidu.com/forum/w%3D580/sign=65ac7c3d9e0a304e5222a0f2e1c9a7c3/4056053b5bb5c9ea8d7d0bdadc39b6003bf3b34e.jpg

  3. https://imgsa.baidu.com/forum/w%3D580/sign=d887aa03394e251fe2f7e4f09787c9c2/77f65db5c9ea15ceaf60e830bf003af33b87b24e.jpg

  4. https://imgsa.baidu.com/forum/w%3D580/sign=0db90d472c1f95caa6f592bef9167fc5/2f78cfea15ce36d34f8a8b0933f33a87e850b14e.jpg

  5. https://imgsa.baidu.com/forum/w%3D580/sign=abfd18169ccad1c8d0bbfc2f4f3f67c4/bd2713ce36d3d5392db307fa3387e950342ab04e.jpg

是不是很兴奋,是不是很惊讶,先别急,我先把代码敲完,再给大家讲解。

 
  1. import urllib.request

  2. import re

  3. def open_url(url):

  4. req = urllib.request.Request(url)

  5. req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36')

  6. response = urllib.request.urlopen(url)

  7. html = response.read()

  8. return html

  9. def get_img(url):

  10. html = open_url(url).decode('utf-8')

  11. p = r'<img class="BDE_Image" src="([^"]+\.jpg)"'

  12. imglist = re.findall(p, html)

  13. '''

  14. for each in imglist:

  15. print(each)

  16. '''

  17. for each in imglist:

  18. filename = each.split('/')[-1]

  19. urllib.request.urlretrieve(each, filename, None)

  20. if __name__ == '__main__':

  21. url = "https://tieba.baidu.com/p/4863860271"

  22. get_img(url)

运行结果,就是很多美眉图片出现在桌面了(前提是这个程序在桌面运行,图片自动下载到程序所在文件夹。)

接下来就来解决大家的困惑了:为什么加个小括号会如此方便呢?

这是因为在 findall() 方法中,如果给出的正则表达式是包含着子组的话,那么就会把子组的内容单独给返回回来。然而,如果存在多个子组,那么它还会将匹配的内容组合成元组的形式再返回。

我们还是举个例子:

因为有时候 findall() 如果使用的不好,很多同学就会感觉很疑惑,很迷茫……

拿前面匹配 ip 地址的正则表达式来讲解,我们使用 findall() 来尝试自动从https://www.xicidaili.com/wt/获取 ip 地址:

初代码如下:

 
  1. import urllib.request

  2. import re

  3. def open_url(url):

  4. req = urllib.request.Request(url)

  5. req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36')

  6. reponse = urllib.request.urlopen(req)

  7. html = reponse.read()

  8. return html

  9. def get_ip(url):

  10. html = open_url(url).decode('utf-8')

  11. p = r'(([0,1]?\d?\d|2[0-4]\d|25[0-5])\.){3}([0,1]?\d?\d|2[0-4]\d|25[0-5])'

  12. iplist = re.findall(p, html)

  13. for each in iplist:

  14. print(each)

  15. if __name__ == "__main__":

  16. url = "https://www.xicidaili.com/wt/"

  17. get_ip(url)

运行结果如下:

 
  1. ============== RESTART: C:\Users\XiangyangDai\Desktop\getIP.py ==============

  2. ('180.', '180', '122')

  3. ('248.', '248', '79')

  4. ('129.', '129', '198')

  5. ('217.', '217', '7')

  6. ('40.', '40', '35')

  7. ('128.', '128', '21')

  8. ('118.', '118', '106')

  9. ('101.', '101', '46')

  10. ('3.', '3', '4')

得到的结果让我们很迷茫,为什么会这样呢?这明显不是我们想要的结果,这是因为我们在正则表达式里面使用了 3 个子组,所以,findall() 会自作聪明的把我们的结果做了分类,然后用 元组的形式返回给我们。

那有没有解决的方法呢?

要解决这个问题,我们可以让子组不捕获内容。

我们查看 -> Python3 正则表达式特殊符号及用法(详细列表),寻求扩展语法。

让子组不捕获内容,扩展语法 就是非捕获组:

《零基础入门学习Python》第060讲:论一只爬虫的自我修养8:正则表达式4,python零基础,python

所以我们的初代码修改如下:

 
  1. import urllib.request

  2. import re

  3. def open_url(url):

  4. req = urllib.request.Request(url)

  5. req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36')

  6. reponse = urllib.request.urlopen(req)

  7. html = reponse.read()

  8. return html

  9. def get_ip(url):

  10. html = open_url(url).decode('utf-8')

  11. p = r'(?:(?:[0,1]?\d?\d|2[0-4]\d|25[0-5])\.){3}(?:[0,1]?\d?\d|2[0-4]\d|25[0-5])'

  12. iplist = re.findall(p, html)

  13. for each in iplist:

  14. print(each)

  15. if __name__ == "__main__":

  16. url = "https://www.xicidaili.com/wt/"

  17. get_ip(url)

运行得到的结果也是我们想要的 ip 地址了,如下:

 
  1. ============== RESTART: C:\Users\XiangyangDai\Desktop\getIP.py ==============

  2. 183.47.40.35

  3. 61.135.217.7

  4. 221.214.180.122

  5. 101.76.248.79

  6. 182.88.129.198

  7. 175.165.128.21

  8. 42.48.118.106

  9. 60.216.101.46

  10. 219.245.3.4

  11. 117.85.221.45

接下来我们又回到文档:

另外还有一些使用的方法,例如:

finditer() ,是将结果返回一个迭代器,方便以迭代方式获取数据。

sub() ,是实现替换的操作。

在Python3 正则表达式特殊符号及用法(详细列表)中也还有一些特殊的语法,例如:

(?=...):前向肯定断言。

(?!...):前向否定断言。

(?<=...):后向肯定断言。

(?<!...):后向肯定断言。

这些都是非常有用的,但是呢,这些内容有点多了,如果说全部都讲正则表达式的话,那我们就是喧宾夺主了,我们主要讲的是 网络爬虫 哦。文章来源地址https://www.toymoban.com/news/detail-606230.html

所以,大家还是要自主学习一下,多看,多学,多操作。

到了这里,关于《零基础入门学习Python》第060讲:论一只爬虫的自我修养8:正则表达式4的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【100天精通python】Day41:python网络爬虫开发_爬虫基础入门

    目录  专栏导读  1网络爬虫概述 1.1 工作原理 1.2 应用场景 1.3 爬虫策略

    2024年02月12日
    浏览(34)
  • 【零基础入门Python爬虫】第三节 Python Selenium

    Python Selenium 是一种自动化测试框架,可以模拟用户在浏览器中的交互行为。它是一个基于浏览器驱动程序的工具,可用于Web应用程序测试、数据采集等方面,能够让开发人员通过代码自动化地模拟用户在浏览器中的操作,并获取到所需的数据。 Selenium的主要优势是它可以模拟

    2024年02月04日
    浏览(36)
  • python爬虫基础入门——利用requests和BeautifulSoup

    (本文是自己学习爬虫的一点笔记和感悟) 经过python的初步学习,对字符串、列表、字典、元祖、条件语句、循环语句……等概念应该已经有了整体印象,终于可以着手做一些小练习来巩固知识点,写爬虫练习再适合不过。 爬虫的本质就是从网页中获取所需的信息,对网页

    2024年02月15日
    浏览(43)
  • Python基础入门之网络爬虫利器:lxml详解

    导语:网络爬虫是数据采集和信息提取的重要工具之一。在Python中,lxml库是一款功能强大且高效的网络爬虫工具,具有解析HTML和XML文档、XPath定位、数据提取等功能。本文将详细介绍lxml库的使用方法,并提供相应的代码示例。 lxml库 lxml是一个HTML/XML的解析器,主要的功能是

    2024年02月07日
    浏览(33)
  • Python爬虫学习笔记(一)---Python入门

    pycharm的安装可以自行去搜索教程。 pycharm的使用需要注意: 1、venv文件夹是这个项目的虚拟环境文件,应与代码文件分开。 2、如果运行没有,最后一行是“进程已结束,退出代码为0”,如果最后不是0,那么,就说明运行出错。 print括号中使用单引号或者双引号都是可以的。

    2024年01月17日
    浏览(26)
  • 【超简版,代码可用!】【0基础Python爬虫入门——下载歌曲/视频】

    科普: get:公开数据 post:加密 ,个人信息 科普: 爬哪个网址? 怎么找视频/音频网址? 都是指URL,并非最上方的地址 把URL复制即可 如下操作: 解释:【看不懂没关系!请看下面的代码!可以直接套用】 res=requests.get(url) # 发送请求 print(res.content) # 获取二进制数据 wb 写入

    2024年01月24日
    浏览(42)
  • 014集:python访问互联网:网络爬虫实例—python基础入门实例

    以pycharm环境为例: 首先需要安装各种库(urllib:requests:Openssl-python等) python爬虫中需要用到的库,大致可分为:1、实现 HTTP 请求操作的请求库;2、从网页中提取信息的解析库;3、Python与数据库交互的存储库;4、爬虫框架;5、Web框架库。 一、请求库 实现 HTTP 请求操作 1、

    2024年01月16日
    浏览(36)
  • 最简单的python爬虫案例,适合入门学习

    用python从网页爬取数据,网上相关文章很多,但能让零基础初学者轻松上手的却很少。可能是有的作者觉得有些知识点太简单不值得花费精力讲,结果是难者不会会者不难,初学者常常因此而蒙圈。本人也是小白,刚摸索着爬了两个简单的网页数据,经历了初学者易犯的各种

    2024年02月08日
    浏览(34)
  • Python爬虫入门:HTTP与URL基础解析及简单示例实践

    在数字化时代,数据已成为一种宝贵的资源。Python作为一种强大的编程语言,在数据采集和处理方面表现出色。爬虫技术,即网络爬虫,是Python中用于数据采集的重要工具。本文作为Python爬虫基础教程的第一篇,将深入讲解URL和HTTP的基础知识,为后续的爬虫实践打下坚实的基

    2024年03月22日
    浏览(33)
  • Python爬虫学习笔记(一)————网页基础

    目录 1.网页的组成 2.HTML (1)标签 (2)比较重要且常用的标签: ①列表标签 ②超链接标签 (a标签) ③img标签:用于渲染,图片资源的标签 ④div标签和span标签 (3)属性 (4)常用的语义化标签 (5)元素的分类及特点 ①块元素 ②行内元素 ③行内块元素 (6)文件路径 (

    2024年02月15日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包