Python 数据获取(二)—— 数据解析与正则表达式

一、 数据解析常用方法

  • 正则表达式:代码可能比较复杂、正则比较难上手,效率较高、准确性高
  • BeautifulSoup(bs4):代码简单,但效率一般
  • xpath解析

这几种方法可以混着用,看哪种简单,本节我们先学习正则表达式。

二、 正则表达式规则

有一个在线正则表达式测试小工具,可以用来学习

https://tool.oschina.net/regex#

1. 常用元字符与量词

2. 贪婪匹配与惰性匹配(重点)

       贪婪匹配:中间尽量多匹配,到最后一个符合的才停下。其实按照之前的理解:.匹配任意字符(除换行符),*重复0或多次,因此基本上中间的所有内容都会匹配到,所以它叫贪婪。

原理是这样的:

.* 往后找到最后一个“游戏”:玩儿吃鸡游戏,晚上一起玩游戏,干嘛呢?打游戏
                                              ---------------------------------------------------------->

       惰性匹配:只匹配第一次符合的,然后就停下。.*跟贪婪匹配一样,但?表示重复0或1次,也就是说如果有多次出现,最多匹配到一个就停下了,所以它叫惰性。

原理是这样的:

.* 往后找到最后一个“游戏”:玩儿吃鸡游戏,晚上一起玩游戏,干嘛呢?打游戏
                                              ---------------------------------------------------------->

? 再往前找,找到第一个游戏:玩儿吃鸡游戏
                                                                <-------------------------------------------

3. 小案例

有这样一个html

<div class=”jay”>周杰伦</div><div class=”jj”>林俊杰</div>

想匹配的效果是:

<div class=”jay”>周杰伦</div>

<div class=”jj”>林俊杰</div>

可以看到,有底色的两部分需要替换。所以我的正则表达式应该对应有两部分惰性匹配:

<div class=”.*?”>.*?</div>

4. 惰性匹配用作分隔符

例如随便一串字符   xxxxxxxxxxbaaaaaabcccccccb

如果我们匹配:.*?b  就表示前面是什么都可以,结尾要是b,相当于就把上面的字符分成列3段

三、 python re模块

1. 函数格式

      re.函数名(r’正则表达式’,’my_strings’,flag)   flag暂时可以不填,后面会用到。比较常用的是re.S,表示.也可以匹配换行符。

2. 几个重点函数

  • ① findall:匹配字符串中所有符合正则的内容,返回一个列表

小知识:

  • r”\d+”那个r表示raw,反转义字符串,建议加,不然会有warning
  • 快速注释/取消注释多行,光标选中,按ctrl + /

② finditer:功能同上,返回迭代器,需要用循环调用.group() 从中取值。迭代器效率更高,也是这里面最常用的一个功能。

③ search:匹配到第一个符合正则的内容就返回。返回一个match对象,需要用.group()从中取值。不用循环,因为只匹配到第一个值就返回。

④ match:匹配以xxx开头,相当于它默认加了^。返回一个match对象,需要用.group()从中取值。不用循环,因为一个字符串只有一个开头。

import re

str = "小明的电话是 10086,小红的电话是 10010"

# findall:匹配字符串中所有符合正则的内容,返回一个列表
# list = re.findall(r'\d+',str)
# print(list)  # 返回结果 ['10086', '10010']

# finditer:功能同上,返回迭代器,需要用循环调用.group()从中取值
# 迭代器效率更高,也是这里面最常用的一个功能
# it = re.finditer(r'\d+',str)
# for i in it:
#     print(i.group())  # 返回结果 10086 和 10010

# search:匹配到第一个符合正则的内容就返回
# 返回一个match对象,需要用.group()从中取值。不用循环,因为只匹配到第一个值就返回。
# s = re.search(r'\d+',str)
# print(s)    # 返回结果 <_sre.SRE_Match object; span=(7, 12), match='10086'>
# print(type(s))      # 返回结果 <class '_sre.SRE_Match'>
# print(s.group())  # 返回结果 10086

# match:匹配以xxx开头,相当于它默认加了^。
# 返回一个match对象,需要用.group()从中取值。不用循环,因为一个字符串只有一个开头。
# str2 = "10086 是小明的电话,10010 是小红的电话"
# s = re.match(r'\d+',str2)
# print(s.group())  # 返回结果 10086

3. 预加载正则表达式

预加载正则表达式相当于先编译好保存起来了,在正则特别复杂时,可以提高一点效率。

re.compile(r'正则表达式')

import re

str = "小明的电话是 10086,小红的电话是 10010"
obj = re.compile(r'\d+')
it = obj.finditer(str)
for i in it:
    print(i.group()) # 返回结果同finditer

四、 综合运用

我想取出这段html中的id和中文名,拼音不需要

<div class='xiaoming'><span id=1>小明</span></div>
<div class='xiaohong'><span id=2>小红</span></div>
<div class='zhangsan'><span id=3>张三</span></div>
<div class='wangwu'><span id=4>王五</span></div>

       类似前面的例子,将要匹配的部分写成惰性匹配。如果要赋值给变量(Django课程也有提到过),python中的用法是 (?P<变量名>.*?)

对应的正则表达式写法很简单:

       注意re.compile中的第二个参数re.S是一个标记位(上面提到的其他函数也有),用途是使.也能匹配换行符。

  • 首先照抄一行

<div class='wangwu'><span id=4>王五</span></div>

  • 把所有有变化的值改成惰性匹配.*?

r”<div class='.*?'><span id=.*?>.*?</span></div>”

  • 要取出的值赋给变量

r”<div class='.*?'><span id=(?P<id>.*?)>(?P<name>.*?)</span></div>”

  • 如果用finditer的话,取值的时候应该写 group("id"),group("name")

代码如下:

import re

s = '''
<div class='xiaoming'><span id=1>小明</span></div>
<div class='xiaohong'><span id=2>小红</span></div>
<div class='zhangsan'><span id=3>张三</span></div>
<div class='wangwu'><span id=4>王五</span></div>
'''

obj = re.compile(r"<div class='.*?'><span id=(?P<id>.*?)>(?P<name>.*?)<",re.S)
it = obj.finditer(s)
for i in it:
    print(i.group("id") + '----' + i.group("name"))

参考:B站视频 P17-P22

2021年最新Python爬虫教程+实战项目案例(最新录制)_哔哩哔哩_bilibili

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hehuyi_In

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值