0
点赞
收藏
分享

微信扫一扫

8.网络爬虫—正则表达式RE实战

Star英 2023-04-23 阅读 39

8.网络爬虫—正则表达式RE实战

正则表达式(Regular Expression)

正则表达式(Regular Expression)是一种用于匹配字符串的工具,它可以根据特定的规则来匹配字符串。正则表达式通常由一组字符和字符集合组成,其中字符集合定义了匹配的字符类型和位置。

re.I

🧾 🧾 语法: re.IGNORECASE 或简写为 re.I

🧾 🧾 含义: 进行忽略大小写匹配

import re  
  
pattern = re.compile('apple', re.I)  
text = 'The apple is red'  
  
match = pattern.search(text)  
  
if match:  
    print(match.group())  
else:  
    print('未找到匹配的字符串')

运行结果:
在这里插入图片描述

在上面的代码中,re.I标志被用来匹配字符串apple,这意味着在匹配时忽略大小写。pattern.search(text) 函数返回一个Match对象,如果找到匹配的字符串,则match.group()方法将被调用并打印出来,否则打印出未找到匹配的字符串。

re.A

🧾 🧾 语法: re.ASCII 或简写为 re.A

🧾 🧾 作用: ASCII表示ASCII码的意思,让 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII,而不是Unicode

以下是一个使用re.ASCII或re.A标志的简单示例:

import re

# 匹配ASCII字符集中的数字和字母
pattern = re.compile(r'\w+', flags=re.ASCII)
text = 'Hello 世界 123'
match = pattern.findall(text)
print(match)


在这里插入图片描述

re.S

🧾🧾 语法: re.DOTALL 或简写为 re.S

🧾🧾 作用: DOT表示.,ALL表示所有,连起来就是.匹配所有,包括换行符\n。默认模式下.是不能匹配行符\n的

以下是一个使用re.DOTALL标志的示例:

import re

text = 'hello\nworld'
pattern = re.compile('.*', re.DOTALL)
match = pattern.match(text)
print(match.group(0))

运行结果:

'hello\nworld'

可以看到,因为使用了re.DOTALL标志,"."符号匹配了换行符,所以整个文本都被匹配了。

需要注意的是,re.DOTALL标志只对"."符号起作用,其他的元字符和字符类仍然按照原来的规则匹配
如果需要匹配包括换行符在内的所有字符,可以使用如下的正则表达式:

pattern = re.compile('.*', re.DOTALL | re.MULTILINE)

re.M

🧾 🧾 语法: re.MULTILINE 或简写为 re.M

🧾 🧾 含义: 多行模式,当某字符串中有换行符\n,默认模式下是不支持换行符特性的,比如:行开头和行结尾,而多行模式下是支持匹配行开头的

例如,如果要匹配字符串apple,可以使用以下代码:


import re

pattern = re.compile('apple', re.MULTILINE)
text = 'The apple is red'

match = pattern.search(text)

if match:
    print(match.group())
else:
    print('未找到匹配的字符串')

运行结果:

在这里插入图片描述

注意:正则语法中^匹配行开头、\A匹配字符串开头,单行模式下它两效果一致,多行模式下\A不能识别\n。

re.X

🧾 🧾 语法: re.VERBOSE 或简写为 re.X

🧾 🧾 作用: 详细模式,可以在正则表达式中加注解

例如:

import re

# 匹配电子邮件地址
pattern = re.compile(r'''
    ^                   # 匹配字符串开头
    [\w\.\+\-]+         # 用户名,可以包含字母、数字、点、加号和减号
    @                   # @ 符号
    [\w\.\-]+           # 域名,可以包含字母、数字、点和减号
    \.                  # . 符号
    [a-zA-Z]{2,4}       # 域名后缀,可以是 2 到 4 个字母
    $                   # 匹配字符串结尾
''', re.VERBOSE)

# 测试正则表达式
print(pattern.match('john.doe+test@example.com'))

输出:

<re.Match object; span=(0, 27), match='john.doe+test@example.com'>

re.L

🧾 🧾 语法: re.LOCALE 或简写为 re.L

🧾 🧾 作用: 由当前语言区域决定 \w, \W, \b, \B 和大小写敏感匹配,这个标记只能对byte样式有效,该标记官方已经不推荐使用,因为语言区域机制很不可靠,它一次只能处理一个 "习惯”,而且只对8位字节有效

使用 re.LOCALE 可能会影响正则表达式的行为,因为它取决于系统的本地化设置。因此,如果需要编写可移植的正则表达式,最好不要使用 re.LOCALE。

