Re解析(正则表达式解析)

news/2024/7/19 10:20:00 标签: 正则表达式, python, 爬虫

正则表达式基础

元字符

B站教学视频: 正则表达式元字符基本使用

量词

贪婪匹配和惰性匹配

惰性匹配如下两张图,而 .* 就表示贪婪匹配,即尽可能多的匹配到符合的字符串,如果使用贪婪匹配,那么结果就是图中的情况三

python中re模块

re模块的常用方法

python">import re

# findall(正则表达式, 待匹配的字符串) -> 符合正则表达式的内容(以列表的形式返回)
# 含义:匹配字符串中所有符合正则表达式的内容(以列表的形式返回)
res_findall = re.findall(r"\d+", "中国移动:10086,中国联通:10010")
print(res_findall)  # ['10086', '10010']

# re.finditer(正则表达式, 待匹配的字符串) -> 符合正则表达式的内容(以迭代器的形式返回)
# 含义:匹配字符串中所有符合正则表达式的内容(以迭代器的形式返回)
res_finditer = re.finditer(r"\d+", "中国移动:10086,中国联通:10010")
print(res_finditer)  # <callable_iterator object at 0x000001CB2875B340>
for item in res_finditer:
    """
    下面两行输出语句的输出结果如下:
    <re.Match object; span=(5, 10), match='10086'>
    10086
    <re.Match object; span=(16, 21), match='10010'>
    10010
    
    item 中还有其他的方法,如item.start()/item.end()分别表示
    匹配到的字符串在原字符串中的起始索引和结束索引
    """
    print(item)  # 得到match对象
    print(item.group())  # 得到匹配的字符串

# re.search(正则表达式, 待匹配的字符串) -> 符合正则表达式的内容(返回match对象)
# 含义:匹配字符串中第一个匹配到的符合正则表达式的内容(返回match对象)
res_search = re.search(r"\d+", "中国移动:10086,中国联通:10010")
print(res_search)  # <re.Match object; span=(5, 10), match='10086'>
print(res_search.group())  # 10086

# 上述三种方法都是全文匹配,而match是从头开始匹配
# re.match(正则表达式, 待匹配的字符串) -> 符合正则表达式的第一个字符串内容(返回match对象)
# 含义:从待匹配的字符串的第一个字符开始匹配,将匹配到的第一个结果返回,返回的是match对象
res_match = re.match(r"\d+", "中国移动:10086,中国联通:10010")
print(res_match)  # None,字符串开头不是数字,所以等于匹配不成功,结果为空
# print(res_match.group())  # 报错
res_match = re.match(r"\d+", "10086,中国联通:10010")
print(res_match)  # <re.Match object; span=(0, 5), match='10086'>
print(res_match.group())  # 10086

# 预加载
# 应用场景:在爬虫中,想要从网页中匹配到想要的内容,匹配的正则表达式可能会很复杂,
# 而又多次的使用到该正则表达式,则可以预加载正则表达式
# 如下,好处就是该正则可以反复使用
obj = re.compile(r"\d+")
res1 = obj.findall("中国移动:10086,中国联通:10010")
res2 = obj.finditer("中国移动:10086,中国联通:10010")
res3 = obj.search("中国移动:10086,中国联通:10010")
res4 = obj.match("中国移动:10086,中国联通:10010")

分组匹配

python">s = """
    <div class="jay">周杰伦</div>
    <div class="jj">林俊杰</div>
