正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
Regular Expression,正则表达式,一种使用表达式的方式对字符串进行匹配的语法规则
我们抓取到的网页源代码本质上就是一个超长的字符串,想从里面提取内容,用正则再合适不过了
正则的优点:速度快,效率高,准确性高
正则的缺点:新手上手难点有点高
元字符:
1 . 匹配除换行符以外的任意字符
2 \w 匹配字母或者数字或者下划线
3 \s 匹配任意空白字符
4 \d 匹配数字
5 \n 匹配换行符
6 \t 匹配制表符tab
7 \b 匹配一个单词的结尾
8 ^ 匹配字符串的开始
9 $ 匹配字符串的结尾
10 \W 匹配非字母或下划线或数字
11 \D 匹配非数字
12 \S 匹配非空白符
13 | 匹配|前或者后的内容
14 () 匹配括号内的表达式,也表示一个组
量词:
1 * 重复零次或者多次
2 + 重复1次或者多次
3 ? 重复零次或者一次
4 {n} 重复n次
5 {n,} 重复n次或者更多次
6 {n,m} 重复n到m次
实例一
# 1.定位到2021必看片 # 2.从2021必看片中提取到子页面的链接地址 # 3.请求子页面的链接地址,拿到我们想要的下载地址。。。。 import requests import re url = 'https://www.dytt89.com/' resp = requests.get(url)# 若加上verify=False 去掉安全验证 resp.encoding = 'gb2312' # 拿到ul里面的li obj_1 = re.compile(r'2021必看热片.*?<ul>(?P<ul>.*?)</ul>', re.S) obj_2 = re.compile(r"<a href='(?P<href>.*?)'", re.S) obj_3 = re.compile(r'◎片 名(?P<movie>.*?)<br />.*?<td ' r'style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<download>.*?)">', re.S) result_1 = obj_1.finditer(resp.text) child_href_list = [] for it in result_1: ul = it.group('ul') # 提取子页面链接 result_2 = obj_2.finditer(ul) for itt in result_2: # 拼接子页面的url地址: 域名 + 子页面地址 child_href = url + itt.group('href').strip('/') child_href_list.append(child_href) # 把子页面链接保存起来 # 提取子页面内容 for href in child_href_list: child_resp = requests.get(href) child_resp.encoding = 'gb2312' result_3 = obj_3.search(child_resp.text) print(result_3.group("movie")) print(result_3.group("download")) ''' re 正则的基本使用已了解 若在请求里加上verify=False 去掉安全验证 encoding 字符编码的转换 '''
实例二
# 拿到页面源代码, requests # 通过re来提取想要的有效信息 re import csv import requests import re # 伪装头 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' } # 目标网址 url = "https://movie.douban.com/top250" # 发送请求,获取响应 resp = requests.get(url, headers=headers) page_content = resp.text # print(page_content) # 解析数据 obj = re.compile(r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)' r'</span>.*?<p class="">.*?<br>(?P<year>.*?) .*?<span ' r'class="rating_num" property="v:average">(?P<score>.*?)</span>.*?' r'<span>(?P<num>.*?)人评价</span>', re.S) # 开始匹配 + 本地保存 result = obj.finditer(page_content) f = open("data.csv", mode="w", encoding="utf8") csvwriter = csv.writer(f) for it in result: # print(it.group("name")) # print(it.group("score")) # print(it.group("num")) # print(it.group("year").strip()) dic = it.groupdict() dic['year'] = dic['year'].strip() csvwriter.writerow(dic.values()) f.close() print("over!")