一、OS
import os
# os.mkdir(文件夹路径) - 在指定的位置创建指定文件夹
# os.mkdir('files/test')
# os.path.exists(文件夹路径/文件路径) - 判断指定文件夹或者文件是否存在
if not os.path.exists('files/test'):
os.mkdir('files/test')
二、正则(regular)
2.1 正则的作用
正则表达式是一种可以让复杂的字符串变得简单的工具。
写正则表达式就是用正则符号来描述字符串规则。
import re
from re import *
# 案例1:判断一个字符串是否是一个合法的手机号码
tel = '23297293329'
result = re.fullmatch(r'1[3-9]\d{9}', tel)
if result:
print('合法')
else:
print('不合法')
# 案例2:提取字符串中所有的数字子串,并且求和
str1 = '睡觉89jss=3.45-换手23=抗生素820=8'
result = re.findall(r'\d+\.?\d*', str1)
print(sum([float(x) for x in result]))
三、正则语法
3.1 re模块 - 提供了python中所有和正则相关的函数
"""
1)fullmatch(正则, 字符串) - 用整个字符串和正则匹配,匹配成功返回匹配对象,匹配失败返回None
2)findall(正则, 字符串) - 获取字符串中所有满足正则的子串,默认返回一个列表,列表中的元素是所有匹配到的子串(存在自动捕获现象)
3)search(正则, 字符串) - 匹配第一个满足正则的子串,匹配成功返回匹配对象,匹配失败返回None
4)split(正则, 字符串) - 将字符串中所有满足正则的子串作为切割点进行切割
5)split(正则, 字符串, N) - 将字符串中前N个满足正则的子串作为切割点进行切割
6)sub(正则, 字符串1, 字符串2) - 将字符串2中所有满足正则的子串都替换成字符串1
7)sub(正则, 字符串1, 字符串2, N)
8)finditer(正则, 字符串) - 获取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是匹配对象
9)match(正则, 字符串) - 匹配字符串开头
"""
注意:Python中表达式一个正则表达式一般使用r字符串
from re import fullmatch, findall, search, split, sub, finditer, match
str1 = '技术7晋级赛7jsks7就开始看'
print(str1.split('7', 2))
str1 = '技术22晋级赛709jsks511就开始80看'
print(split(r'\d+', str1, 2))
str1 = '技术22晋级赛709jsks511就开始80看'
print(sub(r'\d', '+', str1))
message = '妈的,SB,都打起来了你还在打野!草!F u c k'
print(sub(r'(?i)妈的|sb|草|操|艹|f\s*u\s*c\s*k', '*', message))
str1 = '技术22晋级赛709jsks511就开始80看'
result = finditer(r'\d+', str1)
print(list(result))
print(fullmatch(r'\d{3}', '234'))
print(match(r'\d{3}', '234卡咖啡'))
# 1)忽略大小写: (?i)
print(fullmatch(r'(?i)abc', 'abc'))
print(fullmatch(r'(?i)abc', 'Abc'))
print(fullmatch(r'(?i)abc', 'ABc'))
print(fullmatch(r'(?i)abc', 'aBc'))
# 2)单行匹配:(?s)
# 多行匹配(默认):. 不能和换行符进行匹配
# 单行匹配:. 可以和换行符进行匹配
print(fullmatch(r'abc.123', 'abc\n123')) # None
print(fullmatch(r'(?s)abc.123', 'abc\n123')) # <re.Match object; span=(0, 7), match='abc\n123'>
msg = """
'name:"jshf2-
2ss技术"'
"""
result = findall(r'(?s)name:"(.+)"', msg)
print(result)
3.2 正则符号
第一类符号:匹配类符号
1)普通符号 - 在正则表达式中表符号本身的符号
result = fullmatch(r'abc', 'abc')
print(result)
2). - 匹配任意一个字符
result = fullmatch(r'.bc', '*bc')
print(result)
result = fullmatch(r'.bc.', '1bcu')
print(result)
3)\d - 匹配任意一个数字字符
result = fullmatch(r'\d\dabc', '08abc')
print(result)
4)\s - 匹配任意一个空白字符
# 空白字符:空格(' ')、换行('\n')、水平制表符('\t')
result = fullmatch(r'123\sabc', '123\tabc')
print(result)
result = fullmatch(r'\d\d\s\d', '89 2')
print(result)
5)\w - 匹配任意一个字母、数字、下划线或者中文
result = fullmatch(r'abc\w123', 'abc和123')
print(result)
6)\D、\S、\W - 分别和\d、\s、\w的功能相反
result = fullmatch(r'abc\D123', 'abc8123')
print(result) # None
7)[字符集] - 匹配在字符集中的任意一个字符
[abc] - 匹配a或者b或者c
[abc\d] - 匹配a或者b或者c或者任意数字: [abc0123456789]
[1-5] - 匹配字符1到字符5中的任意一个字符
[a-z] - 匹配任意一个小写字母
[A-Z] - 匹配任意一个大写字母
[a-zA-Z] - 匹配任意一个字母
[a-zA-Z\d] - 匹配任意一个字母或者数字
[a-z=%]
[\u4e00-\u9fa5] - 匹配任意一个中文
result = fullmatch(r'abc[M9你]123', 'abc你123')
print(result)
result = fullmatch(r'abc[M9你\d]123', 'abc0123')
print(result)
result = fullmatch(r'abc[\u4e00-\u9fa5]123', 'abc和123')
print(result)
8)
#[^字符集] - 匹配不在字符集中的任意一个字符
result = fullmatch(r'abc[^MN]123', 'abc)123')
print(result)
result = fullmatch(r'abc[^a-z]123', 'abc$123')
print(result)
result = fullmatch(r'abc[M^N]123', 'abcM123')
print(result)
第二类符号:匹配次数符号
匹配类符号匹次数
1)* - 任意次数(0次或者1次或者次数)
a* - a出现任意多次
\d* - 任意多个任意数字
[abc]*
result = fullmatch(r'1a*2', '1aaaaaaaa2')
print(result)
result = fullmatch(r'M\d*N', 'M13599N')
print(result)
result = fullmatch(r'M[3-9]*N', 'M3489N')
print(result)
2)+ - 一次或者多次(至少1次)
result = fullmatch(r'1a+2', '1aaa2')
print(result)
3)? - 0次或者1次
result = fullmatch(r'1a?2', '1aa2')
print(result) # None
4){}
{N} - N次
{M,N} - M到N次
{M,} - 至少M次
{,N} - 最多N次
result = fullmatch(r'1a{3}2', '1aaa2')
print(result)
result = fullmatch(r'1a{3,6}2', '1aaaa2')
print(result)
# 练习:写一个正则表达式,可以匹配任意一个除了0的整数。
# 合法:233、+234、-7283、100、-2000
# 不合法:0、0002、2.23、+-200
result = fullmatch(r'[+-]?[1-9]\d*', '2000')
print(result)
5)贪婪和非贪婪模式
在匹配次数不确定的时候,如果有多种次数都可以匹配成功,贪婪取最多的那个次数,非贪婪取最少的那个次数。(默认是贪婪模式)
贪婪模式:+、?、、{M,N}、{M,}、{,N}
非贪婪模式:+?、??、?、{M,N}?、{M,}?、{,N}?
# 'ahkmb'、'ahkmb收拾b'、'ahkmb收拾b收b'
result = search(r'a.+b', '收拾收拾收ahkmb收拾b收b3]er2')
print(result) # <re.Match object; span=(5, 15), match='ahkmb收拾b收b'>
result = search(r'a.+?b', '收拾收拾收ahkmb收拾b收b3]er2')
print(result) # <re.Match object; span=(5, 10), match='ahkmb'>
# 'ahkmb'
result = search(r'a.+b', '收拾收拾收ahkmb3]er2')
print(result) # <re.Match object; span=(5, 10), match='ahkmb'>
result = search(r'a.+?b', '收拾收拾收ahkmb3]er2')
print(result) # <re.Match object; span=(5, 10), match='ahkmb'>
第三类符号:分组和分支
1)分组 - ()
正则表达式中可以用()将部分内容括起来表示一个整体;括号括起来的部分就是一个分组。
a. 整体操作的时候需要分组
b. 重复匹配 - 正则中可以通过\M来重复它前面第M个分组匹配的结果
c. 捕获 - 提取分组匹配到的结果(捕获分为自动捕获(findall)和手动捕获)
# '23M'、'89K10L'、'09H23P90Q33W'、...
result = fullmatch(r'(\d\d[A-Z])+', '09H23P90Q33W')
print(result)
# '23M23'、'90K90'、'78N78'、'10U10'
result = fullmatch(r'(\d\d)[A-Z]\1', '90K90')
print(result)
result = fullmatch(r'(\d{3})([a-z]{2})=\2\1{2}', '234km=km234234')
print(result)
# findall在正则表达式中有分组的时候,会自动提取正则匹配结果中分组匹配到的内容
message = '技术上234,jsskf8992==技术njk==9223-ssjs233结束时间453'
result = findall(r'[\u4e00-\u9fa5](\d+)', message)
print(result)
# 匹配对象.group(N) - 获取匹配结果中指定分组匹配到的内容
# 提取身高
message = '我是小明,今年23岁,身高180厘米,体重70kg'
result = search(r'身高(\d+)厘米,体重(\d+)kg', message)
print(result) # <re.Match object; span=(11, 25), match='身高180厘米,体重70kg'>
print(result.group()) # '身高180厘米,体重70kg'
print(result.group(1), result.group(2)) # 180 70
2)分支 - |
正则1|正则2|正则3|… - 先用正则1进行匹配,匹配成功直接成功;匹配失败用正则2进行匹配,…
result = fullmatch(r'\d{3}|[a-z]{2}', 'mn')
print(result)
# 'abc34'、'abcKJ'、'abc78'、'abcOP'
result = fullmatch(r'abc\d\d|abc[A-Z]{2}', 'abc23')
print(result)
result = fullmatch(r'abc(\d\d|[A-Z]{2})', 'abcKS')
print(result)
转义符号:在本身具有特殊功能或者特殊意义的符号前加 \ ,让特殊符号变成普通
# 匹整数部分和小数部分都是两位数的小数
result = fullmatch(r'\d\d\.\d\d', '23.45')
print(result)
result = fullmatch(r'\d\+\d', '3+4')
print(result)
# '(amd)'
result = fullmatch(r'\([a-z]{3}\)', '(jsk)')
print(result)
注意:单独存在有特殊意义的符号,在[]中它的功能会自动消失
result = fullmatch(r'\d[+.?*()\]]\d', '3]4')
print(result)
第四类:检测类符号
是在匹配成功的时候,检测所在的位置是否符合要求
\b - 检测是否是单词边界(任何可以将不同的单词进行区分的符号:空白符号、标点符号、字符串开头、字符串结尾)
^ - 检测是否是字符串开头
$ - 检测是否是字符串结尾
from re import fullmatch, findall
print(fullmatch(r'abc\s\b123', 'abc 123'))
msg = '238jshs90睡觉睡觉2838,换手89,100 还是说78世界上78, 628.829=sjs好几家899'
result = findall(r'\b\d+', msg)
print(result)
result = findall(r'^\d+', msg)
print(result)
result = findall(r'\d+$', msg)
print(result)
四、案例
import requests
from re import findall
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
}
response = requests.get('https://movie.douban.com/top250?start=0&filter=', headers=headers)
# print(response.text)
result = findall(r'<img width="100" alt="(.+?)"', response.text)
print(result)
爬取豆瓣案例
import csv
import requests
from re import findall
def get_one_page(start=0):
# 1. 获取网页数据
url = f'https://movie.douban.com/top250?start={start}&filter='
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
}
response = requests.get(url, headers=headers)
html = response.text
# print(html)
# 2. 解析数据
# 1)所有电影的名字
names = findall(r'<img width="100" alt="(.+?)"', html)
# 2)所有电影的上映时间、国家和类型
info = findall(r'(?s)<p class="">(.+?)</p>', html)
info = [x.strip().split('\n')[-1].strip() for x in info]
times = []
countries = []
types = []
for x in info:
result = x.split(' / ')
times.append(result[0])
countries.append(result[1])
types.append(result[2])
# 3)评分
score = findall(r'<span class="rating_num" property="v:average">(.+?)</span>', html)
# 4)评论人数
comment = findall(r'<span>(\d+)人评价</span>', html)
data = map(lambda i1, i2, i3, i4, i5, i6: (i1, i2, i3, i4, i5, i6), names, score, comment, times, countries, types)
# 将数据保存到csv文件中
w2.writerows(data)
print('-------------------------------一页获取完成-----------------------')
def get_one_page2():
# 1. 获取网页数据
url = 'https://movie.douban.com/top250?start=0&filter='
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
}
response = requests.get(url, headers=headers)
html = response.text
# print(html)
# 2. 解析数据
result = findall(r'(?s)<img width="100" alt="(.+?)".+?<p class="">(.+?)</p>.+?<span class="rating_num" property="v:average">(.+?)</span>.+?<span>(\d+)人评价</span>', html)
print(result)
from datetime import datetime
from csv import writer
if __name__ == '__main__':
f = open('files/top250.csv', 'w', encoding='utf-8', newline='')
w2 = writer(f)
w2.writerow(['电影名称', '评分', '评论人数', '上映时间', '国家', '类型'])
for x in range(0, 226, 25):
get_one_page(x)
f.close()