"""
# (?P<name>.*?) 分组匹配(P为大写),相当于把括号中的.*?匹配到的内容给变量name
# 然后通过item.group('name')获取到name的值
# 只要把想要单独获取的内容按以上形式:(?P<xxx>正则表达式) 即可获取
# re.S 的作用就是让 . 也可以匹配到换行符
# flags 是re模块中compile、match、findall等方法的一个参数,具体用法可以百度
obj = re.compile(r'<div class=".*?">(?P<name>.*?)</div>', re.S)
res = obj.finditer(s)
print(res)  # <callable_iterator object at 0x0000020F2E89AEC0>
for item in res:
    """
    输出结果如下:
    <re.Match object; span=(5, 31), match='<div class="jay">周杰伦</div>'>
    <div class="jay">周杰伦</div>
    周杰伦
    <re.Match object; span=(36, 61), match='<div class="jj">林俊杰</div>'>
    <div class="jj">林俊杰</div>
    林俊杰
    """
    print(item)  # <re.Match object; span=(5, 31), match='<div class="jay">周杰伦</div>'>
    print(item.group())  # <div class="jay">周杰伦</div>
    print(item.group('name'))  # 周杰伦

注:关于re模块方法中的flags参数作用,可以百度一下

案例——豆瓣top250(re解析版)

B站视频教程:爬取豆瓣top250电影

python">import requests
import re
import csv

url = "https://movie.douban.com/top250"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
}
resp = requests.get(url, headers=headers)
# print(resp.text)  # 没加headers之前结果为空,说明网站有一些反扒机制
pattern = (r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)</span>.*?'
           r'导演: (?P<director>.*?)&nbsp;.*?主演: (?P<performer>.*?)...<br>.*?'
           r'<span class="rating_num" property="v:average">(?P<score>\d.\d)</span>')

obj = re.compile(pattern, re.S)
res = obj.finditer(resp.text)
# 把获取到的数据存入CSV文件,方便以后对数据进行操作
# 关于CSV文件,请百度
f = open('data.csv', mode='w', encoding='utf-8')
csv_writer = csv.writer(f)  # 表示向文件写入数据
for i in res:
    # print(i.group('name'))
    # print(i.group('director'))
    # print(i.group('performer'))
    # print(i.group('score').strip())
    dic = i.groupdict()  # 将数据以字典形式返回
    # print(dic)
    # 将字典的值按行写入文件,文件中的每一行就是一部电影的信息
    # csv文件中,每一行数据以逗号分隔每个值
    csv_writer.writerow(dic.values())
f.close()
resp.close()
print("数据解析完成!")

部分csv文件内容如下:


http://www.niftyadmin.cn/n/5275769.html

相关文章

【23真题】今晚直播公式宝典带背!

哈喽大家好&#xff0c;现在这个时间节点&#xff0c;有很多同学开始刷真题了&#xff01;所以23真题系列正式启动&#xff01;小马哥将全面发布23真题及详细解析&#xff01; 另外和押题卷一样&#xff0c;还是希望大家可以自己提前打印出来&#xff0c;纸质才能记得更牢固&a…

计算机网络 网络层下 | IPv6 路由选择协议,P多播,虚拟专用网络VPN,MPLS多协议标签

文章目录 5 IPv65.1 组成5.2 IPv6地址5.3 从IPv4向IPv6过渡5.3.1 双协议栈5.3.2 隧道技术 6 因特网的路由选择协议6.1 内部网关协议RIP6.2 内部网关协议 OSPF基本特点 6.3 外部网关协议 BGP6.3.1 路由选择 6.4 路由器组成6.4.1 基本了解6.4.2 结构 7 IP多播7.1 硬件多播7.2 IP多…

无障碍(Accessibility)设计在前端开发中的重要性

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

Linux的SSH(远程登录)

SSH定义&#xff1a; SSH&#xff08;Secure Shell 的缩写&#xff09;是一种网络协议&#xff0c;用于加密两台计算机之间的通信&#xff0c;并且支持各种身份验证机制。 实务中&#xff0c;它主要用于保证远程登录和远程通信的安全&#xff0c;任何网络服务都可以用这个协议…

Next.js 学习笔记(三)——路由

路由 路由基础知识 每个应用程序的骨架都是路由。本页将向你介绍互联网路由的基本概念以及如何在 Next.js 中处理路由。 术语 首先&#xff0c;你将在整个文档中看到这些术语的使用情况。以下是一个快速参考&#xff1a; 树&#xff08;Tree&#xff09;&#xff1a;用于可…

力扣 面试经典150算法题

1合并两个有序数组88. 合并两个有序数组-CSDN博客简单23

【力扣100】108.将有序数组转化为二叉搜索树

添加链接描述 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def sortedArrayToBST(self, nums: List[int…

浪潮信息KOS服务器操作系统:经过周密考虑后的智慧之选

文章目录 一、引言二、服务器操作系统概述三、选择服务器操作系统的关键因素四、评估服务器操作系统的标准五、选择服务器操作系统的实践经验六、浪潮信息KOS服务器操作系统一、稳定可靠二、高效协同三、全天候运维四、广泛兼容 七、总结与展望 浪潮信息信息KOS是浪潮信息信息基…