title: python_汇总
author: 大海(刘光银)
top: 2
categories:
- python
tags:
- reading
Python基础
注释
输出语句
变量
标识符
数据类型
用户输入
类型转换
运算符
注释
使用自己语言描述代码的功能 不属于程序 只是给使用者解读使用
注释有两种:
单行注释 # 注释内容
多行注释 '''注释的内容‘’‘
输出语句
print -- 输出语句 将内容输出给用户查看的 封装的是打印功能
函数 print()
print函数的格式
*args # 表示的是输出的内容,输出内容可以是一个也可以是多个 每个内容之间使用逗号隔开
sep=' ' # 多个内容之间的分隔符 默认是空格
end='\n' # 输出语句的结束语 \n 换行 \t 制表符
file=None # 将输出的内容指定的文件中
# 扩展知识:文件写入
# 指定打开文件 open('文件路径','打开的模式')
# 打开的模式 r 读取内容 w 写入内容
变量
变量的官方概念:变量是用来存储数据的,以便后期的使用和修改
name = "张三" 变量还提供一个为数据标记描述性的名字【变量名】,我们可以在程序中根据这个名字能更好得阅读和理解该变量的作用,要注意取名称时要“见名知意”
简单理解:变量就是一个存储数据的容器
声明变量的方式:
变量名 = 数据 例如;a = 11
一次声明多个:变量名1,变量名2 = 数据1,数据2 例如:a,b=1,2
注意:变量在使用之前一定要先声明,并且进行初始化赋值
没有加双引号或者单引号 代表数值 加了的叫字符串
标识符
用于程序中自定义名字的规范
标识符的组成:英文字母、数字、下划线
自定义名称的时候要注意:
1.不能以数字开头 2.不能使用Python的关键字【变了颜色的不要用】
数据类型
变量是用来存储数据 数据的格式是多样化
变量对应的数据类型是根据赋予的值来确定的
数值类型:
整型 : int
python2.x中整型有两种 int 和 long
int 内存大小 4位 4bit long 8B
python3.x以后只有int 具有long的性质
浮点型 : float
用来存储小数的类型
复数型 : complex
具有实部+虚部:3+4j
布尔类型 : bool
描述状态的类型 值只有True和False 也可以使用1和0
字符类型:str
字符串类型的标识:使用单引号或者双引号包含单个字符或多个字符
列表类型 : list
标识:[]
存放的是多个变量的容器
元组类型 : tuple
标识:()
存放的是多个变量的容器
注意:和list的区别 list中的元素的值是可以变的 元组中的元素的值不可变的
共同点:添加在容器中的元素都有自己的编号,这个编号是从0开始 这个编号也称之为索引 或者 下标 、脚标
字典类型 : dict
标识:{}
存放的数据是用键值对的格式表示 键和值是一一对应的 根据键来查找值
要求:键是不允许重复的 必须唯一的
键的类型对应的数据是不可变的
字典的格式;
集合类型 : set
把集合理解是存放字典key的容器
集合中的数据是不允许重复的 ---- 用于排重 还排序
空值类型 :None
只有一个值 None --代表状态是空
用户输入
input 封装用户输入的功能
格式: value = input("提示用户输入语")
在程序中使用input接受用户输入时 获得数据类型是字符串类型 str
python2.x 用户输入的是什么类型 在程序中接受的就是什么了类型
python3.x 用户不管你输入的是什么格式的数据 接受到的都是字符串类型
类型转换
1.将对应的数据转换为整型
格式:int(x) --- 将x这个数据转为整型
注意: 如果x的类型为字符串类型 需要保证x的数据值必须纯数字的 否则转换失败
2.将对应的数据转换为浮点类型
格式:float(x) --- 将x这个数据转为浮点类型
注意:如果x的类型为字符串类型 需要保证x的数据值除了点之外没有其他非数字符号 否则转换失败
3..将对应的数据转换为布尔类型
格式:bool(x) - -- 将x这个数据转为布尔类型
注意;只有两个值 True False 1 和 0
4.将对应的数据转换为字符串
格式:str(x) - -- 将x这个数据转为字符类型
....
5.将字符(单个)转换为十进制
格式:ord(x) - -- 将字符换转为十进制
6.将对应的十进制转化为字符
格式:chr(x) -- - -- 将x数据转换为字符串
7.将数据转换为二进制
bin(x) -- b
8.将数据转换为八进制
oct(x) --o 0b00 0011
9.将数据转换为十六进制
hex(x)
10.将数据转换为列表
list(x)
11.将数据转换为元组
tuple(x)
12.将数据转换为字典
dict(x)
13.将数据转换为集合
set(x)
14.解析代码
eval(code)
代码是包含在字符串中的
运算符
算术运算符
关系运算符
逻辑运算符
成员运算符
身份运算符
位运算符
注意:() 提高优先级
算术运算符
/
// :9 // 4 等于2
% :取余数
** :幂次方 str ** 2
复合运算符
= 赋值运算符
a = b
a+=b : a=a+b
a/=b : a= a/b
a=b : a=ab
.....
关系运算符
关系运算符运算之后的结果是bool类型
‘ > < >= <= = != ’
逻辑运算符
逻辑运算符两边的表达式都是bool类型, 运算的结果也是bool类型
逻辑与(and):并且的关系 两边同时成立才位真 注:一假则全假
逻辑或(or):或者的关系 一个结果成立 则结果成立 注:一真则全真
逻辑非(not):假变真 真变假
注意: not > and > or
成员运算符
针对序列【字符串 列表 字典 集合..】而言的
包含和不包含的关系
in
x in 序列 -- 判断x是否包含在序列中
not in
x not in 序列 -- 判断是否不包含在序列中
身份运算符
两个变量的身份地址是否一致
id(x) -- 获取变量的内存地址
is -- 判断地址是否相同
id(x) == id(y)
is not -- 判断地址是否不相同
id(x) != id(y)
位运算符
使用的不多 --- 针对二进制数的运算符
流程控制
流程语句
1.顺序语句:代码的执行流程 从上往下执行的
2.分支语句: 根据不同的情况出现不同的分支
3.循环语句:重复操作某一个事件 使用循环语句
判断分支
语文: 如果... 就... 映射到程序中
if 条件表达式:
缩进[通过tab键完成] 满足执行的条件的语句
# if 如果.. 就...
age = int(input("请输入您年龄:"))
# 判断
if age >= 18:
print("小伙子 可以谈恋爱了")
语文:如果...就... 否则...
if 条件表达式:
满足条件执行的操作
else:
不满足条件执行的操作
注:else后面不能添加条件表达式判断
age = int(input("请输入您年龄:"))
# 判断
if age >= 18:
print("小伙子 可以谈恋爱了")
else: # 如果.. 就... 否则....
print("小朋友 你还小 回家做作业去")
语文:排比句
如果...就..
否则如果... 就...
否则如果... 就...
否则如果... 就...
否则如果... 就...
否则...
格式:
if 条件表达式:
执行语句1
elif 条件表达式:
执行语句2
elif 条件表达式:
执行语句3
elif 条件表达式:
执行语句4
....
else:
执行语句
案例:
在控制台录入一个成绩,进行评定:
评定标准: >=90 A 90>x>=80 B >=70 C >=60 D 其他 E
练习:
键盘录入年和月
要求输出对应月份的天数
月份:1 3 5 7 8 10 12 —————— 31
4 6 9 11 ———— 30
2 ———— 闰年 29 平年 28
循环结构
1.range方法 这个方法的作用 生成一个顺序序列
# range 方法
"""
range 生成一个顺序的序列
[stop] 接受结束值 从0开始到多少结束 [0,stop)
"""
res = range(100)
print(res) # (0, 100) 序列
# 把结果转换list 列表
list0 = list(res)
print(list0)
"""
range()
start 起始值
stop 结束值
[, step] 步长 默认1
"""
res = range(1,10,2)
print(list(res)) # [1, 3, 5, 7, 9]
res = range(10,1,-1)
print(list(res)) (10.。。。2)
# 提供用户输入一个字符 输出十进制的值 # 97 a 65 A
s = input("请输入一个字符:")
# 转换为 ASCII
value = ord(s)
# 97 + 26 = 123
if value in range(97,124): # 只判断a-z 范围 a-z
print(s)
循环结构语句
循环:重复执行某个操作
Python中提供的循环机制:while 和 for in
在循环条件明确的时候 使用while循环
当遍历一个序列内容的时候 使用for in
while循环:
while 条件表达式:
重复的操作
当循环条件表达式成立的时候 才会执行重复的操作语句
循环的大致思路:
1.确定循环条件
2.确定重复的操作
案例:
输出1-10的数?
声明一个变量 记录数据 num = 1
确定循环的条件 变量最大10 num<=10
确定要重复的操作:
输出操作
练习;
求1-10累计的和?
while的另外一种格式:
while 循环条件表达式:
循环操作
else:
循环条件不成立的时候执行
练习:求1-10偶数的和? 注:使用while循环
for in 循环:
for 变量 in 序列:
重复操作
针对循环作用有两个关键字
break continue
break: 作用是 结束当前循环结构
遇见break 当前循环语句立即结束
continue
作用: 结束当前循环 继续下一次循环
遇见continue 结束当前次循环 回归到判定循环条件 继续下一次循环
在break和continue后不要直接跟平级的语句 因为这些语句永远不会被执行
常用数据的类型的使用
1.数值类型
2.字符串类型
str = "if123456789"
#把字符串的第一个字符大写
str.capitalize()
#返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 (填充的字符)
str.center()
#返回 str 在 string 里面出现的次数,如果 beg或者 end 指定则返回指定范围内 str 出现的次数
str.count("f", beg=0, end=len(str)) # 1
#检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.
str.endswith(obj, beg=0, end=len(str))
#把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8
str.expandtabs(tabsize=8)
#检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1
string.find(str, beg=0, end=len(string))
#格式化字符串
string.format()
#跟find()方法一样,只不过如果str不在 str中会报一个异常.
string.index(str, beg=0, end=len(string))
#如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False
string.isalnum()
#如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False
string.isalpha()
#如果 string 只包含数字则返回 True 否则返回 False.
string.isdigit()
#如果 string 中只包含数字字符,则返回 True,否则返回 False
string.isnumeric()
#如果 string 是标题化的(见 title())则返回 True,否则返回 False
string.istitle()
#以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
string.join(seq)
#以空格拼接字符串
" ".join(string)
#返回一个原字符串左对齐,并使用空格填充至长度width 的新字符串
string.ljust(width)
#转换 string 中所有大写字符为小写.
string.lower()
#返回字符串 str 中最大的字母。
max(str)
#返回字符串 str 中最小的字母。
min(str)
#把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.
string.replace(str1, str2, num=string.count(str1))
#类似于 index(),不过是从右边开始.
string.rindex( str, beg=0,end=len(string))
#以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+1 个子字符串
string.split(str=" ", num=string.count(str))
#按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为
#False,不包含换行符,如果为 True,则保留换行符。
string.splitlines([keepends])
#检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,
#则在指定范围内检查.
string.startswith(obj, beg=0,end=len(string))
#删除字符串最后的字符
string.strip([obj])
#转换 string 中的小写字母为大写
string.upper()
3.列表类型
列表是python内置一种数据类型:list
list是一种有序的集合【插入顺序和显示的顺序是一致】
列表里的数据是可以随时增加以及删除和修改,添加的元素会自动添加编号,这个编号从0开始的
这个编号又称为下标(脚标 索引)
列表类型类似容器 可以存放多个变量
二维列表:在列表中的元素是列表 [[19,28],[22,33]]
# 列表类型
list0 = ["开群","老谢","嘉豪",10,True,[12,34],(56,78)]
# 列表中元素的个数 len
res = len(list0)
print(res) # 7
# 访问列表中元素
# [0,len(list0)-1] [-len(list0),-1]
res = list0[1] # 7IndexError: list index out of range
print(res)
# 修改元素
list0[0] = "老杨"
print(list0)
# 向列表中添加元素
list0.append("思思")
print(list0)
list0.append(10)
print(list0)
# 在指定位置插入元素 下标0
list0.insert(0,"head")
print(list0)
list0.insert(1,"body")
print(list0)
# 将一个列表合并到当前列表中
list1 = [99,88,77,55,66,10,20,10,22,10]
list0.extend(list1)
print(list0)
# list0.append(list1) # 追加 和 合并是有区别的
# print(list0)
# 删除元素
# 直接删除最后一个元素
list0.pop()
print(list0)
# 删除指定索引位置的元素
list0.pop(0)
print(list0)
# 删除指定的元素
list0.remove(10) # 如果有重复元素 只会删除第一个次出现的元素
print(list0)
# 统计某个元素出现的次数 传入一元素
res = list0.count(10)
print(res)
"""
list0 = [10,22,44,66,22,10,99,66]
要求;列表中元素顺序不变 使每个一个元素只有一个
最后的结果:[10,22,44,66,99]
提示思路:
1.可以借助其他列表辅助完成存储
2.使用到成员运算符 in 或 not in
"""
# list0 = [10,22,44,66,22,10,99,66]
# list1 = []
# for item in list0:
# if item not in list1:
# list1.append(item)
# print(list1)
"""
set 用于排重的 是一个无序的集合【插入顺序和显示顺序不一致】
"""
# res = set(list0)
# print(list(res)) # [66, 99, 10, 44, 22]
# 列表 可以切片吗? [start:stop:step]
print(list0)
# 从头到尾提取数据
sub_list = list0[::]
print(sub_list)
sub_list = list0[1::]
print(sub_list)
# 倒序
sub_list = list0[::-1]
print(sub_list)
# 方法 倒序
list0.reverse()
print(list0)
# 排序:同类型的数据 才会有排序的情况出现
list0 = [12,22,55,35,19,66,48,88]
"""
sort(key=None, reverse=False)
key: 接受的一个函数
函数可以当做值进行传递
key的作用:将列表中的元素依次作用于对应的函数 返回排序的元素状态 默认数据大小进行排序的
reverse: 接受的是布尔值
控制排序完之后是升序还是降序
默认升序 值False
"""
list0.sort(reverse=True)
print(list0)
# 获取列表中最大值
list0 = [12,22,55,35,19,66,48,88]
max_value = max(list0)
print(max_value)
list0 = [12,22,55,35,19,66,48,88]
min_value = min(list0)
print(min_value)
# 自己去写方法
max_value = list0[0]
for item in list0:
if item > max_value:
max_value = item
print(max_value)
# 另外的方式去找最大值
max_index = 0
for i in range(1,len(list0)):
if list0[i] > list0[max_index]:
max_index = i
print(list0[max_index])
# 二维列表
list_two = [[89,77,62],[44,23],[55,66,88,22]]
res = list_two[0]
print(res[0])
res = list_two[2][1]
print(res)
# 获取所有一维列表
for list1 in list_two:
for item in list1:
print(item)
# 返回值与下标
list_two = [89,77,62,44,23,55,66,88,22]
for k,v in enumerate(list_two):
print(k,v)
0 89
1 77
。。。。
4.元组类型
类似于列表的 与列表的区别:
列表对应的元素的值是可以发生修改的
元组的元素值是不可以发生修改的
简单的说;元组一旦确定 内容不能发生改变
没有对应的增加 删除 和 修改
遍历的操作
# 元组类型 () tuple
tuple0 = (23,56,99,True,"abc")
# 获取元组中的数据 通过索引获取
value = tuple0[-1]
print(value)
# 获取元组的元素个数
num = len(tuple0)
print(num)
# 修改元组元素 TypeError: 'tuple' object does not support item assignment 不可以修改
# tuple0[0] = 32
# print(tuple0)
# 获取的操作
tuple1 = ([12,56],"abc",88)
# 获取12
print(tuple1[0][0])
tuple1[0][0] = 22
print(tuple1)
# 元组中的列表 列表是可以修改的
print(id(tuple1[0]))
print(id(tuple1[1]))
print(id(tuple1[2]))
tuple1[0][0] = 22
print(id(tuple1[0]))
print(id(tuple1[1]))
print(id(tuple1[2]))
# 遍历
for item in tuple1:
print(item)
for i in range(len(tuple1)):
print(tuple1[i])
# 小括号 还有另外一层意思 就是提高运算的优先级
print(type((10,)))
5.字典 dict
{} 使用键值对的形式来存储数据的
存放键值对的集合 元素也是无序的
存放的顺序 可能和显示顺序是不一致的 但是一旦确定位置一直在对应位置显示
键和值是一一对应的
在字典中是根据键来查找值的
注:对于键的要求
1.不能重复 必须是唯一的
2.键的类型对应的数据是不可以改变的【值是元素内容】
一旦键发生变化 --- 找不到原的内容
一般采用 字符串(常用) 或 整型
# 字典操作
dict0 = {"语文":100,"数学":150,"英语":60}
res = "语文" in dict0
print(res)
# 1.在字典中添加键值对
dict0["政治"] = 77
print(dict0)
# 获取值 根据键获取值
value = dict0["语文"]
print(value)
# KeyError: '历史' 报错 不建议
# value = dict0["历史"]
# print(value)
# 2. 建议使用 get方式去获取值
value = dict0.get("历史")
print(value) # None
# 3. 修改 值
dict0["语文"] = 88
print(dict0)
# 4. 删除
dict0.pop("政治")
print(dict0)
# 5.对于字典进行遍历
# 5.1 只遍历key 键
for key in dict0:
print(key)
# 5.2 只遍历value 值
for value in dict0.values():
print(value)
# 5.3 获取所有的键值对元素
# items = dict0.items()
# print(items) # [('语文', 88), ('数学', 150), ('英语', 60)]
# for item in items:
# print("key=",item[0],"value=",item[1])
# a,b = (11,12)
# print(a,b)
# 同时获取键和值
for k,v in dict0.items():
print("key=",k,"value=",v)
"""
练习1:
统计一个英文字符串中 每个字母出现的次数
要求使用字典存储:
key:value
字母:个数
例子:aaabbbccca
{'a':4,'b':3,'c':3}
"""
# # 提示用户输入字符串
# src_str = input("请输入一个英文字符串:")
# # 定义容器存储数据 字典
# dict_str = {}
# # 遍历所有输入的字符串
# for s in src_str:
# if s not in dict_str:
# dict_str[s] = 1
# else:
# # 获取value
# value = dict_str[s]
# value += 1
# dict_str[s] = value
# print(dict_str)
"""
练习2:
键盘录入一句英文语句 单词和单词之间用空格隔开 统计每个单词出现的次数
要求使用字典存储:
key:value
字母:个数
abc abc ddd hello hello
"""
# 提示用户输入英文语句
words = input("请录入一句英文语句,单词和单词之间用空格隔开:")
w_dict = {}
# 根据空格切割字符串
w_list = words.split(" ")
# 遍历列表
for word in w_list:
if word not in w_dict:
w_dict[word] = 1
else:
w_dict[word] += 1
print(w_dict)
6.集合
不允许存放重复的数据 会有自动排重的效果
简单说:用于排重的操作
# 集合 setdict0 = {"语文":100,"数学":150,"英语":60,"英语":60}set0 = set([1,2,3,1,2,3])print(set0)# 交集 & 和 并集 |set1 = {1,2,3}set2 = {2,3,4}print(set1&set2) # 2 3print(set1|set2) # 1 2 3 4
函数
1.函数的概述
为什么要使用函数???
函数就是对功能的封装
例子:求圆的面积?
S = π*r**2
求半径为10的圆的面积
3.14*10**2
求半径为9的圆的面积
3.14*9**2
.....
工程效率比较低
函数作用:对功能进行封装 增强代码的复用性 提高程序效率
2.函数的分类
内置函数 和 自定义函数
内置函数: 系统提供的现成的函数 直接可以使用
例如:print() int() type() input()....
自定义函数:
函数的定义格式:
def 函数名(变量1,变量2...变量n): 函数功能的实现 return 功能的结果def --- 声明函数的关键字函数名 --- 功能名字 方便之后通过名字进行调用 命名规范:符合标识符规范 函数名英文字母都是小写 每个单词之间使用下划线隔开 circle_area (起名 最好做到见名知意)小括号 --- 形参列表 形参: 作用于存储函数功能中未知项的值 实参: 为形参赋值的数据 return --- 作用:结束函数 并将功能的结果返回给调用者 如果该功能的实现不必须要返回结果 return可以省略 或者写成 return None
3.函数实战
1.封装功能
根据两个明确来完成函数的声明:
a:明确是否有未知项参与函数功能的运算 --- 形参的列表 有几个未知项就声明几个变量
b:明确调用者是否需要接受结果 -- 决定是return
封装计算圆的面积功能?
S = π*r**2
未知项 : 1个 r
返回结果: 需要return
4.作用域的问题
# 封装一个修改名字的功能name = "开群" # 全局变量def change_name(): """ 在函数内部可以直接获取外部变量的数据 如果要进行修改 变量名 = 值 变量作用域的问题:如果直接在函数内部内容写为 变量名 = 值 解释器会默认为函数内部的变量 与外部变量无关 如果想修改外部变量的值 在函数内部标注该变量的作用域范围 global 使用全局变量 """ global name name = "小杨" # 局部变量 print("函数内部",name)change_name()print("外部",name)
5.默认参数
print(self, *args, sep=' ', end='\n', file=None)
声明了一个形参 并给他赋予初始值
调用函数的时候 如果没有给这个形参赋值 这个参数有默认值 使用默认值参与函数功能的运算
例子:求x的y次方?
模块和包
后面要预习的内容:
高阶函数(内置函数)
map 、reduce、filter
常用的模块
time、datetime、calender、os
一.模块和包
模块就是一个工具包 一个py文件称之为一个模块
有三种模块类型
1.python系统提供的模块
如:random time math...
2.第三方模块
别人写好的 自己拿来使用
需要安装模块工具 pip
控制台命令 输入:pip install 模块名
conda install 模块名
注:必须要有网络
3.自定义模块
如果要使用其他模块 -- 导入模块 import
导入模块的方式:
a) import 模块的名字
这种形式使用模块内容是 格式是 模块名.内容名
b) from 模块名 import 内容名称
c) from 模块名 import *
*
通配符 泛指当前模块下所有的内容
使用之前要注意:调用的内容必须是在模块的“__all__”
字段中指明的内容
注:当导入的模块不容易记住 可以取个别名 as
格式:import 模块名 as 别名
在使用的时候只能通过别名来调用内容
__main__
程序入口
启动程序是 从那个文件先进入 对应的那个文件称之为程序的入口文件 这个文件中__name__
对应的字段值就是 __main__
第三方模块的使用 -- 安装 pip install 模块名
pymysql
redis
pygame
包
包的作用:为模块提供多层命名空间 并对其进行分配管理
常识问题:
在一个文件夹下 不允许同时存在两个名字相同的文件
a:
test.txt
b:
test.txt
在项目中不同的功能
起模块名的时候 -- 很可能模块名重名就重名了
包就是程序中文件夹
包是必须在项目中才能存在的
包创建出来之后 会自带一个'__init__.py'
文件 这个文件的作用就是标注该目录是一个包 而非普通文件夹
想使用包里面的模块的导入模式:
包名.模块名
有几层包 包名都用点分割 标注
随机数模块
random
import randomprint(random.random()) # (0,1) float 大于0且小于1之间的小数print(random.randint(1,3)) #[1,3] 大于等于1小于等于3之间的整数print(random.randrange(1,3)) # [1,3) 大于等于1 小于3之间的整数print(random.choice([1,"23",[4,5]])) # 在序列中随机产生一个内容print(random.sample([1,"23",[4,5]],2)) # 列表中任意组合两个print(random.uniform(1,3)) # 大于1 小于3的小数item = [1,3,5,7,9]random.shuffle(item) # 打乱item的顺序 相当于 洗牌print(item)
常用模块
时间模块: time datetime calender
时间戳:表示的是从1970年1月1日开始按秒计算的偏移量
a).time
import time# 获取当前的时间 -- 时间元组res = time.localtime()print(res)# 可以通过字段的方式获取 (推荐)year = res.tm_yearprint(year)# 通过索引获取# year = res[5]# print(year)# 2.获取当前时间对应时间戳seconeds = time.time()print(seconeds)# 将时间戳转换时间元组time1 = time.localtime(seconeds)print(time1)# 休眠time.sleep(2)print("睡醒了")# 时间格式 2021年4月1日 9:54:22'''表示年的占位符 %Y 2021 %y 21表示月的占位符 %m 日 %d -- 表示是1-31号的日期 %H -- 24小时制 %I -- 12小时制 %p -- am/pm 的标识 分 %M 秒 %S 一年中的第几天 %j'''t1 = time.localtime()# 将其进行格式化res = time.strftime("%Y/%m/%d %H:%M:%S %j %A",t1)print(res)# 将格式化的时间转换为时间元组 2021/04/01 10:00:01time_str = "2021-04-01 10:00:01"res = time.strptime(time_str,"%Y-%m-%d %H:%M:%S")print(res)# 获取指定时间的秒数seconds = time.mktime(res)print(seconeds)'''要求:获取指定时间的三天后的时间思路:指定一个时间 2020-01-01 --- 2020-01-04转成程序认识的时间 获取秒数+3天的秒数 ---时间戳'''# 获取指定时间 的n天后/前的时间戳def get_time(time_str,days,format_str): # 1.将时间转换为程序认识的时间元组 time_tuple = time.strptime(time_str,format_str) # 2.获取指定时间的秒数 seconds = time.mktime(time_tuple) # 3.获取days前/后时间戳 times = seconds + (days) * 24 * 3600 tiems_tuple = time.localtime(times) res_times = time.strftime(format_str,tiems_tuple) return res_timesres = get_time("2020-1-1",-3,"%Y-%m-%d")print(res)
b) datetime
import datetime# 获取当前时间res = datetime.datetime.now()print(res)# 获取当前日期day = datetime.date.today()print(day)print(day.weekday()) # 星期# 获取指定时间 的n天后/前的时间res = datetime.date.today() - datetime.timedelta(days=-2) # 正数代表 过去 负数代表 未来 天数print(res)# 时间格式res = datetime.datetime.now().strftime("%Y-%m-%d %j")print(res)# 在转回去res = datetime.datetime.strptime(res,"%Y-%m-%d %j")print(res)# 将时间转化为时间元组time_tuple = datetime.datetime.now().timetuple()print(time_tuple)
c) calendar
import calendar# 显示指定年的日期res = calendar.calendar(2021)#print(res)res = calendar.month(2021,4)print(res)# 判断闰年和平年res = calendar.isleap(2021)print(res)res = calendar.monthcalendar(2021,1)print(res)day = res[2][2]print(day)res = calendar.weekday(2021,4,1)print(res) #[0,6] [星期1 星期天]# hashlib 加密模块
d) hashlib 加密模块
import hashlibhash = hashlib.md5() # md5 不可逆的 不可反解 但是加密是固定的 关系是一一对应 缺陷 可以被撞出来hash.update(bytes('admin',encoding="utf-8")) # 要对那个字符串进行加密# 输出加密的字符串print(hash.hexdigest()) # 拿到加密的字符串 21232f297a57a5a743894a0e4a801fc3hash2 = hashlib.sha3_384() # 不同算法 hashlib很多加密的算法hash2.update(bytes('admin',encoding="utf-8"))print(hash2.hexdigest())hash3 = hashlib.md5(bytes('abd',encoding="utf-8"))"""如果没有参数 md5遵循一个规则 生成同一个对应关系 如果加了参数 就是在原来的基础上在一层加密 这样的话参数只有自己知道 防止被撞库因为别人永远那不不到这个参数"""hash3.update(bytes('admin',encoding='utf-8'))print(hash3.hexdigest())"""模拟登陆和注册 要求:利用md5进行用户登陆网站进行注册之后密码加密的基本事例扩展:数据放入文本中 open('文件路径','打开模式')******* 模拟网站界面*****1.登录2.注册"""# 封装加密功能def md5_jiami(arg): hash = hashlib.md5(bytes('abcd',encoding='utf-8')) # 如果加了参数 就是在原来的基础上在一层加密 这样的话参数只有自己知道 防止被撞库 hash.update(bytes(arg,encoding='utf-8')) # 要对那个字符串进行加密 return hash.hexdigest()# 封装注册功能def register(user,pwd): with open("db.txt","a",encoding="utf-8") as f: #数据 用户名+密码(加密?) temp = user + "|" + md5_jiami(pwd) + "\n" f.write(temp)# 封装登录功能def log(user,pwd): with open('db.txt','r',encoding="utf-8") as f: for line in f: u,p = line.strip().split("|") # admin da3177cbd9f064004b6a0d59a3a484bb if u == user and p == md5_jiami(pwd): return Trueprint("******* 模拟网站界面*****")print("1.表示登录 \n2.表示注册")i = input("请选择操作功能:")if i == "2": user = input("用户名:") pwd = input("密码:") register(user,pwd)elif i == "1": user = input("用户名:") pwd = input("密码:") res = log(user,pwd) if res: print("登录成功") else: print("登录失败")
迭代对象
判断是否可是迭代对象
# from collections import Iterable # 判断是否是迭代对象 -- 是迭代对象# # isinstance()判断是否是迭代对象的方法# print(isinstance("abc",Iterable)) # True# print(isinstance([1,2,3],Iterable)) # True# print(isinstance(123,Iterable))list1 = list("一二三四五六七八九十")# 获取索引 和 值for i,v in enumerate(list1): print("index:",i,"values",v)
生成式
快速生成列表或者字典的方式
格式:
列表生成式
[列表中存放的元素 元素的来源 元素的筛选]
list0 = [1,2,3,4,5,6,7,8,9,10]# 从上面数据中快速生成[2,4,6,8,10]# 不使用列表生成式# list1 = []# for item in list0:# if item % 2 == 0:# list1.append(item)# print(list1)# 列表生成式list2 = [item for item in list0 if item%2==0]print(list2)# 在上面的基础上 利用列表生成式 生成[4,16,36,64,100]list3 = [item**2 for item in list2]print(list3)# 判断某个数据是否指定的类型res = isinstance(123,str)print(res)list4 = ["good","nice",12,"day","up",88]# 只要字符串 不要数字res = [item for item in list4 if isinstance(item,str)]print(res)## 只要字符串 不要数字 字符串的字母变大写形态res = [item.upper() for item in list4 if isinstance(item,str)]print(res)
字典生成式
# 字典生成式dict0= {"语文":88,"政治":76,"历史":57,"英语":55}# 大于60分的科目dict1 = {k:v for k,v in dict0.items() if v>=60}print(dict1)# 将原字典的键和值颠倒dict1 = {v:k for k,v in dict0.items() if v>=60}print(dict1)
生成器 generator
生成式 可以快速生成一批数据 --- 这些数据是全部在内存中
python提供了生成器 -- 需要去时候才会在内存中产生 不是一次性全部在内存中
定义生成器:
1.列表生成式设置小括号
2.结合函数和yield关键字 形成生成器
在生成器中怎么去获取数据?
迭代器(另外的遍历方式) Iterable
可以迭代对象 Iterable
凡是可以通过for循环遍历的统称称为可迭代对象
可以迭代的对象: 字符串 str 元组tuple 字典dict 集合set 列表list...
验证指定的类型:isinstance(数据,类型)
高级函数
map() 函数
map(func, *iterables)
将序列中的元素依次作用于函数 将函数运行的结果存放在一个新的迭代器中
reduce
将一个函数作用于序列 这个函数必须接受两个参数 reduce 把元素累计结果与下一个元素继续累计的过程
filter
过滤 筛选
filter(function or None, iterable)
sorted
排序
sorted(列表,key,reverse)
函数补充
函数的声明
函数的调用
递归
位置参数:传递的实参的顺序和声明的形参的顺序一致
默认参数:声明函数的时候可以给形参设置默认值 调用的时候如果不传值就是默认值 传值的话就是用传递的值
可变参数
例子:封装一个功能 求n个数的叠加和?
形参设置成可变参数
def 函数名(形参,*形参):
语句块
# 可变参数# 求n个数累计的和def add(*nums): #print(type(nums)) # 元组 # 在函数中nums是一个元组;用于接受传递过来的所有实参的值 sum = 0 for item in nums: sum+=item return sum# res = add(1,2,33,55,10)# print(res)# 直接传递一个元组tuple0 = (34,56,88)# 调用函数res = add(*tuple0) # 在其赋值给函数的可变参数nums 不加* 报错print(res) # TypeError: unsupported operand type(s) for +=: 'int' and 'tuple'list0 = [1,2,3]res = add(*list0)print(res)
关键字参数
关键字参数允许调用函数时 传入0个或者多个带有形参名的参数 这些数据会存放在函数内部自动形成一个字段
什么时候使用关键字参数???
例子:
注册信息
必填项 --- 固定的形参
选填项 --- 关键字参数
# 关键字参数# 选填项就要用关键字参数 字段名=数据def accept_data(username,password,**argus): print(username,password,argus)# 调用函数accept_data("开群","5201314",email="[email protected]",sex="女")dict0 = {'email': '[email protected]', 'sex': '女'}# 通过字典传值accept_data("小群群","1314520",**dict0)
闭包 -- nonlocal 关键字(闭包)
在函数A声明函数B 并且函数A的返回值是函数B --- 这种形式称之为闭包(closure)
global 关键字
如果在函数内部使用全局变量 需要先对其进行global标记
外部函数的局部变量在内部函数使用时 需要将其nonlocal标记
注意:如果不进行标记 会默认认为那个变量是在内部函数里面声明的 与 外部函数的变量只是同名而已
# 闭包# def func_a():# def func_b():# print("内部函数B")# def func_c():# print("内部函数C")# return func_b# res = func_a()# res()#func_a()()# func_b() 在函数内部声明的内容 函数外部获取不到的# 作用域# 变量作用域:全局变量 和 局部变量a = 50 # 全局变量def func_a(): # global a # a = 500 # 局部变量 num = 10 def func_b(): print("内部函数B") nonlocal num num = 100 print("内部函数B",num) def func_c(): print("内部函数C") func_b() print("外部函数:",num) return func_bres = func_a()print(res)# print(a)
装饰器
装饰器的作用:为已经存在的函数添加新的功能 不会对原来功能增加影响
功能:
打印九九乘法表?
计算这个功能执行需要的时间?
# 打印九九乘法表def table(): for i in range(1,10): for j in range(1,i+1): print(j,"*",i,"=",i*j,end=" \t") print("")import time# start = time.time()# table()# end = time.time()# print(end-start)# 想计算每个功能执行的时间def get_time(func): start = time.time() func() end = time.time() print("耗时",end-start)def nums(): for s in range(1,1000000): print(s)get_time(nums)
装饰器的格式本身就是一个闭包
在不修改原来的功能的基础上增加新的功能【新的功能 可以增加 也可以不增加】
def outter_name(func): def inner_name(*value,**argus): # 增加的功能 res = func(*value,**argus) return res return inner_name
偏导函数
例子:将一个数据转换为整数
int()
# 偏函数"""int(x, base=10)--- 常用的状态十进制为基础"""res= int("10",base=2)print(res) # 0000 0000 # 2def int1(value): return int(value,base=2)res = int1("0010")print(res)# 系统也提供了设置偏函数的功能import functoolsint2 = functools.partial(int,base=2)res = int2("1001")print(res)
匿名函数
声明函数时 都有函数名
带有函数名的函数是有一个弊端的
起函数名--- 见名知意
求两个数的和?
def add(a,b):
return a+b
求三个数的和?
def add(a,b,c):
return a+b+c
在一个模块中 声明两个同名的函数 第二函数就会把原来的函数覆盖掉
简单的函数就可以使用匿名函数来完成
匿名函数的格式:
lambda 函数的参数:执行的语句
执行语句注意:只有一条语句 一般这条语句被视为返回语句
# def add(a,b):# return a+bf = lambda a,b:a+bprint(f)res = f(12,34)print(res)# def add(a,b,c):# return a+b+cadd = lambda a,b,c:a+b+cprint(add(1,2,3))# res = add(1,2)# print(res) # 第二个会把第一个覆盖掉
预习:
1.os模块
2.关于文件读写的操作(IO输入输出机制)
re模块
[re.sub(r'\xa0|\t|\n|\s','',i)for i in sho] 替换
其中没填括号的代表不需要的比如空格什么的
os模块
提供了很多的方法来处理磁盘上的文件和目录
import os# 1.获取当前的操作系统的名称name = os.nameprint(name) # nt -- windows posix--Liunx/Mac# 获取系统的信息# res = os.uname() # windows 下是不支持 Mac/Liunx下才有结果# print(res)# 获取环境变量env = os.environprint(env)# 获取某一个的环境变量对应的值res = os.environ.get("Path")print(res)"""绝对路径:从盘符开始 到目的的文件结束D:\Anaconda3\demo.txt相对路径:参照物 C: test a.txt m.py subtest b.txt test1 c.txt参照物是m.py文件需求: 想在m.py中获取a.txt这个路径(平级的直接就写文件名称即可) a.txt 想在m.py中获取b.txt这个路径 (subtest\b.txt) 想在m.py中获取c.txt这个路径 (..\test1\c.txt). --- 当前路径.. --- 上一级路径"""# 获得当前文件所在的当前路径path = os.curdir # 当前路径print(path) # .# 获得当前文件所在的目录path = os.getcwd()print(path)# D:\pythonobj\ch14\os_pack# 获得指定目录下的所有子目录或者子文件的名字path = r"D:\pythonobj"path_list = os.listdir(path)print(path_list)# 创建目录"""make directory 创建文件夹"""#os.mkdir("test_dir") # 相对路径# 多级目录 mkdir不行 创建一级#os.mkdir(r"D:\pythonobj\ch14\os_pack\test")# 想多级目录#os.makedirs(r"D:\pythonobj\ch14\os_pack\test1\test2\test3")# 删除目录#os.rmdir("test_dir")# 删除只能删除空目录(删除只会删除最后一级目录)#os.rmdir(r"D:\pythonobj\ch14\os_pack\test1\test2\test3")# 创建文件 -- 注:后面文件的输入输出详细讲解# 打开一个文件 执行的写的操作 打开这个文件的时候 如果文件不存在 则创建#open("test.txt","w")# 删除文件#os.remove("test.txt")# 获取文件的信息#res = os.stat("os_demo.py") # 存在问题 传入文件名 路径地址#print(res)# 重命名#os.rename("修改目录","原目录")# 重命名目录#os.rename(r"D:\pythonobj\ch14\os_pack\test1",r"D:\pythonobj\ch14\os_pack\test3")# 有些对文件的操作是存在os.path下# 文件的绝对路径ab_path = os.path.abspath(".")print(ab_path) # D:\pythonobj\ch14\os_pack# 拼接路径join_path = os.path.join("路径","文件名)print(join_path) # D:\pythonobj\ch14\os_pack\os_demo.py# 拆分路径 最后的返回结果1个元组 (“前半部分路径”,“最后一级的路径名”)res = os.path.split(ab_path)print(res)# 获取指定路径的扩展名分为两个路径(前半部分路径,文件的扩展名)# 注:如果指定的路径是一个目录的话 扩展名的部分就是空字符res = os.path.splitext(join_path)print(res)# 获取指定路径的 最后一级的名字file_name = os.path.basename(ab_path)print(file_name)# 获取指定路径的 最后一级前的所有路径dir_name = os.path.dirname(ab_path)print(dir_name)# 获取文件的大小file_size = os.path.getsize(join_path)print(file_size) # 字节 B -- KB -- MB -- GB -- TB -- PB -- EB -- ZB -- YB -- BB -- NB -- DB -- CB -- XB# 判断操作# 1.判断指定目录是否绝对路径res = os.path.isabs(join_path)print(res) # True# 2.判断指定路径是不是目录/文件夹res = os.path.isdir(ab_path)print(res)# 3.判断是否是文件res= os.path.isfile(join_path)print(res)# 判断指定路径在计算机中是否存在res = os.path.exists("w:\s")print(res)"""练习:获取指定目录下 后缀为.wmv的文件路径 扩展:想获取指定目录下所有的文件"""path = r"C:\Users\Administrator\Desktop\数据分析5班\2021-4-6\video"dir_list = os.listdir(path)for file_name in dir_list: if file_name.endswith(".wmv"): print(os.path.join(path,file_name))# 想获取指定目录下所有的文件"""test a.txt b.txt subtest 1.txt 2.txt sub_tets l.txt m.txt"""# 目录中 所有的文件def get_file(path): # 判断路径是否存在 if not os.path.exists(path): return if os.path.isfile(path): print("只接受目录") return file_list = os.listdir(path) for file_name in file_list: # 判断路径下是否文件路径 join_path = os.path.join(path,file_name) # 判断整个路径 if os.path.isfile(join_path): print(join_path) else: get_file(join_path) # 在去找# get_file(r"d:\\")"""删除指定目录"""def delete_file(path): # 判断路径是否存在 if not os.path.exists(path): return if os.path.isfile(path): print("只接受目录") return file_list = os.listdir(path) for file_name in file_list: # 判断路径下是否文件路径 join_path = os.path.join(path, file_name) # 判断整个路径 if os.path.isfile(join_path): os.remove(join_path) print(join_path,"已删除") else: delete_file(join_path) # 在去找 # 遍历删除完成后 该目录成了空目录 os.rmdir(path)delete_file(r"E:\pythonobj")
关于文件的读写操作(IO输入输出机制)
当为字典时,想要写入,可以通过json直接写入 ,后面的传参代表不自动转换编码
输入输出是有参照物的
输入:将内容读取到程序的过程 --- 输入过程
输出:将内容从程序中写出去的过程 -- 输出过程
文件:存储在外部介质(磁盘文件、网络数据)上的数据和信息的集合
注:操作的数据流
首先 打开文件 -- 编写数据
首先 打开文件 -- 在程序中的通过介质关联文件 获得文件的手柄
格式:handle = open("文件路径","打开方式")
打开模式:r (read) ---- 只读操作 要求文件必须存在w (write) ---- 只写模式 如果文件不存在 会创建文件 存在将文件原来的内容清空x ---- 写入模式 要求文件是存在的a (append) ---- 只写模式 如果文件不存在 会创建文件 如果文件存在会在原来的基础上进行拼接r+ w+ x+ a+ ----- 可以进行读和写带有b的模式 --- 以二进制的形式对文件进行读写操作 读出/写入的是数据的字节格式rb wb xb abrb+ wb+ xb+ ab+程序本身无法处理程序外部的垃圾【读和写的过程中产生垃圾 程序无法处理】当文件处理完毕后 记得关闭处理通道 防止产出通道垃圾(程序无法处理)handle.close()
对文件进行读取操作
read([size]) 不写参数的话 一次性将文件中的内容全部读取出来传入size大小 一次性读取<=size个字符的数据readline()将数据一行一行的进行读取readlines()读取所有的行 将每一行当做一个元素存放在列表中
# 1.打开文件获取文件的操作手柄# r 读取的是字符数据 记住可能存在编码问题 设置编辑集 utf-8handle = open("hello.txt","r",encoding="gbk")# 调用读取的函数 read# res = handle.read()# print(res)# 获取文件指针位置pos = handle.tell()print(pos)# 按字节读取"""r 按照字符个数读取rb 按照字节数读取"""res = handle.read(5)print(res) # 5个字# 获取文件指针位置pos = handle.tell()print(pos) # gbk 2字节 utf-8 3个字节# 如果还想在读取前面的数据 需要移动文件指针到指定的位置handle.seek(0)# res = handle.read(1)# print(res)# readline 一行一行的读取 读取的时候换行读取出来\n# line = handle.readline()# print(line)# line = handle.readline()# print(line)# # 循环遍历# readlines 读取多行 将每一行当做元素存储在列表中lines = handle.readlines()print(lines)# 关闭通道handle.close()
对文件进行写的操作
write(str/字节数据)将字符串写入到文件中 根据写入的模式来判定写入的内容 a/w --字符串 ab/wb 写入就是字节数据writelines(序列)将序列中的内容写入到文件中
# 写的操作handle = open("hello.txt","a")handle.write("\n这首诗叫做静夜思")# 按序列写入内容list0 = ["小乔流水人家\n","古道西风瘦马\n","夕阳西下\n","断肠人在天涯"]# handle.writelines(list0)for item in list0: handle.write(item)handle.close()
二进制写入
# 二进制写入handle = open("hello.txt","wb")# 写进去的就是字节数据 如果是带b模式只能写入字节数据handle.write("\n离离原上草".encode('gbk'))# 如果遇到写入不成功 可以执行刷新handle.flush()handle.close()
案例:学员管理系统
功能:1.添加学员 2.修改学员 3.查询学员 4.删除学员 0.退出程序
注:根据编号选择对应的功能
学员字段:序号、姓名、年龄、性别、手机号
查询学员:a.查询所有学员 b.姓名查询
修改学员:选查询是否有这个学员存在,在进行修改
删除学员:选查询是否有这个学员存在 a.通过序号删除 b.删除全部学员 c.根据名字删除
例子:#系统界面while 1: print("**********************学员管理系统**********************") print("**********************1.添加学员**********************") print("**********************2.修改学员**********************") print("**********************3.查询学员**********************") print("**********************4.删除学员**********************") print("**********************0.退出程序**********************") num = int(input("请选择你的操作:")) if num == 1: pass elif num==2: pass elif num==3: pass elif num==4: pass else: print("退出程序") break
深拷贝,浅拷贝
#深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变import copyalist=`[``1``,``2``,``3``,[``"a"``,``"b"``]]`d=copy.deepcopy(alist)#copy浅拷贝,没有拷贝子对象,所以原始数据改变,子对象会改变\>> b=alist\>>> print b[1, 2, 3, ['a', 'b']]\>>> alist.append(5)\>>> print alist;print b[1, 2, 3, ['a', 'b'], 5][1, 2, 3, ['a', 'b'], 5]
序列化
直接将对象存放与文件中 这个过程称之为序列化
在文件中读取对象的过程称之为反序列化
python提供了pickle模块实现序列化
CSV操作读写
1.向csv文件中写入数据
import pandas as pa# data = pa.DataFrame(dict(item))# data.to_csv('医药.csv',mode='a',header=False,index=False,sep='|')
(1) 列表方式写入
# 列表方式写入csvimport csv# 当前上下文操作 with 自动关闭通道with open("data.csv","a+",encoding="utf-8",newline='') as csvfile: # csv 写入操作对象 writer = csv.writer(csvfile) # 写入一行 writer.writerow(['1','2','3','4','5']) # 写入多行 writer.writerows([[0,1,3],[1,2,3],[2,3,4]]) # 以二维列表方式进行写入
(2)字典方式写入
# 字典方式的写入csvimport csvwith open("data2.csv","a+",encoding="gbk",newline="") as csvfile: # 字典 name:张三 sex:男 filename = {'name','sex'} # 写入标题 writer = csv.DictWriter(csvfile,fieldnames=filename) writer.writeheader() # 写入内容 writer.writerow({'name':'开群','sex':'男'}) writer.writerow({'name': '嘉豪', 'sex': '男'}) writer.writerow({'name': '小东', 'sex': '男'})
2.读取csv文件中的内容
(1).列表方式的读取
# 列表方式的读取import csvwith open('data.csv','r',encoding='utf-8') as csvfile: # 读取的对象 reader = csv.reader(csvfile) for row in reader: print(row,row[0]) # 读取出来的内容是列表格式的 0
(2).字典方式的读取
# 字典方式的读取import csvwith open('data2.csv','r',encoding='gbk') as csvfile: reader = csv.DictReader(csvfile) for row in reader: print(row['sex']) # 可以直接通过键的名称取值
异常机制
什么是异常?
在程序中异常是不期而遇的各种状态
NameError
ValueError
TypeError
FileNotFound
...
异常机制:
出现异常的时候Python解释器会自动在出现错误的地方生成一个异常对象,而Python解释器在出现异常的位置查看是否有处理异常的操作 如果没有异常抛出 由Python解释器捕获这个异常对象导致程序终止
在程序中手动捕获异常 避免程序异常终止
捕获方式:
try: 可能出现的异常代码except 异常类型 as 变量: 变量就是用于接受 Python解释器抛出的异常对象except 异常类型n as 变量n: passelse: 当try中没有异常的时候执行
练习:
控制用户输入一个整数
# 异常机制num = 0try: num = int(input("请输入一个数字:"))except ValueError as ve: print("输入的格式不正确",ve)else: print("else")
如果不知道具体的异常类型,我们可以使用异常的祖宗(Exception)
在try中存在多个异常 出现第一个异常 将其捕获 try-except就结束了 不会去捕获其他异常
捕获异常只是辅助程序员修改程序中出现的问题
finally: 无论try中是否有异常 都会执行
手动抛出异常
语句:raise 异常对象
抛出异常的语句是跟随在一条语句的后面的
只要在语句后面写上 手动抛出异常的语句 无论这句语句有没有异常 程序都会将异常抛出
raise后面不能直接跟随其他语句 因为这些代码无法执行
手动抛出异常的处理
1.可以当场把出现异常的代码使用try-except包含
2.如果不想执行第一种行为:函数体内有异常 只要调用函数机会出现异常 谁调用函数 谁去处理
自定义异常-- 涉及到面向对象的知识点
练习:
1.删除指定目录
2.在a文件中读取数据,写入到b文件中,如果b文件中有内容,拼接在原有内容的后面
注:内容自定义
预习:面向对象思想
面向对象思想
面向对象编程
OOP(Object Oriented Programming )是程序的一种设计思想。
OOP把对象当做程序的基本单元,一个对象包含了数据和操作数据的功能
常见的编程思想:
面向过程程序
把程序视为一系列命令的集合 也就是一组函数的顺序执行
为了简化程序 把函数分为多个子函数 通过子函数的调用来完成程序的执行 降低程序的复杂度
面向对象程序
把程序做一组对象的集合 每个对象都可以调用其他对象发送过来的消息 并处理这些消息 其实就是一些消息在各个对象直接进行传递
例:在Python中 是面向对象的编程语言 所有的数据类型都可以视为对象
a = 10
例子:
想处理学生的成绩表 查询学生的成绩
student1 =
student2 =
具有相同特征的 -- 归为一类事物
class Student: # 描述所有个体的特征 name = "" score = 0
面向对象和面向过程的区别
面向过程:
在生活中出现面向过程:
一种看待问题的方式 在思考问题的时候着眼于问题是怎样一步一步解决的 亲力亲为的去解决问题
买电脑:查看电脑的资料 --- 去电脑城买电脑 --- 砍价
在程序中:
代码是从上向下执行的
各模块之间的关系尽量的简单 几乎各自独立状态 每一个模块的内部都是顺序 选择 循环结构来完成的
通过函数设置 在自己模块中一步一步调用完成功能的需求
面向对象:【更符合生活】
在生活中:着眼于指定的功能的具体的个体 委托这个个体完成指定的功能 这个具体的个体就是对象
买电脑:委托身边对电脑特别熟悉的人 去帮自己买电脑
在程序中:
把数据和操作的方法放在一起 作为一个相互依存的整体 --- 对象
对同类的整体(对象)进行抽象提取 形参类
类里面存在的是相同对象的共同特性和行为
类通过一个简单的外部方法与外界发生关系,创建对象 达到对象和对象直接交互的关系
项目流程:
产品经理: 根据项目需求 指定项目功能 画出大致的功能流程图---- 原型图
开发人员--测试人员--UI设计人员 一起研究
后台开发人员: 设计数据库 设计接口 UI人员: 设计图 ----->开发人员 会比照原型图 和 设计图做对比 不合理 打回去重做
前段开发人员: 根据UI设计图 进行界面设计
前段开发人员与后台开发人员 对照接口调试数据 测试/调试接口【本地接口】
后台接口上线 -- 在与前段人员进行调试【正式接口也调用完了】
测试人员 :根据功能/设计图 去看项目中的问题 -- 提交问题 --改bug
程序正式上线
面向对象和面向过程区别的总结
这两个都是看待问题的一种思维方式 都能够解决问题
面向过程着眼于问题是一步一步解决的
面向对象着眼于对象:找到具体功能的对象 委托其完成指定功能
类和对象
在面向对象的语言中 类和对象是面向对象的核心
类的概念:
一个具有特殊功能的实体的集合 类是Python语言的基本单位
对象的概念:
在一类事物中 具有特殊功能的实体 可以被委托完成任务 称之为对象 / 实例
两者之间的关系:
类是对象的抽象描述 对象是类的实例【对象是真实存在的具体一个事物】
例子:
类 对象
学生类 开群 小东
电脑 我正在使用的Windows
a = "10“
自定义类的格式
声明一个类的关键字 class对象的描述: 特征描述:名字 年龄 行为描述: 正在吃饭... 正在跑步... 这些描述映射到程序中: 特征描述 --- 变量(属性) 行为描述 --- 功能(方法)class 自定义类的名字: def __init__(self,形参列表): self.特征描述的变量 = 创建对象传值的初始化数据 def 行为名字(self,参与行为的未知项): 行为的实现
案例:
学生类 :
特征描述:姓名 年龄 性别
行为描述:
正在吃饭...
正在跑步...
创建对象格式
变量 = 自定义的类名称(描述该对象的数据值)
练习:
动物类
特性:品种 性别 年龄
行为:吃饭 睡觉
创建对象:
东北虎 雄 2
调用吃饭行为:东北虎在吃饭
长毛兔 雌 1
调用睡觉行为:长毛兔在睡觉
对象和类的回顾
class Student: """ def __init__(self,name,age,sex,address): 初始化方法:来为新建的对象进行初始化特征值的 self --- 表示你当前创建的对象 初始化方法需要明确为那个对象来进行初始化 -- 用self来接受的对象 这个self不需要手动进行赋值的 自动将你创建的对象赋予给self 动态为对象添加字段(属性) :对象有哪些特征 直接通过self.特征名字 动态添加 注:self.name 和 init方法中的形参名name不是一个内容 self.name --- 表示是该对象的特征 形参name --- 接受初始化数据 为特征赋值的 """ def __init__(self,name,age,sex,address): self.name = name self.age = age self.sex = sex self.address =address print("嘿嘿") # 行为 def sleep(self): print(self.name,"在睡觉") # 析构方法 def __del__(self): print(self.name,"在内存中消失了..")
面向对象语言的三大特性:封装 继承 多态
封装
什么是封装?
在程序中 封装就是对具体对象的一种抽象
简单的说:将某些部分隐藏起来 程序的其他位置是看不到的【没有办法直接调用】
隐藏起来 --- 私有化
将类中的特征或者某些方法私有化 外部无法直接使用
封装的好处:
1.保护隐私 -- 把不想让外界知道的部分隐藏起来
2.隔离复杂度 -- 把程序中复杂的实现 隐藏起来 -- 对外部提供一个简单的接口
3.提高代码的健壮性
代码中的封装如何实现:
一般就是将属性私有化 对属性提供对应的set和get方法
练习封装:昨天动物类
属性化get和set方法
方法的调用
对象名.方法名()
将其属性化之后 --- 调用的时候与直接调用属性的格式类似
直接调用属性 对象名.属性名
将方法属性化之后 对象名.方法名
将get方法属性化方式 - 系统提供一个装饰器 @property
将set方法属性化方法 -- 在get方法属性化的基础创建一个setter装饰器 -- 将set方法属性化 格式:@get方法名.setter
继承
在程序中:
有两个或者多个相关的类中提取共性 将共性存放于一个共通类中 通过指定方式有普通类与共通类关联起来 形成继承体系
共通类: 称为父类、超类、基类
普通类:子类
父类和子类的关系:子类继承自父类 父类派生出子类
案例:
学生类:
特征:学号 [姓名 年龄 性别]
行为:学习 [吃饭]
工人类:
特征:工号 [姓名 年龄 性别]]
行为:工作 [吃饭]
人类:
特征:姓名 年龄 性别
行为:吃饭
格式:
父类的格式: class 父类的类名: def __init__(self,形参列表) 子类共同的特征(属性) 子类中共同行为子类 class 子类类名(父类类名): def __init__(self,共性属性列表,个性属性的列表) # 调用父类的共性属性进行初始化 # 在为个性属性进行赋值 个性方式
练习:
Dog:
特征:昵称 年龄 品种 性别
行为:啃骨头 看家
Cat:
特征:昵称 年龄 性别
行为:吃鱼 抓老鼠
抽象父类,完成继承关系,进行测试
要求:对属性进行封装
继承中的概念
单继承:一个类仅有一个父类
多重继承/多层继承:一个类可以间接继承多个父类
子类--父类--爷爷类--祖宗类
虽然是间接继承 也可以直接使用共性的
多继承:一个类可以有多个父类【Python是支持多继承】
class 子类(父类1,父类2,...父类n)
案例:动物体系演示概念
狗:dog
蝙蝠:bat
鹦鹉:parrot
鸵鸟:ostrich
顶级类:动物 Animal
哺乳类Mammal和鸟类Brid
哺乳类:狗 蝙蝠
鸟类:鹦鹉 鸵鸟
能跑的runnable 能飞的flyable
方法的重写
子类去重写父类中的方法
什么时候进行重写?
子类中的功能的实现 父类无法满足了 子类就可以对其进行重写
当子类重写了父类中的方法 子类在调用该方法是 调用的是子类重写的方法
系统方法的重写
__str__ 应用于用户的 用户查看的信息 使用__str__显示出来__repr__ 类似__str__ 正对程序而言__slots__ 对象的特征是动态赋予
多态
多态:事物的多种形态
静态语言 和 动态语言
静态语言 类型是明确的 Java
声明一个变量的时候 必须先指明该变量被赋值的类型 这个变量被赋值只能定义该类型的值 例如:int num = 0
如果赋予其他的值 就会报错
整数:byte short int long
浮点数:float double
....
动态语言:Python
变量的类型是根据赋值来决定
a = 10 a="10"
主人 介绍宠物
宠物猫
宠物狗
类属性和类方法
对象属性:在类中描述的对象特征 ---- 对象属性
想获取/修改对象属性的值 只能借助对象去修改
stu = Student("小东",18)
name age
stu.name
每个对象都有类中描述的属性 但是又可能每个对象对应的特征值是不一样
类属性:
是属于类的 该类所有对象都是共享
无论该类那个对象来进行调用 值都是一样的
直接类中包含的变量 -- 类属性
什么时候去使用类属性?
如果该类所有对象对应的某个属性(字段)的值都是一样的 就可以将这个字段提升为类属性
注;在使用类属性是 建议是通过类名来进行调用 也可以通过对象来调用
类方法需要对象类属性进行操作 将方法设置为类方法
将一个方法设置类方法的方法:需要在方法添加装饰器@classmethod
类方法第一个参数cls--用于接收类型
案例:参考代码
深拷贝和浅拷贝
浅拷贝:
只是拷贝了最外层对象本身 对象内部的其他对象只能拷贝地址引用
深拷贝:
外部和内部的对象都进行拷贝
引用拷贝:
声明一个对象的时候 声明一个变量来接受对象 这个变量只是对象的地址
项目案例:银行管理系统(面向对象)
功能:1.开户 2. 查询 3.存款 4.取款 5.转账 6.该密 7.锁卡 8.解卡 9.销户 0.退出
需求: 根据上面的功能,进行模拟
创建的类:
账号类:姓名 身份证 所拥有的卡【一个账号对象一张卡】
卡类:卡号 密码 金额【默认10】 是否锁卡【默认没锁】
操作类:功能体现
测试类:导入操作类 进行测试
爬虫
requests 获取网页对象模块
西次代理
req ==requests.get(访问地址,headers={请求头},proxies={传入代理地址},timeout=时间,auth=HTTPBasicAuth('账户', '密码'),potion=potion,) req.text:输出返回的值,文本 req.content: 输出返回值,返回一个二进制值req.status_code:打印状态码 200为正常访问req.url: 返回请求路径requests.get(‘https://github.com/timeline.json’) #GET请求requests.post(“http://httpbin.org/post” ,data=表单参数,params=查询参数 ,headers=请求头) #POST请求,上传/添加数据requests.put(“http://httpbin.org/put”) #PUT请求,修改或更改数据 requests.delete(“http://httpbin.org/delete”) #DELETE请求删除数据requests.head(“http://httpbin.org/get”) #HEAD请求requests.options(“http://httpbin.org/get”) #OPTIONS请求chardet 转换编码模块req.encoding = chardet.detect(req.content)["ebconding"](第一种方式)req.encoding = "utf-8"|"gbk":转换编码(第二种方式)#案列import requests r = requests.get(url='http://www.itwhy.org') # 最基本的GET请求print(r.status_code) # 获取返回状态r = requests.get(url='http://dict.baidu.com/s', params={'wd':'python'}) #带参数的GET请求print(r.url) #返回请求网址print(r.text) #打印解码后的返回数据模块chardet 编码转换ss = chardet.detect(req.cintent)[encoding] #获取编码
warnings 模块 去除警告
warnings.filterwarnings("ignore")
xpath 网页解析
提取所有标签下的元素
//div
当前节点
/a
.提取文本
a/text()
提取属性
a/@href
提取指定位置的元素
'//div[1]/a/@hrfe' #获取第一个div标签下是a标签hrfe属性
获取最后一个div标签下是a标签属性
'//div[last()]/a/@hrfe'
获取倒数第二个div标签下是a标签属性
'//div[last()-2]/a/@hrfe'
获取前n个
//div[postion()<n]
通过属性查找
'//div[@class="shu"]/a/@hrfe' '//div[@id="shu"]/a/@hrfe'
xpath模块 解析网页#模块导入from lxml import etree#首先要初始化网页后才能通过xpath#初始化html = etree.HTML((req.text) 或 (req.content)传入请求对象)html.xpath(传入选取的节点)/ 从根节点选取。// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。. 选取当前节点。.. 选取当前节点的父节点。@ 选取属性。| 或者元素child::book 选取所有属于当前节点的子元素的 book 节点。attribute::lang 选取当前节点的 lang 属性。child::* 选取当前节点的所有子元素。attribute::* 选取当前节点的所有属性。child::text() 选取当前节点的所有文本子节点。child::node() 选取当前节点的所有子节点。descendant::book 选取当前节点的所有 book 后代。ancestor::book 选择当前节点的所有 book 先辈。ancestor-or-self::book 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)child::*/child::price 选取当前节点的所有 price 孙节点案列html.xpath(r'//[@id="id选择器名字"]/div/tr/a@herf')#返回的是a标签里的路径 返回是列表案列2html.xpath(r'//[@id="id选择器名字"]/div/tr/a/text()')#返回的是a标签里的文本 返回是列表html.xpath(r'//[@id="id选择器名字"]/div/tr/a/text() | //[@id="id选择器名字"]/div/tr/a/text()') 可以这种表示法
bs4模块
from bs4 import BeautifulSoup #包import requests req = requests.get()req.encoding ="utf-8"# 生成BeautifulSoup对象soup = BeautifulSoup('req.text 或 text.content ','lxml(固定模式)')print(soup.prettify()) # 输出格式化print("hade标签内容",soup.head) # 获取hade标签print(soup.body.a.img) # 获取到body的第一个a标签print("获取所有的img标签",soup.find_all('img')) # 获取所有的img标签 find_all()print("获取的第一个img的属性",url + soup.img['src']) # 获取src的属性print("a标签name",soup.a.name) # 获取a标签名name a元素# 修改a标签为b标签tag = soup.a# 修改btag.name = 'b' # 赋值print("a标签修改后的tag内容",tag)# 获取全部属性print("tag对象的全部属性",tag.attrs)# 获取属性的值 classprint("class的值",tag['class'])# 修改class的值tag['class'] = "Logo"# 输出修改后的内容print(tag.attrs)# 新增属性 idtag['id'] = "logo"print(tag.attrs)# 输出标签print("tag标签",tag)# 删除属性del tag['href']print("tag标签",tag)# 针对内容操作# 获取title的内容tag = soup.titleprint(tag)# 获取标签中的字符串print("tag标签中的字符串",tag.string)# 替换标题内容tag.string.replace_with("重庆华信智原")print(tag)# 获取注释的内容# <!-- 学科建设 -->markup = "<b><!-- 学科建设 --></c>" # <b></c>没有任何意义soup_comment = BeautifulSoup(markup,'lxml')# 获取文本comment = soup_comment.b.stringprint(comment)# 获取某个元素的全部节点 titleprint("名为title的全部节点",soup.find_all('title'))# 获取title的文本数据 string get_text()print(soup.title.string) (一)print(soup.title.get_text()) (二)# 查找ul元素标签 参数 属性 class idtag = soup.find_all('ul',class_='menu') # 按照css类名进行完全匹配print("匹配ulclass名menu节点",tag)# 通过id匹配tag = soup.find_all(id='menu')print("通过id匹配节点",tag)# 通过ul名称下a标签的内容taga = soup.ul.find_all('a')print("ul下所有的a标签",taga)# 输出a标签的所有hreffor tag in taga: print(tag.get('href'))# 获取整个页面的url地址 进行下载在本地tagimgs = soup.find_all('img')print(tagimgs)# 循环输出图片的地址for imgsrc in tagimgs: print(url + imgsrc.get('src')) #ul的class属性pli 下的li 的标签 tu = soup.select(''ul.pli > li > div > a > img'') #返回为一个可迭代的#获取img里的所有src路径sq = [i["src"] for i in tu] #列表生成式
selenium 动态网页爬取
官方文档:https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chainschromedriver下载:http://chromedriver.storage.googleapis.com/index.htmlchromedriver与chrome的对应关系表:https://www.jb51.net/article/151629.htm 基本使用#安装: pip install selenium#导入模块from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains # 鼠标操作模块#创建浏览器对象browser = webdriver.Chrome(executable_path='chromedriver.exe'可不用填写) # 声明一个浏览器对象 指定使用chromedriver.exe路径browser.get("https://www.baidu.com") # 打开Chrome并导入路径input = browser.find_element_by_id("kw") # 通过id定位到input框input.send_keys("python") # 在输入框内输入pythonbrowser.implicitly_wait(2) # 设定等待时间browser.save_screenshot('传入保存的名字')#对当前页面进行截屏#得到需要鼠标移动位置的节点weizhi = find_elements_by_name("q")#把鼠标移上去#perform()立即执行鼠标事件ActionChains('浏览器对象').move_to_element(wenzhi).perform()#鼠标点击事件#鼠标点击长按指定的标签ActionChains('浏览器对象').click_and_hold('q 定位节点 ')for i in range(5): #这一步显示为鼠标长按一个节点,并水平方向移动12个像素 ActionChains('浏览器对象').move_to_element(12,x轴,y轴).perform()#释放动作ActionChains('浏览器对象').release() browser.maximize_window() #窗口最大化 browser.minimize_window() #窗口最小化browser.execute_script("window.scrollTo(0,document.body.scrollHeight)") # 将进度条下拉到最底部(第一种)browser.execute_script(scroll(0,屏幕的高度))#(第二种)find_elements_by_id("q").get_attribute("src") #获取标签里的src 属性#处理弹框页面,accept()确定 dismiss()取消browser.swith_to_alert().accept()#返回上一级页面browser.back()#返回下一级页面browser.forward()find_elements_by_id("q".text #获取文本send_keys() #输入文字用clear() #清空文字用click() #点击按钮用browser.current_url # 打印url路径browser.get_cookies() # 打印Cookiesbrowser.page_source # 打印整个网页源代码browser.close() # 关闭浏览器 #无头浏览器,也可称为不可视化 #导入模块 from selenium.webdriver.chrome.options import Options #实力化options = Options()options.add_argument('--headless')options.add_argument('--disable-gpu') #实力化浏览器时传入一个参数 webdriver.Chrome(url,chrome_options=options) #不显示检测弹框#导入模块from selenium.webdriver import ChromeOptionsoption = ChromeOptions() option.add_experimental_option('excludeSwitches',['enable-automation']) #实力化浏览器时传入一个参数 webdriver.Chrome(options=option) #嵌套iframe#如果定位的标签是存在于iframe标签中,则必须通过如下方法进行定位:div= broeser.switch_to.frame('定位于iframe节点')div.find——element_by_....('需要定位的节点')#获取单节点# 通过属性查找单个节点,当在element后面增添一个“s”时就是查找多个browser.find_elements_by_css_selector(".service-bd li") # 注意是elements多个s,输出为列表find_elements_by_id("q")find_elements_by_name("q")find_elements_by_css_selector("#q")find_elements_by_xpath('//*[@id="q"]')find_elements_by_link_textfind_elements_by_partial_link_textfind_elements_by_tag_namefind_elements_by_class_name browser.find_element_by_id("id的名字") # 通过id找 browser.find_element_by_name("name的名字") # 通过name属性值找 web.find_element_by_class_name() #通过class查找 browser.find_element_by_css_selector(" .classmingzi > 下一级 > ....") # 根据css选择器找#s_position_list > ul > li.con_list_item.first_row.default_list > div.list_item_top > div.position > div.p_top > a # 根据css选择器找 注意 > 两端要有一个空格 browser.find_element_by_xpath('//*[@id="q"]') # 根据xpath找#//*[@id="s_position_list"]/ul/li[1]/div[1]/div[1]/div[1]/a 根据xpath找#关闭浏览器 browser.close()# 其他获取单个节点方法find_element_by_link_textfind_element_by_partial_link_textfind_element_by_tag_namefind_element_by_class_name#案列获取输入框并输入关键字,点击搜索按钮import timefrom selenium import webdriverbrowser = webdriver.Chrome()browser.get("https://www.taobao.com")input = browser.find_element_by_id("q")input.send_keys("iPhone") #在搜索框输入iPhoneinput.clear() # 清空搜索框的文字time.sleep(2)input.send_keys("iPad") # 在搜索框输入iPadbutton = browser.find_element_by_class_name("btn-search") # 获取点击按钮button.click() # 点击搜索#当需要进入二级页面时,所用方法#获取当前所有句柄(窗口) url = browser.window_handles #这回把所有路径都存在一个列表里,而且是 一级网页存放在前面,二级页面放在后面 #切换到二级网页里面,切换到新的页面 browser.switch_to_window(url[1]) #案列from selenium import webdriverfrom selenium.webdriver import ActionChains # 引入动作链browser = webdriver.Chrome()url = "https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable"browser.get(url)browser.switch_to.frame("iframeResult") # 切换到元素所在的frame[框架]"""可以传入id、name、index以及selenium的WebElement对象,index从0开始"""source = browser.find_element_by_css_selector("#draggable") # 找到被拖拽对象target = browser.find_element_by_css_selector("#droppable") # 找到目标actions = ActionChains(browser) # 声明actions对象actions.drag_and_drop(source,target) # 拖拽元素的起点和终点actions.perform() # 执行动作action.click_and_hold() # 点击且长按,更多方法查看官方文档#案列,下拉滚动条到最底部执 selenium import webdriverbrowser = webdriver.Chrome()url = "https://www.zhihu.com/explore"browser.get(url)browser.execute_script("window.scrollTo(0,document.body.scrollHeight)") # 将进度条下拉到最底部(第一种)browser.execute_script(scroll(0,屏幕的高度))#(第二种)browser.execute_script("alert('hello word')") # 弹出alert提示窗#案列from selenium import webdriverbrowser = webdriver.Chrome()url = "https://www.zhihu.com/explore"browser.get(url)"""WebElement常用属性: get_attribute 获取属性值 text 获取文本值 id 获取节点id location 获取节点在页面中的相对位置 tag_name 获取标签名称 size 获取节点大小(宽和高)"""# 获取属性logo = browser.find_element_by_id("zh-top-link-logo") # 获取logo节点print(logo) # 返回值为WebElement对象logo_class = logo.get_attribute("class") # 获取zh-top-link-logo节点的class属性值print(logo_class)# 获取文本值text_Ele = browser.find_element_by_css_selector(".question_link") # 通过css选择器获取文本内容所在的标签text = text_Ele.text # 取出标签内的文本内容print(text)# 获取ID 位置 标签名和大小test = browser.find_element_by_class_name("zu-top-add-question")print(test.id) # 0bfe7ae6-ebd9-499a-8f4e-35ae34776687print(test.location) # {'x': 759, 'y': 7}print(test.tag_name) # buttonprint(test.size) # {'height': 32, 'width': 66}#案列获取子页面from selenium import webdriverbrowser = webdriver.Chrome()url = "https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable"browser.get(url)"""网页中有一种节点叫做iframe,也就是子Frame,相当于页面的子页面,他的结构和外部网页的结构完全一致。selenium打开页面后,他默认是在父级Frame里面操作,而此时如果页面中还有子Frame,他是不能获取到子Frame里面的节点的,这时候就需要使用switch_to.frame()方法来切换Frame。"""browser.switch_to.frame("iframeResult")logo = browser.find_elements_by_class_name("logo")print(logo)# [<selenium.webdriver.remote.webelement.WebElement (session="1ccb11403013c749ce9fceda50a00975", element="88e5924e-d655-44c3-a905-8af1947b9d86")>]# 报错信息""" raise exception_class(message, screen, stacktrace)selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".aaa"} (Session info: chrome=75.0.3770.142)#如果selenium没有在DOM中找到节点,将继续等待,超出设定事件后,则抛出找不到节点的异常。当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间在查找DOM,默认时间是0"""--------------------------显式等待------------------------# 显示等待from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECbrowser = webdriver.Chrome()browser.get("https://www.taobao.com/")wait = WebDriverWait(browser,2)input = wait.until(EC.presence_of_element_located((By.ID,"q")))button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,".btn-search")))print(input,button)# 等待条件# EC.presence_of_element_located 节点出现# EC.element_to_be_clickable 可点击# 更多等待条件查看260页"""引入WebDriverWait对象指定最长等待时间,调用它的until方法,传入要等待的条件expected_conditions,比如这里传入例如presence_of_element_located这个条件,代表节点出现的意思,其参数是节点的定位元组,也就是ID为q的搜索框。这样可以做到的效果就是,在10秒内如果ID为q的节点(即搜索框)成功加载出来,就返回该节点,如果10秒还没有加载出来,就抛出异常。""""""异常:TimeoutException""""""指定要查找的节点,然后指定一个最长等待时间,如果在规定时间内加载出来了这个节点,就返回查找的节点,如果到了规定时间依然没有加载出该节点,则抛出【超时】异常"""#案例import timefrom selenium import webdriverbrowser = webdriver.Chrome()browser.get("https://www.baidu.com")browser.get("https://www.taobao.com")browser.get("https://www.jd.com")browser.back() # 后退time.sleep(2)browser.forward() # 前进browser.close() # 关闭浏览器# 连续访问三个页面from selenium import webdriverbrowser = webdriver.Chrome()browser.get("https://www.zhihu.com/explore")cookies = browser.get_cookies() # 获取cookiesprint(cookies)browser.add_cookie({"name":"name","domain":"www.zhihu.com","vlue":"germey"})browser.delete_all_cookies() # 删除所有cookies#案例import timefrom selenium import webdriverbrowser = webdriver.Chrome()browser.get("https://www.baidu.com")browser.execute_script("window.open()")print(browser.window_handles)# ['CDwindow-7106D94FF002752ADF198B986343E31D', 'CDwindow-B669BA9559DBB78D8D6EC9C5AA699C40']browser.switch_to.window(browser.window_handles[1])browser.get("https://www.taobao.com")time.sleep(1)browser.switch_to.window(browser.window_handles[0])browser.get("https://jd.com")"""1、打开百度网页2、新开一个选项卡,调用execute_script()方法传入JavaScript语法window.open()3、切换到新打开的选项卡,调用window_handles属性获取当前开启的所有选项卡,返回的是选项卡的代号列表,要想切换选项卡只需要调用switch_to.window()方法,这里我们将第二个选项卡代号传入,即跳转到第二个选项卡,在第二个选项卡里打开新页面https://www.taobao.com,然后切换回第一个选项卡打开jd页面"""复制代码异常处理#复制代码from selenium import webdriverbrowser = webdriver.Chrome()browser.get("https://www.baidu.com")try: browser.find_element_by_id("hello")except Exception as e: print(e) # 打印错误信息 Exception捕获所有错误信息赋给efinally: browser.close()"""在使用selenium的过程中,难免遇到一些异常,例如超时、节点未找到错误,一旦出现此类错误,程序便不会在继续运行了,这里我们使用try except语句来捕获各种异常"""#案列import timefrom selenium import webdriverfrom selenium.webdriver import ChromeOptionsoption = ChromeOptions()browser = webdriver.Chrome(executable_path='D:\chromedriver.exe',options=option) # 声明一个浏览器对象 option.add_experimental_option('excludeSwitches', ['enable-automation'])browser.get("https://www.baidu.com") # 打开Chromeinput = browser.find_element_by_id("kw") # 通过id定位到input框input.send_keys("爱奇艺") # 在输入框内输入pythonbrowser.find_element_by_id("su").click()time.sleep(3)browser.find_element_by_xpath('//*[@id="1"]/h3').click()time.sleep(10)browser.switch_to_window(browser.window_handles[1]) # 切换到新打开的选项卡定位爱奇艺的搜索框search = browser.find_element_by_xpath("//input[@class='search-box-input']").send_keys("青春有你")browser.close() # 关闭浏览器#案列from selenium import webdriverfrom selenium.webdriver.chrome.options import Options# 创建chrome参数对象opt = Options()# 把chrome设置成无界面模式,不论windows还是linux都可以,自动适配对应参数opt.add_argument('--headless')# 创建chrome无界面对象driver = webdriver.Chrome(options=opt)driver.get("http://www.baidu.com")print(driver.page_source)
回顾:
采集静态网页和动态网页
scrapy框架
架构图
了解框架的每个部分的功能:
Scrapy Engine(引擎):
负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
Scheduler(调度器):
它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
Downloader(下载器):
负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理.
Spider(爬虫)文件:
它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器).
Item Pipeline(管道):
它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.
Downloader Middlewares(下载中间件):
你可以当作是一个可以自定义扩展下载功能的组件。
Spider Middlewares(Spider中间件):
你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件.
创建Scrapy项目
安装库:pip install scrapy 或者 conda install scrapy
进行项目创建:scrapy startproject demo 后面的demo是项目名称
了解项目相关配置文件:
spiders文件夹:创建Scrapy项目自动创建一个文件夹,用于存放用户编写爬虫脚本
items.py:定义爬虫程序的数据模型 (数据的字段)
middlewares.py:定义数据模型中的中间件(自定义扩展的功能)
pipelines.py:管道文件 负责对爬虫返回数据的处理(分析 过滤 存储等)
settings.py:爬虫程序设置文件 主要是一些优先性设置,优先级越高值越小
scrapy.cfg:内容为scrapy的基础
中间事件:
显示指定类型的日志信息
LOG_LEVEL ='ERROR'
只看到错误信息和打印的内容
LOG_LEVEL='WARNING'
response.xpath('')返回的是一个列表对象,需要用extract()提取出来
当只有一个元素时,可以用extract_tirst(),直接返回一个字符串
在一个函数里可以写多个回调yield 且可以回调给自己,一般用于翻页时
当不在一个函数调用item时,最好用到函数copy.deepcopy(item)深拷贝,避免重复
import copy
请求传参,当需要的数据不在一个网页,需要在下一个网页时,就可以用请求传参
class (BossSpiderlscrapy.Spider) : name = ' boss' #allowed_ domains = [ " www. xxx. com ' ] start urls = ['https:/ /www. zhipin. com/ job_ detail/ ?que ry=python&c ity=101010100&indus def parse(self, response) : li_ list = response . xpath( ' //* [@id="main"]/div/div[3]/ul/li' ) for li in li_ list: item = BossproItem( ) #一级页面需要的内容 item['job_ name'] = li. xpath( './/div [@class="info-prima ry"]/h3/a/div[1]/text()') .extract() #item['job_ name' ] = job_ name # print( job_ name ) #二级页面路径 detail_ url = ' https:/ /www. zhipin. com '+li. xpath( ' .//div [@class=" info-prima ry#对详情页发请求 获取详情页的页面源码数据 #手动请求的发送 #进请求传参i meta=ften 可以将meta字典传递给请求对应的回调函数 yield scrapy.Reauest(detail_url,callback = self.parse_detail,meta= {'item' : item}) #回调函数接受itemdef parse_detail(self, response) : item = response.meta['item'] #二级页面所需要的东西 item['job_ desc'] ="".join(response.xpath('//[@id="main"]/div[3]/div/div[2]/div[2]/div[1]/div/)).extract() #job_ desc =''.join(job_ desc) # print(job_ desc) #item['job_ desc'] = job_ desc yield item
持久化存储:
1、基于终端指令:
特点:只可以将parse方法rerutn(返回)的值,存储在本地的文件中;一般是用列表套字典的形式存储。存储的方式在cmd面板中输入scrapy crawl 爬虫名 -o ./名字.csv(类型有:json、jsonlines,csv,xml,marshal,paickle)
2、基于管道:
item中定义属性,然后在提交给管道持久化存储:
class QiubaiproPipe Line (object): fp = None 并重写父类的一个方法:该方法只在开始爬虫的时候被调用一次 defm apen spider(selfaspiderli #print( '开始爬虫....... ) self.fp = open(' ./giubai. txt'。'w' zencoding='utf-8' ) #专门用来处理item类型对象 #该方法可以接收爬虫文件提交过来的item对象进该方法没接收到-个item就会被调用一次 def process_ item(self, item, spider) : authar = item [ ' author' ] content= item[ ' content'] self. fp. write( author+' : '+content+'\n' ) return item def close_ spider(self,spider) : #关闭文件 self.fp.close()#另一种import pandas as pd #模块class DiannaoPipeline: def process_item(self, item, spider): data = pd.DataFrame(dict(item)) data.to_csv('电脑.csv',mode='a',index=False,header=False,sep=',')
当爬取图片时,第一个页面只需解析出图片路径,在管道内设置如下:,重新创建类,需要在配置里去启动;
然后在在配置文件里去设置保存路径:
Scrapy编写步骤:
1.定义采集数据模型
# Define here the models for your scraped items## See documentation in:# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass DemoItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # 标题 title = scrapy.Field() # 时间 date = scrapy.Field() # 作者 author = scrapy.Field() # 浏览次数 view_count = scrapy.Field()
2.编写spider脚本
命令 进入编写脚本的文件夹中:cd 命令
输入创建命令:scrapy genspider [项目名]tipdm [连接地址]http://www.tipdm.com/
3.启动框架命令
scrapy crawl 项目名 ------- 项目运行
4.保存数据(分析/清洗等)
5.设置配置信息
定制中间件
user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1 QQBrowser/6.9.11079.201", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)"]
{'ip_port': '111.8.60.9:8123', 'user_passwd': 'user1:pass1'},{'ip_port': '101.71.27.120:80', 'user_passwd': 'user2 :pass2'},{'ip_port': '122.96.59.104:80', 'user_passwd': 'user3:pass3'},{'ip_port': '122.224.249.122:8088', 'user_passwd': 'user4:pass4'}
思考:现在通过的scrapy框架采集的静态网页,那么我们要采集动态网页? scrapy + selenium运用
作业:通过已学过的知
识去扩展,利用scrapy框架+selenium去采集动态网页数据。保存到csv、json、txt
一、爬虫的反反爬虫方案
1.通过浏览器的方式访问
解决方案:携带参数,模拟浏览器进行访问。需要注意的字段:User-Agent,属性值正常范围。
2.ip限制
如果一个固定的ip在短暂的时间,快速大量的访问一个网站,后台的管理员可以编写ip限制,不让修改ip就不能访问。
解决方案:IP代理池
3.session访问限制
后台统计登录的操作,比如短时间的点击事件,请求数据事情,与正常进行对比,用于区分用户是否处理异常状态,如果是,则限制登录用户的权限,需要添加数据的操作,阈值设置不好,容易造成错误操作。
解决方案:注册多个账号,模拟多个ip,模拟正常的操作
4.验证码限制
a) 图片验证码
复杂型:找出同类别的图片
解决方案:平台雇佣人力,专门帮人识别验证码,识别完后结果传回去。总共的操作几秒钟的时间。打码平台具有记忆功能。图片被识别后“鞋子",那么下次这张图片再次出现的时候,就会自动判断它是”鞋子"。
b) 简单型:数字+字母
解决方案:可以直接使用OCR识别技术(利用第三方库pytesseract)来识别.
背景比较清晰,识别没有任何问题。如果背景比较模糊,那么需要进行灰度处理。
c) 短信验证码
用webbrowser技术,模拟用户打开短信的行为,最终获取验证码。
d) 滑动验证码
对于滑动验证码,可以利用图片的像素作为线索,确定好基本的属性值,查看位置的差值,对于差值超过基本的属性值,我们就能大概确定图片的位置。
e) 计算图片验证码
数据计算也有可能是汉字计算,保存为黑白图,把验证码按照字体颜色二值化,去出噪点,然后将所有图片异常进行像素对比,计算出相似的值,找出最像的那张图片。
f) 倒立文字验证码
有8个汉字,倒立,扭曲
方案:首先确定前两个倒立的文字,可以确定后面8个文字的左边,验证码中的8个文字的位置确定。只需要提出确定每个汉字所在的坐标将其存入列表中。然后交个人工确定倒立文字的序号,将列表中的序号对应到坐标可以实现。 接入第三方平台,实现破解网站的验证码
g) 文字的点击顺序
方案:确定坐标,根据提示的顺序进行点击
h)绘制图案验证码
每次拖动的顺序不一样,结果也不一样。
利用机器学习所有的拖动顺序,利用1万张图片进行训练,完成类似人的操作,最终识别。
也可以利用selenium技术来模拟人的操作顺序
5.动态数据的加载
可以利用selenium、json文件
6.数据加密-- 使用加密的算法
前段加密:通过查询的参数、user-agent、验证码、cookie等前段数据进行加密生成一串加密的指令。将指令作为参数,再次进行服务器请求。该加密的参数为空或者错误,服务器就不响应数据。
服务器加密:在服务端同样有一段加密的逻辑,生成一串编码,与请求的编码进行匹配,匹配通过则返回数据。
解决方案:js加密破解方式,就是找到js的加密的代码,然后通过第三方库js2py在python中运行js代码,就能获取到相应的编码。
二、简单的验证码识别+JS逆向
a) 验证码识别
安装机器视觉的工具 Tesseract
tesseract是一套流行的OCT算法,专门做图片内容识别。我们只需要下载相应的训练数据就能使用teserract进行图片内容读取。
# 导入库import pytesseractfrom PIL import Imageimage = Image.open('code.jpg')# res = pytesseract.image_to_string(image)# print(res)# 对图片进行灰度处理image = image.convert('L')# 加载图片data = image.load()w,h = image.size # ndarryfor i in range(w): for j in range(h): if data[i,j] > 40: data[i,j] = 255 else: data[i,j] = 0image.show()res = pytesseract.image_to_string(image)print(res)
b) JS逆向
# 目标地址:https://fanyi.youdao.com/# https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule# e:输入翻译内容# ts:当前时间戳字符串# bv:将user-agent经过md5加密后的字符串# salt:时间戳字符串拼接随机数# sign:将"fanyideskweb" + e + i+ "Tbh5E8=q6U3EXe+&L[4c@"import randomimport timeimport hashlibimport requestsclass Youdao(object): def __init__(self, word): # 初始化 self.url = "https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule" # 请求头信息 self.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", "Cookie": "[email protected]; OUTFOX_SEARCH_USER_ID_NCOO=1946771786.421294; JSESSIONID=aaacAtoZRHi0Ud08zLvNx; ___rl__test__cookies=1622786844607", "Referer": "https://fanyi.youdao.com /" } # 翻译内容 self.word = word # 定义字典存储表单数据 self.post_boyd = {} def genrator_post(self): # 得到ts 拿到时间戳 ts = str(int(time.time()*1000)) # 得到salt 时间戳 + 一个随机的值 salt = ts + str(random.randint(0,10)) # 得到sign 字符串 + 陪翻译的值 + 盐值 sign_str = "fanyideskweb" + self.word + salt + "Tbh5E8=q6U3EXe+&L[4c@" # 将sign_str md5进行加密 md5 = hashlib.md5() md5.update(sign_str.encode()) sign = md5.hexdigest() # 生成数据信息 self.post_boyd = { "i": self.word, "from": "AUTO", "to": "AUTO", "smartresult": "dict", "client": "fanyideskweb", "salt": salt, "sign": sign, "lts": ts, "bv": "960780974768cef6d5005081d3d340f0", "doctype": "json", "version": "2.1", "keyfrom": "fanyi.web", "action": "FY_BY_REALTlME" } # 请求方法 def send_request(self): # 发送请求 response =requests.post(self.url,headers=self.headers,data=self.post_boyd) return response.json() # 解析方法 def parser_response(self,ret_dict): ret = ret_dict["translateResult"][0][0]["tgt"] print("翻译的文本:{} 翻译后的结果:{}".format(self.word,ret)) # 操作方法 def run(self): self.genrator_post() ret_dict = self.send_request() self.parser_response(ret_dict)if __name__ == '__main__': word = input("请输入要翻译的文本:") yd = Youdao(word) yd.run()
三、Scrapy框架分布式(reids)
a) reids 数据库
1.redis安装和连接
reids:是一个数据库
2.数据库分为:
关系型数据库(数据在磁盘中存放):mysql,sqlserver等 存放字段 id name
非关系型数据库(数据存放在内存中,提供了持久化保存的机制):redis、mongodb等 存放的kv:key-value
3.redis安装:官网进行下载:redis.io
Redis官网是不支持windows的,只是开发一个msi格式安装文件
下载msi安装包:安装过程一路next,默认选择即可,需要添加到环境变量,设置内存的大小默认100M
4.启动redis
启动命令:redis-cli
5.键命令
0-15:redis默认有16个数据库,默认是在第0个数据库中
select num:切换数据库
keys * :所有键
6.五种数据类型:字符串(string)、哈希(字典)、列表(list)、集合(set)、有序集合(zset)
7.交互方式,三种
7.1指令交互(cmd窗口化)
7.2客户端交互(可视化工具)
7.3代码交互(python操作redis)
五种数据类型使用方式
字符串(string):
set key value: #设置key-valueget key: #获取key所对应的valuegetrange key start end: #字符串的提取,字符串从0开始,包含start和endgetset key value :#设置key的值,返回的是旧值,新值会设置成功setex key seconds value: #设置key的值 过期时间为seconds 如果存在 则替换之,时间为s为单位setnx key value:#该key不存在的时候才设置,存在不设置strlen key :#得到该key对应的值的长度mset key value[key value]:#同时设置多个键值对mget :#一次获取多个键的值incr key:#为key对应的值增加1 如果key不存在那么先创建key,值为0,然后再设置为1decr key:#为key对应的值减1incrby key number :#在指定的key对应的值加number
redis 在python中的运用
import redisres = redis.StrictRedis('localhost', 6379)# sq = res.hkeys('books')## for i in sq:# print(i.decode('utf-8'))# print(res.hlen('books'))# sq = (res.hmget('books','僵尸管家2006','劫匪与僵尸'))# for i in sq:# print(i.decode('utf-8'))# sq = res.hgetall('books')# # print((sq.d).decode('utf-8'))# print(res.hset('books','劫匪与僵尸').decode('utf-8'))# sq = res.hvals('books')# for i in sq:# print(i.decode('utf-8'))# print(res.llen('book'))# print(res.lindex('book',5).decode('utf-8'))# sq = res.lrange('book',3,10)# for i in sq:# print(i.decode('utf-8'))#存: red = redis.StrictRedis('localhost', 6379) #哈希 red.hset('安康', str(item['name']), str(item)) #列表 red.lpush('安康',str(item))
哈希(hash)以字典的形式:
增:1、hmset key(名字) field1(键) value1(值) [field2 value2 ] #同时将多个 field-value (域-值)对设置到哈希表 key 中。2、hsetnx key field value #只有在字段 field 不存在时,设置哈希表字段的值。3、hincrby key field increment #为哈希表 key 中的指定字段的整数值加上增量 increment删:1、hdel key field1 [field2] #删除一个或多个哈希表字段查:1、hexists key field #查看哈希表 key 中,指定的字段是否存在 存在返回TRUE 否则返回false。2、hget key field #获取存储在哈希表中指定字段的值。3、hgetall key #获取在哈希表中指定key的所有字段和值,返回值为字典4、hkeys key #获取所有哈希表中的 key字段, 所有键的值5、hlen key #获取哈希表中字段的数量 键的数量6、hmget key field1 [field2] #获取多个给定字段的值7、hset key field value #将哈希表key中的字段field的值设为value 。8、hvals key #获取哈希表中所有值。 返回值为列表9、hscan key cursor [MATCH pattern] [COUNT count] #迭代哈希表中的键值对。
列表(list):
增:1、lpush key value1 [value2] #将一个或多个值插入到列表头部2、rpush key value1 [value2] #在列表中添加一个或多个值3、rpushx key value #为已存在的列表添加值4、lpushx key value #将一个值插入到已存在的列表头部5、linsert key before|after pivot value #在列表的元素前或者后插入元素删:1、blpop key1 [key2 ] timeout #移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。2、brpop key1 [key2 ] timeout #移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。3、rpop key #移除列表的最后一个元素,返回值为移除的元素。4、rpoplpush source destination #移除列表的最后一个元素,并将该元素添加到另一个列表并返回5、lpop key #移出并获取列表的第一个元素6、lrem key count value #移除列表元素7、ltrim key start stop #对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。查:1、lindex key index #通过索引获取列表中的元素2、llen key #获取列表长度3、lrange key start stop #获取列表指定范围内的元素4、lset key index value #通过索引设置列表元素的值5、brpoplpush source destination timeout #从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
集合(set):
sadd key member1 [member2] #向集合添加一个或多个成员scard key #获取集合的成员数sdiff key1 [key2] #返回第一个集合与其他集合之间的差异。sdiffstore destination key1 [key2] #返回给定所有集合的差集并存储在 destination 中sinter key1 [key2] #返回给定所有集合的交集sinterstore destination key1 [key2] #返回给定所有集合的交集并存储在 destination 中 sismember key member #判断 member 元素是否是集合 key 的成员smembers key #返回集合中的所有成员smove source destination member #将 member 元素从 source 集合移动到 destination 集合spop key # 移除并返回集合中的一个随机元素srandmember key [count] #返回集合中一个或多个随机数srem key member1 [member2] #移除集合中一个或多个成员sunion key1 [key2] #返回所有给定集合的并集sunionstore destination key1 [key2] #所有给定集合的并集存储在 destination 集合中sscan key cursor [MATCH pattern] [COUNT count] #迭代集合中的元素
有序集合(zset):
zadd key score1 member1 [score2 member2]
#向有序集合添加一个或多个成员,或者更新已存在成员的分数zcard key #获取有序集合的成员数zcount key min max #计算在有序集合中指定区间分数的成员数zincrby key increment member #有序集合中对指定成员的分数加上增量 incrementzinterstore destination numkeys key [key ...] #计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 destination 中zlexcount key min max #在有序集合中计算指定字典区间内成员数量zrange key start stop [WITHSCORES] #通过索引区间返回有序集合指定区间内的成员zrangebylex key min max [LIMIT offset count] #通过字典区间返回有序集合的成员zrangebyscore key min max [WITHSCORES] [LIMIT] #通过分数返回有序集合指定区间内的成员zrank key member #返回有序集合中指定成员的索引zrem key member [member ...] #移除有序集合中的一个或多个成员zremrangebylex key min max #移除有序集合中给定的字典区间的所有成员zremrangebyrank key start stop #移除有序集合中给定的排名区间的所有成员zremrangebyscore key min max #移除有序集合中给定的分数区间的所有成员zrevrange key start stop [WITHSCORES] #返回有序集中指定区间内的成员,通过索引,分数从高到低zrevrangebyscore key max min [WITHSCORES] #返回有序集中指定分数区间内的成员,分数从高到低排序zrevrank key member #返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序zscore key member #返回有序集中,成员的分数值zunionstore destination numkeys key [key ...] #计算给定的一个或多个有序集的并集,并存储在新的 key 中zscan key cursor [MATCH pattern] [COUNT count] #迭代有序集合中的元素(包括元素成员和元素分值)
mysql讲解
下载地址:https://dev.mysql.com/downloads/mysql/
一、mysql的基本操作
1.开启mysql数据库服务
格式:net start mysql(服务名) -- mysql57
2.关闭mysql数据服务
格式:net stop mysql(服务名) -- mysql57
3.登录mysql
格式:mysql -u root -p 输入密码
4.查看当前数据库版本信息
格式:select version();
5.查看当前的时间
格式: select now();
6.退出
quit,exit
二.数据库的database的操作
1.查看当前有哪些数据库
格式:show databases;
2.创建数据库
格式:create database 数据库名 charset='utf8'
3.使用数据库
格式:use 数据名称
4.查看当前使用的数据库
格式;select database()
5.删除数据库
格式:drop database db
三、表table的操作
1.查看当前数据库有哪些表
格式:show tables;
2.创建一个表
格式:create table 表名(字段名 及类型)
auto_increment :自动增加
例:
create table student(
id int auto_increment primary key,
name varchar(20) not null,
age int not null,
address varchar(50),
gender bit default 1);
3.查看表的结构
格式:desc 表名
4.查看创建表的语句
格式:show create table 表名
5.修改表
5.1 修改表的名字
格式:rename table 旧表名 to 新表名
5.2 修改表的结构 modify|add|drop|change
格式:modify 修改表字段类型
alter table 表名 modify 字段名 varchar(30)
格式:add 添加新的字段
alter table 表名 add 字段名 类型
格式:change 修改 表格里面的标题
alter table 表名 change 旧字段名 新字段名 新字段数据类型
格式:drop 删除
alter table 表名 drop 字段名
6.删除表
格式:drop table 表名
四、数据的操作
1.插入数据
格式:insert into 表名 values(值1,值2...)
注意;顺序需要与表的结构对应,主键可以写为0
2.缺省值插入
格式:insert into 表名(字段名1,字段名2..) values(值1,值2...)
3.插入多条数据
格式:insert into 表名 values(值1,值2..),(值1,值2...),(值1,值2...)
例:insert into student values(0,'赵六',24,'叙利亚',1),(0,'黑七',25,'火星',1)
4.修改数据
格式:update 表名 set 字段名1=值,字段名2=值... where 条件 (注意只要满足条件都会改变)
5.删除数据
格式:delete from 表名 where 条件
6.查询数据
格式:
6.1 查询所有
格式:select * from 表名
6.2 按条件查询
格式:select 字段名1,字段名2.. from 表名 where 条件
注意:6.2.1 select 后跟的是查询结果需要显示的字段名
6.2.2 *表示所有的字段名都要显示
6.2.3 from 后面跟的是表名 表示从那个表查询
6.2.4 where 后面跟的是筛选的条件
6.2.5 可以使用别名 字段名 as 别名
条件中:运算
a) 比较运算符 > 大于 <小于 >= <= = != 等
格式:select 字段名1,字段名2... from 表名 where 字段名 比较运算符 值
b) 逻辑运算符 and 且 or 或者 not 非
格式:select 字段名1,字段名2... from 表名 where 字段名 比较运算符 值 逻辑运算符 字段名 比较运算符 值
6.3 模糊查询 like
% 表示多个任意字符
_ 表示一个任意字符
格式: select * from 表名 where 字段名 like 查询值
6.4 范围查询
in (多个值) 判断一个值是否在多个值中的一个
between 值1(包含) and 值2(包含) 判断一个值是否在 值1 和 值2之间
格式:select 字段名1,字段名2... from 表名 where 字段名 范围运算符 值
7.空判断
is null 为空
is not null 不为空
格式:select 字段名1,字段名2... from 表名 where 字段名 is null
8.优先级 ()
9.去重复的值
格式:select distinct 字段名 from 表名 where 条件
10.聚合函数
count(*) 求当前结果的共有多少条数据
sum(字段名) 求列名对应的和
avg(字段名) 求列名对应的平均值
max(字段名) 求列名对应的最大值
min(字段名) 求列名对应的最小值
...
例子:求当前表总共有多少条数据?
select count(*) from student;
求年龄最小的值?
select min(age) from student;
11.分组 group by
格式: select 字段名.... from 表名 where 条件 group by 字段名
例子:1.查看当前数据表的性别
select gender from student group by gender
2.统计男生和女生各有多少个?
select gender,count(*) from student group by gender
3.统计所有女生的个数? 男生代表1 女生代表0
select gender as 性别,count(*) as 个数 from student where gender=0 group by gender
select gender as 性别,count(*) as 个数 from student group by gender having gender=0
where 查询条件 是对select 数据结果的查询条件
having 查询条件 是对group by分组后的结果加的查询条件
12.排序 order by
升序: 从小到大 asc
降序: 从大到小 desc
格式:select * from 表名 order by 字段名 asc;
13.分页
格式: select 字段名... from 表名 where 条件 limit 起始值,多少条数据
起始值可以从0开始
标签:大海,name,python,res,汇总,--,key,print,browser From: https://www.cnblogs.com/demo443/p/17154173.html