Bootstrap

【数据解析概述—RE】

[python爬虫笔记]

💕学习爬虫的第四天💕

今天给大家分享一些有关数据解析的概述。python爬虫中存在三种不同的数据解析方法。分别是RE(正则表达式)解析、bs4中的Beautifulsoup解析以及xpath解析。今天主要介绍一下RE的用法。

概述

当我们使用python爬虫拿到了页面的源码之后就不知道该这么办了,有的还沉浸在拿到源码的兴奋中(嘻嘻~呃……这么说话会不会有人打我😱),当然对于像我一样的小白来说,拿到了源码自然很高兴。
但是拿到了源码只是爬虫的第一步,真正的核心在于对数据的解析提取。一般来说,爬虫的解析方式有三种:

  1. RE(正则表达式)解析
  2. bs4中的Beautifulsoup解析
  3. xpath解析

注:这三种方式可以混合进行使用,完全以结果作导向,只要能拿到想要的数据,用什么方式不重要。另外bs4写起来简单,但性能差,re最快,性能高,不易理解。

RE解析(Regular Expression)

在Python中需要通过正则表达式对字符串进⾏匹配的时候,可以使⽤⼀个python自带的模块,名字为re。

正则表达式,是一种使用表达式的方式对字符串进行匹配的语法规则。

  • 正则的优点:速度快,效率高,准确性高;
  • 正则的缺点:新手上手难度高。

抓取的网页源代码本质上就是一个超长的字符串;

正确的语法:使用元字符进行排列组合用来匹配字符串,在线测试正则表达式在线工具 —— OSCHINA.NET社区(https://tool.oschina.net/)

元字符:具有固定含义的特殊符号。

具体学习链接:==正则表达式30分钟入门教程 | 菜鸟教程 (runoob.com)==

常用元字符

.	 匹配除换行符以外的任意字符

\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字

\n 匹配一个换行符
\t 匹配一个制表符

# 以下两个用在校验最多
^	 匹配字符串的开始
$	 匹配字符串的结尾

\W 匹配非字母或数字或下划线
\D 匹配非数字
\S 匹配非空白符

a|b 匹配字符a或字符b

() 匹配括号内的表达式,也表示一个组···这里面的表达式必须是连续写

#以下连个为组,想要连续匹配时不能有分割符
[...] 匹配字符组中的字符			组里边有的才会被匹配
[^...] 匹配除了字符组中字符的所有字符

量词:控制前面的元字符出现的次数

*	 重复零次或更多次
?	重复零次或一次
+	 重复一次或更多次

{n}   重复n次		比如\d{5}=>表示\d被重复了5{n,}  重复n次或更多次
{n,m} 重复n到m次

贪婪匹配和惰性匹配

.*	   贪婪匹配		=>	尽可能多的让*匹配
.*? 	惰性匹配	 =>	 尽可能少的让.*匹配

爬虫中用的最多的就是惰性匹配

这些符号并不是要求全部记住,用的时候再拿来用就行了,但是必须要知道其中的含义和语法。
好了,既然我们已经了解了大致的语法,那我们接下来说一说常用的查询函数。
一般常用的函数包括4种:

  1. findall:匹配字符串中所有符合正则的内容
  2. finditer:匹配字符串中所有的内容【返回的是迭代器】,从迭代器中拿到内容需要.group()
  3. search,为全文搜索。找到一个结果就返回,返回的结果是match对象。拿到数据需要.group()
  4. match是从头开始匹配,默认在表达式中添加了一个^,若前面有不符合正则表达式的字符则会报错.

这4种函数的参数包含三个,分别为patternstringflags 关键参数在于patternstring

具体的实例如下:

# 使用RE

import re

# 1. findall:匹配字符串中所有符合正则的内容
lst = re.findall(r"\d+", "我的电话号是:10086,女朋友的电话号是10010")
print(lst)  # ['10086', '10010'] 列表的效率不高

# 2. finditer:匹配字符串中所有的内容【返回的是迭代器】,从迭代器中拿到内容需要.group()
it = re.finditer(r"\d+", "我的电话号是:10086,女朋友的电话号是10010")
# <callable_iterator object at 0x000001652885BE20>

print(it)
for i in it:
    # print(i)
    """
    match对象:
    <re.Match object; span=(7, 12), match='10086'>
    <re.Match object; span=(21, 26), match='10010'>
    """
    print(i.group())  # 10086  10010

print("")

# 3. search,为全文搜索。找到一个结果就返回,返回的结果是match对象。拿到数据需要.group()
s = re.search(r"\d+", "我的电话号是:10086,女朋友的电话号是10010")
# match对象:<re.Match object; span=(7, 12), match='10086'>
print(s.group())  # 10086

print("-------")

# 4. match是从头开始匹配,默认在表达式中添加了一个^,若前面有不符合正则表达式的字符则会报错
# st = re.match(r"\d+", "我的电话号是:10086,女朋友的电话号是10010")
# print(st)   # None
# print(st.group())  # AttributeError: 'NoneType' object has no attribute 'group' => 表明st是空的
st2 = re.match(r"\d+", "10086,女朋友的电话号是10010")
print(st2)  # <re.Match object; span=(0, 5), match='10086'>
print(st2.group())  # 10086

除此之外,为了避免一直这4种函数或者说提高效率和代码可读性,我们可以采用预加载正则
所谓“预加载正则”,顾名思义。就是规定一个样式,这个样式可以是多条的,使用这个提前加载好的规则去匹配想要的内容。主要用到的函数是compile()
预加载正则种可以正常调用所需函数。
在这里插入图片描述
使用的样式如下:

# 预加载正则表达式 compile()
odj = re.compile(r"\d+")    # 预加载正则
result = odj.finditer("我的电话号是:10086,女朋友的电话号是10010")  # 这里只需要填写字符串
for item in result:
    print(item.group())  # 10086  10010

说了这么多,不知道你有没有看的明白💝。
在这里插入图片描述
算了,给你来点《实例》让你瞧瞧。
在这里插入图片描述

# 使用RE中的预加载
# 快速向下复制粘贴:ctrl+D
import re

s = """
<div class='jfaj'><span id='1001'>张杰</span></div>
<div class='gsa'><span id='1002'>邓紫棋</span></div>
<div class='hdfs'><span id='1003'>王嘉欣</span></div>
<div class='hdsr'><span id='1004'>白月光</span></div>
"""
# 原始预加载
# odj = re.compile(r"<div class='.*?'><span id='.*?'>.*?</span></div>", re.S)  # re.S => 让.能匹配换行符
# 想要进一步获取内容,需要设置一个名字.在取名字的时候要注意是大写的P (?P<名字>正则)
odj2 = re.compile(r"<div class='.*?'><span id='.*?'>(?P<aaa>.*?)</span></div>", re.S)  # re.S => 让.能匹配换行符
result = odj2.finditer(s)
for i in result:
    # print(i.group())
    """
    <div class='jfaj'><span id='1001'>张杰</span></div>
    <div class='gsa'><span id='1002'>邓紫棋</span></div>
    <div class='hdfs'><span id='1003'>王嘉欣</span></div>
    <div class='hdsr'><span id='1004'>白月光</span></div>
    """
    # 想要拿到其中的任意内容,就要将对应组名作为参数传递给group
    print(i.group("aaa"))
    """
    张杰
    邓紫棋
    王嘉欣
    白月光

好了,今天分享到这儿,明天再见💕~

;