正则表达式
正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在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!")