以下是一个使用 re.LOCALE 的示例:

import re

# 匹配非字母数字字符
pattern = re.compile(r'\W+', re.LOCALE)

# 测试正则表达式
print(pattern.findall('Hello, 你好!'))

输出:

[',', '!']

re.U

🧾 🧾 语法: re.UNICODE 或简写为 re.U

🧾 🧾 作用: 与 ASCII常量类似,匹配unicode编码支持的字符,但是Python3默认字符串已经是Unicode,所以显得有点多余

在 Python 3 中,默认情况下所有正则表达式都启用了 Unicode 匹配模式,所以在大多数情况下不需要使用 re.UNICODE。

以下是一个使用 re.UNICODE 的示例:

import re

# 匹配非字母数字字符
pattern = re.compile(r'\W+', re.UNICODE)

# 测试正则表达式
print(pattern.findall('Hello, 你好!'))

输出:

[',', '!']

🧾 🧾 理论讲解完毕,结合之前学到的知识和新学到的知识来实战吧!🧾 🧾 !

美某杰实战

import requests
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
}
for i in range(1, 4):
    url = f'https://www.meishij.net/chufang/diy/jiangchangcaipu/?&page={i}'

    html = requests.get(url, headers=headers)


    print(html.text)

运行结果:
在这里插入图片描述
在这里插入图片描述


<div class="c1"><strong>蛤蜊酿虾滑</strong><span>0 评论  0 人气</span><em>朴朴超市</em></div>
						<div class="c2"><ul><li class="li1">4/ 大概30分钟</li><li class="li2">/ 咸鲜味</li></ul></div>	

<div class="c1"><strong>洋葱焖鸡</strong><span>0 评论  2 人气</span><em>东古美食厨房</em></div>
						<div class="c2"><ul><li class="li1">5/ 大概15分钟</li><li class="li2">/ 家常味</li></ul></div>

<div class="c1"><strong>蒜蓉粉丝蒸鲍鱼</strong><span>0 评论  1 人气</span><em>靓杰</em></div>
						<div class="c2"><ul><li class="li1">11/ 大概60分钟</li><li class="li2">/ 家常味</li></ul></div>
'<div class="c1"><strong>(\w+)</strong><span>(.*?)</span><em>(.*?)</em></div>\s*<div class="c2"><ul><li class="li1">(.*?)</li><li class="li2">(.*?)</li></ul></div>',

“.*?” 表示非贪心算法,表示要精确的配对。

“.*”表示贪心算法,表示要尽可能多的匹配

1️⃣1️⃣完整代码如下:

import re
import requests

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
}


def main(index):
    url = f'https://www.meishij.net/chufang/diy/jiangchangcaipu/?&page={index}'

    html = requests.get(url, headers=headers)

    data = re.findall(
        '<div class="c1"><strong>(\w+)</strong><span>(.*?)</span><em>(.*?)</em></div>\s*<div class="c2"><ul><li class="li1">(.*?)</li><li class="li2">(.*?)</li></ul></div>',
        html.text)

    for i in data:
        print(i)


for i in range(1, 4):
    main(i)

运行结果:

在这里插入图片描述

写入csv文件:

先导入:
在这里插入图片描述

f = open('data.csv', 'w+', encoding='gbk', newline='')
csv_f = csv.writer(f)
csv_f.writerow(['菜名', '信息', '作者', '大概步骤', '类型'])

然后把这个代码写进去,就得到一个完整的代码:

import csv
import re
import requests

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
}

f = open('data.csv', 'w+', encoding='gbk', newline='')
csv_f = csv.writer(f)
csv_f.writerow(['菜名', '信息', '作者', '大概步骤', '类型'])


def main(index):
    url = f'https://www.meishij.net/chufang/diy/jiangchangcaipu/?&page={index}'

    html = requests.get(url, headers=headers)
    # print(html.text)

    data = re.findall(
        '<div class="c1"><strong>(\w+)</strong><span>(.*?)</span><em>(.*?)</em></div>\s*<div class="c2"><ul><li class="li1">(.*?)</li><li class="li2">(.*?)</li></ul></div>',
        html.text)
    # print(data)
    for i in data:
        csv_f.writerow(i)
        print(i)


for i in range(1, 4):
    main(i)

f.close()

我们来查看一下csv文件:
在这里插入图片描述

在这里插入图片描述

举报

相关推荐

0 条评论