访问Python官网: https://www.python.org/ 点击downloads按钮,在下拉框中选择系统类型(windows/Mac OS/Linux等) 选择下载最新版本的Python
双击下载好的Python安装包
勾选左下角 Add Python 3.9 to PATH 选项
然后选择 Install now 立刻安装Python. 默认安装,或者选择自定义安装(Customize installation)
自定义安装
选择install,到此安装完成
点击电脑左下角开始按钮,输入 cmd
进入到windows的命令行模式。 在命令行中输入**Python
**,正确显示Python版本,即表示Python安装成功
pip 是一个现代的,通用的Python包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能,便 于我们对Python的资源包进行管理。
在安装Python时,会自动下载并且安装pip
在windows命令行里,输入**pip -V
** 可以查看pip的版本。
**
pip install <包名>
**安装指定的包
pip uninstall <包名>
删除指定的包
pip list
显示已经安装的包
pip freeze
显示已经安装的包,并且以指定的格式显示
运行pip install 命令会从网站上下载指定的python包,默认是从`https://files.pythonhosted.org/ 网站上下 载。这是个国外的网站,遇到网络情况不好的时候,可能会下载失败,我们可以通过命令,修改pip现在软件时的 源。
国内常用的pip下载源列表:
阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
在pycharm是这样修改的
file——>setting——>Project:项目名称——>Python Interpreter——>选择+新增——>选择MANAGER REPOSITORIES——>选择+新增。最好把之前的源删掉,然后换上我们提供的源
以#开头,**
#
**右边的所有东西当做说明,而不是真正要执行的程序,起辅助说明作用。
print('hello world')
#我的作用是在控制台输出hello world
以
'''
开始,并以**'''
** 结束,我们称之为多行注释。
变量即是可以变化的量,可以随时进行修改。 程序就是用来处理数据的,而变量就是用来存储数据的。
程序中: 在 Python 里为了应对不同的业务需求,也把数据分为不同的类型。
在python中,只要定义了一个变量,而且它有数据,那么它的类型就已经确定了,不需要咱们开发者主动的 去说明它的类型,系统会自动辨别。也就是说在使用的时候 “变量没有类型,数据才有类型”。
比如下面的示例里,a 的类型可以根据数据来确认,但是我们没法预测变量 b 的类型。
如果临时想要查看一个变量存储的数据类型,可以使用 type(变量的名字),来查看变量存储的数据类型。
- 标识符由字母、下划线和数字组成,且数字不能开头。
- 严格区分大小写。
- 不能使用关键字。
标识符命名要做到顾名思义
遵守一定的命名规范
- 驼峰命名法,又分为大驼峰命名法和小驼峰命名法
- 还有一种命名法是用下划线“_”来连接所有的单词,比如send_buf
一些具有特殊功能的标识符,这就是所谓的关键字。 关键字,已经被python官方使用了,所以不允许开发者自己定义和关键字相同名字的标识符。
函数 | 说明 |
---|---|
int(x) |
将x转换为一个整数 |
float(x) |
将x转换为一个浮点数 |
str(x) |
将对象 x 转换为字符串 |
bool(x) |
将对象x转换成为布尔值 |
print(int("123")) # 123 将字符串转换成为整数
print(int(123.78)) # 123 将浮点数转换成为整数
print(int(True)) # 1 布尔值True转换成为整数是 1
print(int(False)) # 0 布尔值False转换成为整数是 0
# 以下两种情况将会转换失败
'''
123.456 和 12ab 字符串,都包含非法字符,不能被转换成为整数,会报错
print(int("123.456"))
print(int("12ab"))
'''
f1 = float("12.34")
print(f1) # 12.34
print(type(f1)) # float 将字符串的 "12.34" 转换成为浮点数 12.34
f2 = float(23)
print(f2) # 23.0
print(type(f2)) # float 将整数转换成为了浮点数
str1 = str(45)
str2 = str(34.56)
str3 = str(True)
print(type(str1),type(str2),type(str3))
print(bool(''))
print(bool(""))
print(bool(0))
print(bool({}))
print(bool([]))
print(bool(()))
取a=9 b=2
运算符 | 描述 | 实例 |
---|---|---|
+ |
加 | 两个对象相加 a + b 输出结果 11 |
- |
减 | 两个对象相加 a - b 输出结果 7 |
* |
乘 | 两个对象相加 a * b 输出结果 14 |
/ |
除 | 两个对象相加 a / b 输出结果 2.5 |
// |
取整除 | 两个对象相加 a // b 输出结果 2 |
% |
求余 | 两个对象相加 a % b 输出结果 1 |
** |
指数 | 两个对象相加 a ** b 输出结果 81 |
() |
小括号 | 提高运算优先级 |
注意:混合运算时,优先级顺序为:
** 高于 * / % // 高于 + -
,为了避免歧义,建议使用 () 来处理运 算符优先级。 并且,不同类型的数字在进行混合运算时,整数将会转换成浮点数进行运算。
a = "hello"
b = " "
c = "world"
print(a + b + c)
a = "hello"
b = 12
c = "world"
print(a + b + c)
a = "hello"
b = 10
print(a*b)
运算符 | 描述 | 实例 |
---|---|---|
= |
赋值运算符 | 把 = 号右边的结果 赋给 左边的变量,如 num = 1 + 2 * 3,结果num的值为7 |
运算符 | 描述 | 实例 |
---|---|---|
+= |
加法赋值运算符 | c += a 等效于 c = c + a |
-= |
减法赋值运算符 | c -= a 等效于 c = c - a |
*= |
乘法赋值运算符 | c *= a 等效于 c = c * a |
/= |
除法赋值运算符 | c /= a 等效于 c = c / a |
//= |
取整除赋值运算符 | c //= a 等效于 c = c // a |
%= |
取模赋值运算符 | c %= a 等效于 c = c % a |
**= |
幂赋值运算符 | c * *= a 等效于 c = c ** a |
以下假设变量a为10,变量b为20
运算符 | 描述 | 实例 |
---|---|---|
== |
等于:比较对象是否相等 | (a == b) 返回 False |
!= |
不等于:比较两个对象是否不相等 | (a != b) 返回 true |
> |
大于:返回x是否大于y | (a > b) 返回 False |
>= |
大于等于:返回x是否大于等于y | (a >= b) 返回 False |
< |
小于:返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特 殊的变量True和False等价 | (a < b) 返回 true |
<= |
小于等于:返回x是否小于等于y | (a <= b) 返回 true |
运算符 | 逻辑表 达式 | 描述 | 实例 |
---|---|---|---|
and |
x and y | 只要有一个运算数是False,结果就是False; 只有所有的运算数都为True时,结果才是True 做取值运算时,取第一个为False的值,如果所有的值 都为True,取最后一个值 | True and True and False–> 结果为False True and True and True–> 结果为True |
or |
x or y | 只要有一个运算数是True,结果就是True; 只有所有的运算数都为False时,结果才是False 做取值运算时,取第一个为True的值,如果所有的值都 为False,取最后一个值 | False or False or True–>结 果为True False or False or False–>结 果为False |
not |
not x | 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not True --> False |
python中变量的输出,print 会自动在行末加上回车,如果不需回车,只需在print语句的结尾添加一个逗号”,“
print('hello')
格式化符号大全
符 号 | 描述 |
---|---|
%c | 格式化字符及其ASCII码 |
%s | 格式化字符串 就是强转 ----->str(变量) |
%d | 格式化整数 ------->int(变量) |
%u | 格式化无符号整型 |
%o | 格式化无符号八进制数 |
%x | 格式化无符号十六进制数 |
%X | 格式化无符号十六进制数(大写) |
%f | 格式化浮点数字,可指定小数点后的精度,且四舍五入 ‘%.2f’ % s ,表示将变量s保留2位小数且四舍五入 |
%e | 用科学计数法格式化浮点数 |
%E | 作用同%e,用科学计数法格式化浮点数 |
%g | 浮点型数据 会去掉多余的零 至多保留6位 |
%G | 浮点型数据 会去掉多余的零 至多保留6位 |
%p | 用十六进制数格式化变量的地址 |
print('%s' % 'hello world') # 字符串输出
hello world
#就是将非字符串%后面的字符串替换成'%s'
格式化操作符辅助指令:
符号 | 描述 |
---|---|
* | 定义宽度或者小数点精度 |
- | 用做左对齐 |
+ | 在正数前面显示加号( + ) |
< sp > | 在正数前面显示空格 |
# | 在八进制数前面显示零(‘0’),在十六进制前面显示’0x’或者’0X’(取决于用的是’x’还是’X’) |
0 | 显示的数字前面填充’0’而不是默认的空格 |
% | ‘%%‘输出一个单一的’%’ |
(var) | 映射变量(字典参数) |
m.n. | m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话) |
%
操作符是传统格式化输出的基本方法,从 Python 2.6 版本开始,为字符串数据新增了一种格式化方法str.format()
,它通过{}
操作符和:
辅助指令来代替%
操作符。‘b’ - 二进制。将数字以2为基数进行输出。
‘c’ - 字符。在打印之前将整数转换成对应的Unicode字符串。
‘d’ - 十进制整数。将数字以10为基数进行输出。
‘o’ - 八进制。将数字以8为基数进行输出。
‘x’ - 十六进制。将数字以16为基数进行输出,9以上的位数用小写字母。
‘e’ - 幂符号。用科学计数法打印数字。用’e’表示幂。
‘g’ - 一般格式。将数值以fixed-point格式输出。当数值特别大的时候,用幂形式打印。
‘f’ - 浮点数。将数字以浮点数形式输出,默认6位小数。
‘n’ - 数字。当值为整数时和’d’相同,值为浮点数时和’g’相同。不同的是它会根据区域设置插入数字分隔符。
‘%’ - 百分数。将数值乘以100然后以fixed-point(‘f’)格式打印,值后面会有一个百分号。>>> print('{0:b}'.format(3)) 11 >>> print('{:c}'.format(20)) >>> print('{:d}'.format(20)) 20 >>> print('{:o}'.format(20)) 24 >>> print('{:x}'.format(20)) 14 >>> print('{:e}'.format(20)) 2.000000e+01 >>> print('{:g}'.format(20.1)) 20.1 >>> print('{:f}'.format(20)) 20.000000 >>> print('{:n}'.format(20)) 20 >>> print('{:%}'.format(20)) 2000.000000%
python 3.6 中引入了一种新的字符串格式化,用起来更为方便。使用方式如下,以 f 开头,包含的 {} 表达式在程序运行时会被表达式的值代替。
name = 'Bertram'
age = 30
print(f"hello,{name},you are {age}")
在Python中,获取键盘输入的数据的方法是采用 input 函数。input()会把用户输入的任何值都作为字符串来对待
password = input("请输入密码:")
print('您刚刚输入的密码是:%s' % password)
if 要判断的条件:
条件成立时,要做的事情
age = 30
if age >= 18:
print("我已经成年了")
if 条件:
满足条件时的操作
else:
不满足条件时的操作
age = 18
if age >= 18:
print("我可以去红浪漫了")
else:
print("未成年,不允许去")
if xxx1:
事情1
elif xxx2:
事情2
elif xxx3:
事情3
score = 77
if score>=90:
print('本次考试,等级为A')
elif score>=80:
print('本次考试,等级为B')
elif score>=70:
print('本次考试,等级为C')
elif score>=60:
print('本次考试,等级为D')
elif score<60:
print('本次考试,等级为E')
在Python中 for循环可以遍历任何序列的项目,如一个列表或者一个字符串等
for 临时变量 in 列表或者字符串等可迭代对象:
循环满足条件时执行的代码
# 遍历字符串
for s in "hello":
print(s)
# 打印数字
for i in range(5):
print(i)
range 可以生成数字供 for 循环遍历,它可以传递三个参数,分别表示 起始、结束和步长。
for i in range(2, 10, 3):
print(i)
字符串的常见操作包括:
获取长度:len
len函数可以获取字符串的长度。查找内容:find
查找指定内容在字符串中是否存在,如果存在就返回该内容在字符串中第一次 出现的开始位置索引值,如果不存在,则返回-1.判断:startswith,endswith
判断字符串是不是以谁谁谁开头/结尾 计算出现次数:count
返回 str在start和end之间 在 mystr里面出现的次数替换内容:replace
替换字符串中指定的内容,如果指定次数count,则替换不会超过count次。切割字符串:split
通过参数的内容切割字符串- **
修改大小写:upper,lowe
**r 将字符串中的大小写互换空格处理:strip
去空格 字符串拼接:join 字符串拼接
添加元素
- append 在末尾添加元素
# 定义变量A,默认有3个元素 A = ['张三', '李四', '王二'] print("‐‐‐‐‐添加之前,列表A的数据‐‐‐‐‐A=%s" % A) # 提示、并添加元素 temp = input('请输入要添加的学生姓名:') A.append(temp) print("‐‐‐‐‐添加之后,列表A的数据‐‐‐‐‐A=%s" % A)
- insert 在指定位置插入元素
insert(index, object) 在指定位置index前插入元素object
s = ['a', 'b', 'm', 's'] s.insert(3, 'h') print(s)
- extend 合并两个列表
a = ['a', 'b', 'c'] b = ['d', 'e', 'f'] a.extend(b) print(a) # ['a', 'b', 'c', 'd', 'e', 'f'] 将 b 添加到 a 里 print(b) # ['d','e','f'] b的内容不变
我们是通过指定下标来访问列表元素,因此修改元素的时候,为指定的列表下标赋值即可。
# 定义变量A,默认有3个元素 A = ['张三', '李四', '王二'] print("‐‐‐‐‐修改之前,列表A的数据‐‐‐‐‐A=%s" % A) # 修改元素 A[1] = '麻子' print("‐‐‐‐‐修改之后,列表A的数据‐‐‐‐‐A=%s" % A)
- in(存在),如果存在那么结果为true,否则为false
- not in(不存在),如果不存在那么结果为true,否则false
# 待查找的列表 nameList = ['张三', '李四', '王二'] # 获取用户要查找的名字 findName = input('请输入要查找的姓名:') # 查找是否存在 if findName in nameList: print('在列表中找到了相同的名字') else: print('没有找到')
列表元素的常用删除方法有:
del
:根据下标进行删除movieName = ['加勒比海盗', '骇客帝国', '第一滴血', '指环王', '霍比特人', '速度与激情'] print('‐‐‐‐‐‐删除之前‐‐‐‐‐‐movieName=%s' % movieName) del movieName[2] print('‐‐‐‐‐‐删除之后‐‐‐‐‐‐movieName=%s' % movieName)
pop
:删除最后一个元素movieName = ['加勒比海盗', '骇客帝国', '第一滴血', '指环王', '霍比特人', '速度与激情'] print('‐‐‐‐‐‐删除之前‐‐‐‐‐‐movieName=%s' % movieName) movieName.pop() print('‐‐‐‐‐‐删除之后‐‐‐‐‐‐movieName=%s' % movieName)
remove
:根据元素的值进行删除movieName = ['加勒比海盗', '骇客帝国', '第一滴血', '指环王', '霍比特人', '速度与激情'] print('‐‐‐‐‐‐删除之前‐‐‐‐‐‐movieName=%s' % movieName) movieName.remove('指环王') print('‐‐‐‐‐‐删除之后‐‐‐‐‐‐movieName=%s' % movieName)
Python的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。
元组语法很简单,只要将一些值用逗号分隔,就能自动创建一个元组,只有一个元素的元组,必须要在元素后写一个逗号
切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作。
切片的语法:[起始:结束:步长],也可以简化使用 [起始:结束]
注意:选取的区间从"起始"位开始,到"结束"位的前一位结束(不包含结束位本身),步长表示选取间隔。
s = 'Hello World!'
print(s)
print(s[4]) # o 字符串里的第4个元素
print(s[3:7]) # lo W 包含下标 3,不含下标 7
print(s[1:]) # ello World! 从下标为1开始,取出 后面所有的元素(没有结束位)
print(s[:4]) # Hell 从起始位置开始,取到 下标为4的前一个元素(不包括结束位本身)
print(s[1:5:2]) # el 从下标为1开始,取到下标为5的前一个元素,步长为2(不包括结束位本身)
使用key查找数据,还可以使用get来获取数据
info = {'name': '班长', 'age': 18}
print(info['age']) # 获取年龄
# print(info['sex']) # 获取不存在的key,会发生异常
print(info.get('sex')) # 获取不存在的key,获取到空的内容,不会出现异常
print(info.get('sex', '男')) # 获取不存在的key, 可以提供一个默认值。
字典的每个元素中的数据是可以修改的,只要通过key找到,即可修改
info = {'name': '班长', 'id': 100}
print('修改之前的字典为 %s:' % info)
info['id'] = 200 # 为已存在的键赋值就是修改
print('修改之后的字典为 %s:' % info)
如果在使用 变量名[‘键’] = 数据 时,这个“键”在字典中,不存在,那么就会新增这个元素
info = {'name': '班长'}
print('添加之前的字典为:%s' % info)
info['id'] = 100 # 为不存在的键赋值就是添加元素
print('添加之后的字典为:%s' % info)
对字典进行删除操作,有一下几种:
- del
info = {'name': '班长', 'id': 100} print('删除前,%s' % info) del info['name'] # del 可以通过键删除字典里的指定元素 print('删除后,%s' % info)
- clear()
info = {'name': 'monitor', 'id': 100} print('清空前,%s' % info) info.clear() print('清空后,%s' % info)
- 遍历字典的key(键)
info = {'name': 'monitor', 'id': 100, 'position': '班长'} for key in info.keys(): print(key)
- 遍历字典的value(值)
info = {'name': 'monitor', 'id': 100, 'position': '班长'} for value in info.values(): print(value)
- 遍历字典的项(元素)
info = {'name': 'monitor', 'id': 100, 'position': '班长'} for item in info.items(): print(item)
- 遍历字典的key-value(键值对)
info = {'name': 'monitor', 'id': 100, 'position': '班长'} for key, value in info.items(): print("key=%s,value=%s" % (key, value))
def 函数名():
代码
定义了函数之后,就相当于有了一个具有某些功能的代码,想要让这些代码能够执行,需要调用它 调用函数很简单的,通过 函数名() 即可完成调用
函数定义好以后,函数体里的代码并不会执行,如果想要执行函数体里的内容,需要手动的调用函数。 每次调用函数时,函数都会从头开始执行,当这个函数中的代码执行完毕后,意味着调用结束了。
def f1():
print('欢迎光临德云水都')
print('男宾2位')
f1()
在定义函数的时候,小括号里写等待赋值的变量名,称为 “形参”
在调用函数的时候,小括号里写真正要进行运算的数据,称为 “实参”
def add2num(a, b):
c = a + b
print(c)
add2num(11, 22) # 调用带有参数的函数时,需要在小括号中,传递数据
想要在函数中把结果返回给调用者,需要在函数中使用return
# 定义函数
def add2num(a, b):
return a + b
# 调用函数,顺便保存函数的返回值
result = add2num(100, 98)
# 因为result已经保存了add2num的返回值,所以接下来就可以使用了
print(result)
strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
**注意:**该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
str = "00000003210Runoob01230000000";
print str.strip( '0' ); # 去除首尾字符 0
str2 = " Runoob "; # 去除首尾空格
print str2.strip();
# result
3210Runoob0123
Runoob
str = "123abcrunoob321"
print (str.strip( '12' )) # 字符序列为 12
# result
3abcrunoob3
返回一个长度为width,两边用fillchar(单字符)填充的字符串,即字符串str居中,两边用fillchar填充。若字符串的长度大于width,则直接返回字符串str.(width等于字符串的长度加上fillchar)
语法:str.center(width , “fillchar”) -> str 返回字符串 注意:引号不可省
sstr1 = "i love Python"
print(str1.center(30, "*"))
print(str1.center(1, "*"))
print(str1.center(20, "8"))
将字符串中的小写字母转为大写字母
str1 = "i love Python"
print(str1.upper())
eval( )函数官方解释:将字符串str当作有效的表达式来求值并返回计算结果
eval(expression, globals=None, locals=None)
- expression参数,将字符串str当成有效的表达式来求值并返回计算结果。
- globals和locals参数是可选的,
如果提供了globals参数,那么它必须是dictionary类型;
如果提供了locals参数,那么它可以是任意的map对象。
a = "[[1, 2], [3, 4], [5, 6]]"
b = eval(a)
print(b)
print(type(b))
c = "{1: 'a', 2: 'b'}"
d = eval(c)
print(d)
print(type(d))
e = "11 + 12"
f = eval(e)
print(f)
Python 有办法将任意值转为字符串:将它传入repr() 或str() 函数。
函数str() 用于将值转化为适于人阅读的形式,而repr() 转化为供解释器读取的形式。
repr()函数得到的字符串通常可以用来重新获得该对象,repr()的输入对python比较友好。通常情况下obj==eval(repr(obj))这个等式是成立的。
print(repr([0, 1, 2, 3]))
print(repr('Hello'))
print(str(1.0 / 7.0))
print(repr(1.0 / 7.0))
'sep'.join(seq)
参数说明
sep:分隔符。可以为空
seq:要连接的元素序列、字符串、元组、字典上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串
返回值:返回一个以分隔符sep连接各个元素后生成的字符串
局部变量,就是在函数内部定义的变量 其作用范围是这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的
def test1():
a = 100
print("修改前---a=%d" % a)
a = 200
print("修改后---a=%d" % a) # 虽然没有定义变量a但是依然可以获取其数据
def test2():
a = 300
print("----test2-----a=%d" % a) # 虽然没有定义变量a但是依然可以获取其数据
# 调用函数
test1()
test2()
如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量。
在函数外边定义的变量叫做 全局变量 全局变量能够在所有的函数中进行访问
# 定义全局变量
a = 100
def test1():
print(a) # 虽然没有定义变量a但是依然可以获取其数据
def test2():
print(a) # 虽然没有定义变量a但是依然可以获取其数据
# 调用函数
test1()
test2()
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件
open(文件路径,访问模式)
f = open('test.txt', 'ab')
E:\python
,从电脑的盘符开始,表示的就是一个绝对路径。test.txt
,是在当前文件夹查找 test.txt 文件./test.txt
,也是在当前文件夹里查找 test.txt 文件,./
**表示的是当前文件夹。 …/test.txt ,从当前文件夹的上一级文件夹里查找 test.txt 文件。../
**表示的是上一级文件夹 demo/test.txt ,在当前文件夹里查找 demo 这个文件夹,并在这个文件夹里查找 test.txt 文件。访问模式 | 说明 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
w | 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
w+ | 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
**写数据(write) **
f = open('test.txt', 'a+') f.write('hello world, i am here!\n' * 5) f.close()
#open函open('test.txt', 'a+')配合with使用时,操作完成后会自动释放占用的资源,无需使用.close关闭文件 with open('test.txt', 'a+') as f f.write('hello world, i am here!\n' * 5)
读数据(read) 使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入 num,那么就表示读取文件中所有的数据
f = open('test.txt', 'r') content = f.read(5) # 最多读取5个数据 print(content) print("‐" * 30) # 分割线,用来测试 content = f.read() # 从上次读取的位置继续读取剩下的所有的数据 print(content) f.close()
读数据(readline)。readline只用来读取一行数据。
f = open('test.txt', 'r') content = f.readline() print("第1行:%s" % content) content = f.readline() print("第2行:%s" % content) f.close()
读数据(readlines)。readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行为列表的 一个元素。
f = open('test.txt', 'r') content = f.readlines() print(type(content)) for temp in content: print(temp) f.close()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XmtkiyNX-1635002626136)(C:/Users/25959/AppData/Roaming/Typora/typora-user-images/image-20210902155317373.png)]
读取中文文件
在open函数末端加一个encoding声明就好了,encoding声明里用的编码是文本自己本身所用的编码
input = open(test.txt,encoding= 'utf-8') data = input.read()
我们进入open函数的源码发现以下解释:
快速查看windows 的字符集:
win+R 输入cmd
右击菜单栏进入属性
或者使用decode(“utf-8”)解码
seek简介:用于移动文件读取指针到文件指定的位置
file. seek(offset[, whence])whence:0,1,2三个参数,0表示文件开头,1表示当前位置,2表示文件结尾
offset:偏移量,可正可负,正数表示向后移动offset位,负数表示向前移动offset位。
tell函数会返回当前文件指针在文件中的位置。
- utf8编码下:如果是中文的话,一个字的偏移量是3。
- 每一行的末尾其实是\r\n,代表了2个偏移量
通过文件操作,我们可以将字符串写入到一个本地文件。但是,如果是一个对象(例如列表、字典、元组等),就无 法直接写入到一个文件里,需要对这个对象进行序列化,然后才能写入到文件里。 设计一套协议,按照某种规则,把内存中的数据转换为字节序列,保存到文件,这就是序列化,反之,从文件的字节序列恢复到内存中,就是反序列化。 对象—》字节序列 === 序列化 字节序列–》对象 ===反序列化 Python中提供了JSON这个模块用来实现数据的序列化和反序列化。
JSON(JavaScriptObjectNotation, JS对象简谱)是一种轻量级的数据交换标准。JSON的本质是字符串。
**JSON提供了dump和dumps方法,将一个对象进行序列化。 dumps方法的作用是把对象转换成为字符串,它本身不具备将数据写入到文件的功能。**json只能序列化最基本的数据类型,json只能把常用的数据类型序列化(列表、字典、列表、字符串、数字、),但不能是日期格式、类对象等。
把数据类型转换成字符串
import json
file = open('names.txt', 'w')
names = ['zhangsan', 'lisi', 'wangwu', 'jerry', 'henry', 'merry', 'chris']
# file.write(names) 出错,不能直接将列表写入到文件里
# 可以调用 json的dumps方法,传入一个对象参数
result = json.dumps(names)
# dumps 方法得到的结果是一个字符串
print(type(result)) #
# 可以将字符串写入到文件里
file.write(result)
file.close()
dump方法可以在将对象转换成为字符串的同时,指定一个文件对象,把转换后的字符串写入到这个文件里。
#输出中文的json。通过使用 ensure_ascii=False,输出原有的语言文字。indent参数是缩进数量。
import json
file = open('names.txt', 'w',encoding= 'utf-8')
names = ['张三', '李四', '王二', 'jerry', 'henry', 'merry', 'chris']
# dump方法可以接收一个文件参数,在将对象转换成为字符串的同时写入到文件里
json.dump(names, file, ensure_ascii=False,indent=4)
file.close()
使用loads和load方法,可以将一个JSON字符串反序列化成为一个Python对象。
loads方法需要一个字符串参数,用来将一个字符串加载成为Python对象。
# 调用loads方法,传入一个字符串,可以将这个字符串加载成为Python对象
import json
result = json.loads('["zs", "lisi", "wangwu", "jerry", "henry", "merry", "chris"]')
print(type(result))
for i in result:
print(i)
load方法可以传入一个文件对象,用来将一个文件对象里的数据加载成为Python对象。
import json
# 以可读方式打开一个文件
file = open('names.txt', 'r')
# 调用load方法,将文件里的内容加载成为一个Python对象
result = json.load(file)
print(result)
file.close()
程序在运行过程中,由于我们的编码不规范,或者其他原因一些客观原因,导致我们的程序无法继续运行,此时, 程序就会出现异常。如果我们不对异常进行处理,程序可能会由于异常直接中断掉。为了保证程序的健壮性,我们 在程序设计里提出了异常处理这个概念。
try…except语句可以对代码运行过程中可能出现的异常进行处理。 语法结构:
try:
可能会出现异常的代码块
except 异常的类型:
出现异常以后的处理语句
示例:
try:
f = open('test.txt', 'r')
print(f.read())
except FileNotFoundError:
print('文件没有找到,请检查文件名称是否正确')
wordcloud是优秀的词云展示第三方库,以词语为基本单位,通过图形可视化的方式,更加直观和艺术的展示文本;
使用wordColud设计词云的时候可能会产生乱码问题,因为wordColud默认的字体不支持中文,所以我们只需要替换wordColud的默认字体即可正常显示中文。
安装:
网络正常情况下命令行输入
pip install wordcloud
或者直至使用pycharm安装
参数解读:
参数: font_path : string #字体路径,需要展现什么字体就把该字体路径+后缀名写上,如:font_path = '黑体.ttf' width : int (default=400) #输出的画布宽度,默认为400像素 height : int (default=200) #输出的画布高度,默认为200像素 prefer_horizontal : float (default=0.90) #词语水平方向排版出现的频率,默认 0.9 (所以词语垂直方向排版出现频率为 0.1 ) mask : nd-array or None (default=None) # #如果参数为空,则使用二维遮罩绘制词云。如果 mask 非空,设置的宽高值将被忽略,遮罩形状被 mask 取代。除全白(#FFFFFF)的部分将不会绘制,其余部分会用于绘制词云。如:bg_pic = imread('读取一张图片.png'),背景图片的画布一定要设置为白色(#FFFFFF),然后显示的形状为不是白色的其他颜色。可以用ps工具将自己要显示的形状复制到一个纯白色的画布上再保存,就ok了。 scale : float (default=1) #按照比例进行放大画布,如设置为1.5,则长和宽都是原来画布的1.5倍。 min_font_size : int (default=4) #显示的最小的字体大小 font_step : int (default=1) #字体步长,如果步长大于1,会加快运算但是可能导致结果出现较大的误差。 max_words : number (default=200) #要显示的词的最大个数 stopwords : set of strings or None #设置需要屏蔽的词,如果为空,则使用内置的STOPWORDS background_color : color value (default=”black”) #背景颜色,如background_color='white',背景颜色为白色。 max_font_size : int or None (default=None) #显示的最大的字体大小 mode : string (default=”RGB”) #当参数为“RGBA”并且background_color不为空时,背景为透明。 relative_scaling : float (default=.5) #词频和字体大小的关联性 color_func : callable, default=None #生成新颜色的函数,如果为空,则使用 self.color_func regexp : string or None (optional) #使用正则表达式分隔输入的文本 collocations : bool, default=True #是否包括两个词的搭配 colormap : string or matplotlib colormap, default=”viridis” #给每个单词随机分配颜色,若指定color_func,则忽略该方法。 函数: fit_words(frequencies) #根据词频生成词云 generate(text) #根据文本生成词云 generate_from_frequencies(frequencies[, ...]) #根据词频生成词云 generate_from_text(text) #根据文本生成词云 process_text(text) #将长文本分词并去除屏蔽词(此处指英语,中文分词还是需要自己用别的库先行实现,使用上面的 fit_words(frequencies) ) recolor([random_state, color_func, colormap]) #对现有输出重新着色。重新上色会比重新生成整个词云快很多。 to_array() # numpy array to_file(filename) #输出到文件
from matplotlib import pyplot as plt
from wordcloud import WordCloud
filename = "text.txt" # 文本路径
with open(filename, encoding="utf-8") as f:
data = f.read()
font = r'D:\pythonProject\demo\simhei.ttf'
wc = WordCloud(font_path=font, # 如果是中文必须要添加字体
background_color='white',
width=1000,
height=800,
).generate(data)
wc.to_file('ss.png') # 保存图片
plt.imshow(wc) # 用plt显示图片
plt.axis('off') # 不显示坐标轴
plt.show() # 显示图片
# wc.to_file('img.jpg') #保存图片
import jieba
from matplotlib import pyplot as plt
from wordcloud import WordCloud
from PIL import Image
import numpy as np
font = r'D:\pythonProject\demo\simhei.ttf' # 字体路径
text = (open(r'text.txt', 'r', encoding='utf-8')).read()
cut = jieba.cut(text) # 分词
string = ' '.join(cut) # 将词语连接起来,以空格为连接词
img = Image.open(r'img_1.png') # 打开背景图片
img_array = np.array(img) # 将图片装换为数组
stopword = ['xa0'] # 设置停止词,也就是你不想显示的词
wc = WordCloud(
background_color='pink',
width=1000,
height=800,
max_font_size=70,
mask=img_array,
font_path=font,
)
wc.generate_from_text(string) # 绘制图片
plt.imshow(wc)
plt.axis('off')
plt.show() # 显示图片
wc.to_file(r'new.png') # 保存图片
如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小 蜘蛛,沿着蜘蛛网抓取自己想要的数据
1.爬取网页:爬取整个网页 包含了网页中所有得内容
2.解析数据:将网页中你得到的数据 进行解析
3.难点:爬虫和反爬虫之间的博弈
- 数据分析/人工数据集
- 社交软件冷启动
- 舆情监控
- 竞争对手监控
实例:
百度、360、google、sougou等搜索引擎‐‐‐伯乐在线
功能 :
访问网页‐>抓取数据‐>数据存储‐>数据处理‐>提供检索服务
robots协议:
一个约定俗成的协议,添加robots.txt文件,来说明本网站哪些内容不可以被抓取,起不到限制作用 自己写的爬虫无需遵守
网站排名(SEO):
- 根据pagerank算法值进行排名(参考个网站流量、点击率等指标)
- 百度竞价排名
缺点:
- 抓取的数据大多是无用的
- 不能根据用户的需求来精准获取数据
功能:
根据需求,实现爬虫程序,抓取需要的数据
设计思路:
1.确定要爬取的url
如何获取Url
2.模拟浏览器通过http协议访问url,获取服务器返回的html代码
如何访问
3.解析html字符串(根据一定规则提取需要的数据)
如何解析
- User‐Agent:
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版 本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
- 代理IP:
- 西次代理
- 快代理
- 什么是高匿名、匿名和透明代理?它们有什么区别?
- 使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。
- 使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。
- 使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。
- 验证码访问:
- 打码平台
- 云打码平台
- 超级
- 动态加载网页 网站返回的是js数据 并不是网页的真实数据
- selenium驱动真实的浏览器发送请求
- 数据加密:
- 分析js代码
urllib是 Python标准库中最常用的 Python网页访问的模块,它可以让用户像访问本地文本文件一样读取网页的内容。 Python2系列使用的是 urllib2, Python3以后将其全部整合为 urllib;在 Python3.x中,用户可以使用 urllib 这个库抓取网页。
urllib库提供了一个网页访问的简单易懂的API接口,还包括一些函数方法,用于进行参数编码、下载网页等操作。这个模块的使用门槛非常低,初学者也可以尝试去抓取和读取或者保存网页。 urllib是ー个URL处理包,在这个包中集合了一些处理URL的模块。 (1) urllib.request模块:用来打开和读取URL.
(2) urllib.error模块:包含一些由 urllib.request产生的错误,可以使用try进行捕捉处理。
(3) urllib.parse模块:包含一些解析URL的方法。
(4) urllib.robotparser模块:用来解析 robots.txt文本文件。它提供了一个单独的RobotFileparser类,通过该类提供的 can_fetch()方法测试爬虫是否可以下载一个页面
urllib.request.urlopen() 模拟浏览器向服务器发送请求
response 服务器返回的数据
response的数据类型是HttpResponse
字节‐‐>字符串
解码decode
字符串‐‐>字节
编码encode
read() 字节形式读取二进制 扩展:rede(5)返回前几个字节
readline() 读取一行
readlines() 一行一行读取 直至结束
getcode() 获取状态码
geturl() 获取url
getheaders() 获取headers
urllib.request.urlretrieve()
请求网页
请求图片
请求视频
# 使用urllib来获取百度首页的源码
import urllib.request
# (1)定义一个url 就是你要访问的地址
url = 'http://www.baidu.com'
# (2)模拟浏览器向服务器发送请求 response响应
response = urllib.request.urlopen(url)
# (3)获取响应中的页面的源码 content 内容的意思
# read方法 返回的是字节形式的二进制数据
# 我们要将二进制的数据转换为字符串
# 二进制--》字符串 解码 decode('编码的格式')
content = response.read().decode('utf-8')
# 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
f = open('my_urllib.html', mode='w', encoding='utf-8')
# 将爬取到的内容写入文件
f.write(content)
# 使用urllib来获取百度首页的源码
import urllib.request
# (1)定义一个url 就是你要访问的地址
url = 'http://www.baidu.com'
# (2)模拟浏览器向服务器发送请求 response响应
response = urllib.request.urlopen(url)
# 返回状态码 如果是200了 那么就证明我们的逻辑没有错
print(response.getcode())
# 返回的是url地址
print(response.geturl())
# 获取是一个状态信息
print(response.getheaders())
import urllib.request
# 下载网页
# url_page = 'http://www.baidu.com'
# url代表的是下载的路径 filename文件的名字
# 在python中 可以变量的名字 也可以直接写值
urllib.request.urlretrieve(url_page,'baidu.html')
import urllib.request
# 下载图片
# 随便找个图片的地址链接就行
url_img = 'https://p8.qhimg.com/bdm/1000_618_80/t017973b4213ee88f43.jpg'
urllib.request.urlretrieve(url=url_img, filename='李知恩.jpg')
import urllib.request
# 下载视频
# 有些视频的地址有保护机制,可能不行
url_video='https://vd2.bdstatic.com/mda-mi1c1q6ap99uxzcz/sc/cae_h264/1630571601182790753/mda-mi1c1q6ap99uxzcz.mp4?v_from_s=hkapp-haokan-tucheng&auth_key=1630720133-0-0-30e1ea53397a0b973dcdc92b5ef4f77a&bcevod_channel=searchbox_feed&pd=1&pt=3&abtest='
urllib.request.urlretrieve(url_video, '篮球.mp4')
UA介绍:User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统 及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等
语法:request = urllib.request.Request()
# url的组成 # https://www.baidu.com/s?wd=周杰伦 # http/https www.baidu.com 80/443 s wd = 周杰伦 # # 协议 主机 端口号 路径 参数 锚点 #常见的端口号 # http 80 # https 443 # mysql 3306 # oracle 1521 # redis 6379 # mongodb 27017
import urllib.request
url = 'https://www.baidu.com'
# url的组成
# https://www.baidu.com/s?wd=周杰伦
# http/https www.baidu.com 80/443 s wd = 周杰伦 #
# 协议 主机 端口号 路径 参数 锚点
# http 80
# https 443
# mysql 3306
# oracle 1521
# redis 6379
# mongodb 27017
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
# 因为urlopen方法中不能存储字典 所以headers不能传递进去
# 请求对象的定制
# 之所以写url=url,headers=headers,而不直接写url,headers是因为源码def __init__(self, url, data=None, headers={},
# origin_req_host=None, unverifiable=False,
# method=None)的第三参数才是headers,如果直接写,那么会把headers当作第二个参数
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf8')
print(content)
由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号, 这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。 但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突, 所以,中国制定了GB2312编码,用来把中文编进去。 你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc‐kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。 因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。 Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。 现代操作系统和大多数编程语言都直接支持Unicode。
urllib.parse.urlencode()就是将中文变成Unicode编码,这样才不会报错
# https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6
# 需求 获取 https://www.baidu.com/s?wd=周杰伦的网页源码
import urllib.request
import urllib.parse
url = 'https://www.baidu.com/s?wd='
# 请求对象的定制为了解决反爬的第一种手段
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
# 将周杰伦三个字变成unicode编码的格式
# 我们需要依赖于urllib.parse
name = urllib.parse.quote('周杰伦')
url = url + name
print(url)
# 请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的内容
content = response.read().decode('utf-8')
# 打印数据
print(content)
通过访问频度反爬
普通用户通过浏览器访问网站的速度相对爬虫而言要慢得多,所以不少网站会利用这一点对访问频度设定一个阈值,如果一个IP单位时间内的访问频度超过预设的阈值,则网站将会对该IP做出访问限制。通常情况下,该IP需要经过验证码验证后才能继续正常访问,严重时,网站甚至会在一段时间内禁止该IP访问
# https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6
# 需求 获取 https://www.baidu.com/s?wd=周杰伦的网页源码
import urllib.request
import urllib.parse
# 请求对象的定制为了解决反爬的第一种手段
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
# 将周杰伦三个字变成unicode编码的格式
# 我们需要依赖于urllib.parse
base_url = 'https://www.baidu.com/s?'
data = {
'wd': '周杰伦',
'sex': '男',
'location': '中国台湾省'
}
new_data = urllib.parse.urlencode(data)
# 请求资源路径
url = base_url + new_data
print(url)
# 请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的内容
content = response.read().decode('utf-8')
# 打印数据
print(content)
百度翻译
# post请求
import json
import urllib.request
import urllib.parse
# 请求对象的定制为了解决反爬的第一种手段
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
url = 'https://fanyi.baidu.com/sug'
keyword = input('请输入您要查询的单词')
data = {
'kw': keyword
}
# post请求的参数 必须要进行编码
data = urllib.parse.urlencode(data).encode('utf‐8')
# post的请求的参数 是不会拼接在url的后面的 而是需要放在请求对象定制的参数中
# post请求的参数 必须要进行编码
request = urllib.request.Request(url=url, headers=headers, data=data)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')
obj = json.loads(content)
print(obj)
演示如何找到请求地址:
案例:豆瓣电影
import urllib.request
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
# (1) 请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
# (2)获取响应的数据
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
# (3) 数据下载到本地
# open方法默认情况下使用的操作系统的编码,windows是GBK 如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
# encoding = 'utf-8'
fp = open('douban.json', 'w', encoding='utf-8')
fp.write(content)
# 还可以这样写
# with open('douban1.json','w',encoding='utf-8') as fp:
# fp.write(content)
案例:爬取大量豆瓣电影
# page 1 2 3 4
# start 0 20 40 60
# start (page - 1)*20
# 下载豆瓣电影前10页的数据
# (1) 请求对象的定制
# (2) 获取响应的数据
# (3) 下载数据
import urllib.parse
import urllib.request
def create_request(page):
base_url = 'https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&'
data = {
'start': (page - 1) * 20,
'limit': 20
}
data = urllib.parse.urlencode(data)
url = base_url + data
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
request = urllib.request.Request(url=url, headers=headers)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(page, content):
with open('douban_' + str(page) + '.json', 'w', encoding='utf-8') as fp:
fp.write(content)
# 程序的入口
if __name__ == '__main__':
start_page = int(input('请输入起始的页码'))
end_page = int(input('请输入结束的页面'))
for page in range(start_page, end_page + 1):
# 每一页都有自己的请求对象的定制
request = create_request(page)
# 获取响应的数据
content = get_content(request)
# 下载
down_load(page, content)
案例:KFC官网商铺位置
# 1页
# http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# post
# cname: 北京
# pid:
# pageIndex: 1
# pageSize: 10
# 2页
# http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# post
# cname: 北京
# pid:
# pageIndex: 2
# pageSize: 10
import urllib.request
import urllib.parse
def create_request(page):
base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname1'
data = {
'cname': "天津",
'pid': '',
'pageIndex': page,
'pageSize': '10'
}
data = urllib.parse.urlencode(data).encode('utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
request = urllib.request.Request(url=base_url, headers=headers, data=data)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(page, content):
with open('kfc_' + str(page) + '.json', 'w', encoding='utf-8') as fp:
fp.write(content)
if __name__ == '__main__':
start_page = int(input('请输入起始页码'))
end_page = int(input('请输入结束页码'))
for page in range(start_page, end_page + 1):
# 请求对象的定制
request = create_request(page)
# 获取网页源码
content = get_content(request)
# 下载
down_load(page, content)
数据分析是用适当的方法对收集来的大量数据进行分析,帮助人们作出判断,以便采取适当行动。
matplotlib: 最流行的Python底层绘图库,主要做数据可视化图表,名字取材于MATLAB,模仿MATLAB构建
Matplotlib可以画图线图、散点图、等高线图、条形图、柱形图、3D图形、图形动画等。
每个红色的点是坐标,把5个点的坐标连接成一条线,组成了一个折线图
调用
matplotlib
库绘图一般是用pyplot
子模块,其集成了绝大部分常用方法接口,查看pyplot源码文件可以发现,它内部调用了matplotlib路径下的大部分子模块(不是全部),共同完成各种丰富的绘图功能。其中有两个需要重点指出:figure和axes
,其中前者为所有绘图操作定义了顶层类对象Figure,相当于是提供了画板
;而后者则定义了画板中的每一个绘图对象Axes,相当于画板内的各个子图
。换句话说,figure是axes的父容器,而axes是figure的内部元素,而我们常用的各种图表、图例、坐标轴等则又是axes的内部元素。
3种绘图接口
用matplotlib绘制可视化图表,主要有3种接口形式:
- plt接口,例如常用的plt.plot(),用官方文档的原话,它是matplotlib的一个state-based交互接口,相关操作不面向特定的实例对象,而是面向"当前"图
- 面向对象接口,这里的面向对象主要是指Figure和Axes两类对象。前文提到,Figure提供了容纳多个Axes的画板,而Axes则是所有图标数据、图例配置等绘图形元素的容器。面向对象的绘图,就是通过调用Figure或Axes两类实例的方法完成绘图的过程(当然,Figure和Axes发挥的作用是不同的)。通俗的说,就是将plt中的图形赋值给一个Figure或Axes实例,方便后续调用操作
- pylab接口,如前所述,其引入了numpy和pyplot的所有接口,自然也可用于绘制图表,仍然可看做是pyplot接口形式。因其过于庞大官方不建议使用
鉴于pylab的特殊性,matplotlib绘图主要采用前2种方式。而在二者之间:
- 如果是简单的单图表绘制,或者是交互实验环境,则plt接口足以满足需要,且操作简单易用
- 如果是多图表绘制,需要相对复杂的图例配置和其他自定义设置,那么毫无疑问面向对象接口绘图是当之无愧的不二选择
需要指出,Axes从形式上是坐标轴axis一词的复数形式,但意义上却远非2个或多个坐标轴那么简单:如果将Figure比作是画板的话,那么Axes就是画板中的各个子图,这个子图提供了真正用于绘图的空间,除了包含纯粹的两个坐标轴(axes)外,自然还包括图形、图例等。所以准确的讲,如果说Axes和坐标轴有何关联的话,那么Axes应该算是广义的坐标轴,或简单称之为子图即可。
创建画板,包括创建figure和axes对象,常用有3种方法(plt指的就是pyplot)
- plt.figure,主要接收一个元组作为figsize参数设置图形大小,返回一个figure对象用于提供画板,用来创建一个空包白画布
- plt.axes,接收一个figure或在当前画板上添加一个子图,返回该axes对象,并将其设置为"当前"图,缺省时会在绘图前自动添加
- plt.subplot,主要接收3个数字或1个3位数(自动解析成3个数字,要求解析后数值合理)作为子图的行数、列数和当前子图索引,索引从1开始(与MATLAB保存一致),返回一个axes对象用于绘图操作。这里,可以理解成是先隐式执行了plt.figure,然后在创建的figure对象上添加子图,并返回当前子图实例
- plt.subplots,主要接收一个行数nrows和列数ncols作为参数(不含第三个数字),创建一个figure对象和相应数量的axes对象,同时返回该figure对象和axes对象嵌套列表,并默认选择最后一个子图作为"当前"图
- pyplot子模块的绘图流程如图
pyplot子模块创建画布与添加子图的函数
- 绘制图表,常用图表形式包括:
- plot,折线图或点图,实际是调用了line模块下的Line2D图表接口
- scatter,散点图,常用于表述两组数据间的分布关系,也可由特殊形式下的plot实现
- bar/barh,条形图或柱状图,常用于表达一组离散数据的大小关系,比如一年内每个月的销售额数据;默认竖直条形图,可选barh绘制水平条形图
- hist,直方图,形式上与条形图很像,但表达意义却完全不同:直方图用于统计一组连续数据的分区间分布情况,比如有1000个正态分布的随机抽样,那么其直方图应该是大致满足钟型分布;条形图主要是适用于一组离散标签下的数量对比
- pie,饼图,主要用于表达构成或比例关系,一般适用于少量对比
- imshow,显示图像,根据像素点数据完成绘图并显示
pyplot子模块绘制图表内容所常用的函数
NumPy 是 Python 语言的一个第三方库,其支持大量高维度数组与矩阵运算。此外,NumPy 也针对数组运算提供大量的数学函数。机器学习涉及到大量对数组的变换和运算,NumPy 就成了必不可少的工具之一。
NumPy 中定义的最重要的对象是称为 ndarray
的 N 维数组类型。 它描述相同类型的元素集合。 可以使用基于零的索引访问集合中的项目。
ndarray
中的每个元素在内存中使用相同大小的块。 ndarray
中的每个元素是数据类型对象的对象(称为 dtype
)。
从ndarray
对象提取的任何元素(通过切片)由一个数组标量类型的 Python 对象表示。 下图显示了ndarray
,数据类型对象(dtype
)和数组标量类型之间的关系。
基本的ndarray
是使用 NumPy 中的数组函数创建的,如下所示:
numpy.array
它从任何暴露数组接口的对象,或从返回数组的任何方法创建一个ndarray,将数据转化为矩阵
numpy.array(object, dtype = None, copy = True, order = 'K', subok = False, ndmin = 0)
上面的构造器接受以下参数:
序号 | 参数及描述 |
---|---|
1. | object 任何暴露数组接口方法的对象都会返回一个数组或任何(嵌套)序列。 |
2. | dtype 数组的所需数据类型,可选。 |
3. | copy 可选,默认为true ,对象是否被复制。 |
4. | order C (按行)、F (按列)或A (任意,默认)。 |
5. | subok 默认情况下,返回的数组被强制为基类数组。 如果为true ,则返回子类。 |
6. | ndmin 指定返回数组的最小维数。 |
import numpy as np
a = np.array([1, 2, 3])
print(a)
print("*" * 20)
# 多于一个维度
b = np.array([[1, 2], [3, 4]])
print(b)
print("*" * 20)
# 最小维度
c = np.array([1, 2, 3, 4, 5], ndmin=2)
print(c)
print("*" * 20)
# dtype 参数
d = np.array([1, 2, 3], dtype=complex)
print(d)
NumPy 支持比 Python 更多种类的数值类型。 下表显示了 NumPy 中定义的不同标量数据类型。
序号 | 数据类型及描述 |
---|---|
1. | bool_ 存储为一个字节的布尔值(真或假) |
2. | int_ 默认整数,相当于 C 的long ,通常为int32 或int64 |
3. | intc 相当于 C 的int ,通常为int32 或int64 |
4. | intp 用于索引的整数,相当于 C 的size_t ,通常为int32 或int64 |
5. | int8 字节(-128 ~ 127) |
6. | int16 16 位整数(-32768 ~ 32767) |
7. | int32 32 位整数(-2147483648 ~ 2147483647) |
8. | int64 64 位整数(-9223372036854775808 ~ 9223372036854775807) |
9. | uint8 8 位无符号整数(0 ~ 255) |
10. | uint16 16 位无符号整数(0 ~ 65535) |
11. | uint32 32 位无符号整数(0 ~ 4294967295) |
12. | uint64 64 位无符号整数(0 ~ 18446744073709551615) |
13. | float_ float64 的简写 |
14. | float16 半精度浮点:符号位,5 位指数,10 位尾数 |
15. | float32 单精度浮点:符号位,8 位指数,23 位尾数 |
16. | float64 双精度浮点:符号位,11 位指数,52 位尾数 |
17. | complex_ complex128 的简写 |
18. | complex64 复数,由两个 32 位浮点表示(实部和虚部) |
19. | complex128 复数,由两个 64 位浮点表示(实部和虚部) |
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n行m列 |
ndarray.size | 数组元素的总个数,相当于.shape中的 n * m的值 |
ndarray.dtype | ndarray对象的元素类型 |
ndarray.itemsize | ndarray对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray对象的内存信息 |
ndarray.real | ndarray元素的实部 |
ndarray.imag | ndarray元素的虚部 |
ndarray.data | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 |
numpy.ndim
用于返回矩阵的维数,等于秩
import numpy as np
# 这个函数返回ndarray对象,包含给定范围内的等间隔值。
a = np.arange(24)
print(a)
print("-----------")
print(a.ndim) # a 现只有一个维度
print("-----------")
# 现在调整其大小
b = a.reshape(2, 4, 3) # b现在拥有三个维度
print(b)
print("----------")
print(b.ndim)
numpy.shape
表示数组的维度,返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性(秩)。比如,一个二维数组,其维度表示"行数"和"列数"。它也可以用于调整数组大小。
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
# a.shape表示返回一个元组,这里返回的是(2,3)表示2行三列的矩阵
print(a.shape)
print("*"*20)
# 调整矩阵的维度
a.shape = (3, 2)
print(a)
numpy.itemsize
这一数组属性返回数组中每个元素的字节单位长度。
例如,一个元素类型为 float64 的数组 itemsiz 属性值为 8(float64 占用 64 个 bits,每个字节长度为 8,所以 64/8,占用 8 个字节),又如,一个元素类型为 complex32 的数组 item 属性为 4(32/8)。
import numpy as np
# 数组的 dtype 为 int8(一个字节)
x = np.array([1, 2, 3, 4, 5], dtype=np.int8)
print(x.itemsize)
# 数组的 dtype 现在为 float64(八个字节)
y = np.array([1, 2, 3, 4, 5], dtype=np.float64)
print(y.itemsize)
numpy.flags
ndarray
对象拥有以下属性。这个函数返回了它们的当前值。
序号 属性及描述 1. C_CONTIGUOUS (C)
数组位于单一的、C 风格的连续区段内2. F_CONTIGUOUS (F)
数组位于单一的、Fortran 风格的连续区段内3. OWNDATA (O)
数组的内存从其它对象处借用4. WRITEABLE (W)
数据区域可写入。 将它设置为flase
会锁定数据,使其只读5. ALIGNED (A)
数据和任何元素会为硬件适当对齐6. UPDATEIFCOPY (U)
这个数组是另一数组的副本。当这个数组释放时,源数组会由这个数组中的元素更新
import numpy as np
x = np.array([1,2,3,4,5])
print(x.flags)
numpy.ravel
将多维数组降为一维. ravel()展平的顺序可以通过参数order来决定,‘C’行,‘F’列,'A’原顺序,’K’表示在内存中出现的顺序
import numpy as np
x = np.arange(9).reshape(3, 3)
print("创建的二维数组为:\n", x)
# ravel()展平的顺序可以通过参数order来决定,‘C’行,‘F’列,'A'原顺序,’K’表示在内存中出现的顺序
print("按行展平后的数组为:", x.ravel())
print("按列展平后的数组为:", x.ravel(order='F'))
numpy.split
把一个数组从左到右按顺序切分
参数:
- ary:要切分的数组
- indices_or_sections:如果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭)
说白了就是往给的参数数组
- axis:沿着哪个维度进行切向,默认为0,横向切分。为1时,纵向切分
比如说有一个数组为a = [12, 323, 23, 2, 434, 2, 32, 4, 3, 4, 343, 45],np.split(a, [1,3, 5,6])表示在该数组索引为1,3,5,6的地方进行分割,如图:
import numpy as np
a = np.array([12, 323, 23, 2, 434, 2, 32, 4, 3, 4, 343, 45]) # 创建一个数组
b = np.split(a, 3) # 平均分割3个数组
c = np.split(a, [1, 3, 5, 6]) # 表示在该数组索引为1,3,5,6的地方进行分割
print(a)
print(b)
print(c)
numpy.empty
数组元素为随机值,因为它们未初始化。
numpy.empty(shape, dtype = float, order = 'C')
构造器接受下列参数:
序号 | 参数及描述 |
---|---|
1. | Shape 空数组的形状,整数或整数元组 |
2. | Dtype 所需的输出数组类型,可选 |
3. | Order 'C' 为按行的 C 风格数组,'F' 为按列的 Fortran 风格数组 |
import numpy as np
x = np.empty([3, 2], dtype=int)
print(x)
numpy.zeros
返回特定大小,以 0 填充的新数组。
numpy.zeros(shape, dtype = float, order = 'C')
构造器接受下列参数:
序号 | 参数及描述 |
---|---|
1. | Shape 空数组的形状,整数或整数元组 |
2. | Dtype 所需的输出数组类型,可选 |
3. | Order 'C' 为按行的 C 风格数组,'F' 为按列的 Fortran 风格数组 |
# 含有 5 个 0 的数组,默认类型为 float
import numpy as np
x = np.zeros(5)
print(x)
numpy.ones
返回特定大小,以 1 填充的新数组。
numpy.ones(shape, dtype = None, order = 'C')
构造器接受下列参数:
序号 | 参数及描述 |
---|---|
1. | Shape 空数组的形状,整数或整数元组 |
2. | Dtype 所需的输出数组类型,可选 |
3. | Order 'C' 为按行的 C 风格数组,'F' 为按列的 Fortran 风格数组 |
import numpy as np
x = np.ones([2, 2], dtype=int)
print(x)
numpy.arange
这个函数返回
ndarray
对象,包含给定范围内的等间隔值。numpy.arange(start, stop, step, dtype)
序号 参数及描述 1. start
范围的起始值,默认为0
2. stop
范围的终止值(不包含)3. step
两个值的间隔,默认为1
4. dtype
返回ndarray
的数据类型,如果没有提供,则会使用输入数据的类型。
import numpy as np
# 设置了 dtype
x = np.arange(5, dtype=float)
print(x)
print("*" * 20)
y = np.arange(1, 11, 2, dtype=int)
print(y)
numpy.linspace
此函数类似于
arange()
函数。 在此函数中,指定了范围之间的均匀间隔数量,而不是步长。 此函数的用法如下。numpy.linspace(start, stop, num, endpoint, retstep, dtype)
构造器接受下列参数:
序号 参数及描述 1. start
序列的起始值2. stop
序列的终止值,如果endpoint
为true
,该值包含于序列中3. num
要生成的等间隔样例数量,默认为50
4. endpoint
序列中是否包含stop
值,默认为ture
5. retstep
如果为true
,返回样例,以及连续数字之间的步长6. dtype
输出ndarray
的数据类型
import numpy as np
# 将 endpoint 设为 false
x = np.linspace(10, 20, 5, endpoint=False)
print(x)
numpy.logspace
此函数返回一个
ndarray
对象,其中包含在对数刻度上均匀分布的数字。 刻度的开始和结束端点是某个底数的幂,通常为 10。numpy.logscale(start, stop, num, endpoint, base, dtype)
logspace
函数的输出由以下参数决定:
序号 参数及描述 1. start
起始值是base **start
2. stop
终止值是base ** stop
3. num
范围内的数值数量,默认为50
4. endpoint
如果为true
,终止值包含在输出数组当中5. base
对数空间的底数,默认为10
6. dtype
输出数组的数据类型,如果没有提供,则取决于其它参数
import numpy as np
# 默认底数是 10
# 这句话的意思是在10的1次方到10的二次方之间,等比例出现的十个数字
a = np.logspace(1.0, 2.0, num=10)
print(a)
ndarray
对象的内容可以通过索引或切片来访问和修改,就像 Python 的内置容器对象一样。如前所述,
ndarray
对象中的元素遵循基于零的索引。 有三种可用的索引方法类型: 字段访问,基本切片和高级索引。基本切片是 Python 中基本切片概念到 n 维的扩展。 通过将
start
,stop
和step
参数提供给内置的slice
函数来构造一个 Pythonslice
对象。 此slice
对象被传递给数组来提取数组的一部分。
import numpy as np
a = np.arange(10)
print(a)
print("*"*20)
s = slice(2, 7, 2)
print(a[s])
print("*"*20)
d = a[2:7:2]
print(d)
a[…, 1] 省略号表示根据对应的ndim展开相应数量少一个的冒号,这里是二维,等价于a[:,1],
说白了...表示所有的意思
import numpy as np
a = np.array([[1, 2, 4], [4, 5, 6], [7, 8, 9]]) # 创建多维数组
print("数组a的内容为:\n", a) # 打印数组a的内容
print("指定索引结果:\n", a[1]) # 打印行号为1的内容
print("指定索引范围的结果:\n", a[1:]) # 打印行号为1以及后面的内容
print("指定行列结果:\n", a[1, 1:4]) # 打印行号为1,列号为1到4(不包括4)的内容
print("获取第二列元素:\n", a[..., 1]) # 省略号表示根据对应的ndim展开相应数量少一个的冒号,这里是二维,等价于a[:,1]
print("获取第二列元素:\n", a[:, 1]) # a[:,1]表示行号取全部元素,列号取1
print("获取第二行元素:\n", a[1, ...])
print("获取第二行元素:\n", a[1, :])
print("获取第二列及以后的元素:\n", a[..., 1:])
print("获取第二列及以后的元素:\n", a[:, 1:])
如果一个
ndarray
是非元组序列,数据类型为整数或布尔值的ndarray
,或者至少一个元素为序列对象的元组,我们就能够用它来索引ndarray
。高级索引始终返回数据的副本。 与此相反,切片只提供了一个视图。有两种类型的高级索引:整数和布尔值。
这种机制有助于基于 N 维索引来获取数组中任意元素。 每个整数数组表示该维度的下标值。 当索引的元素个数就是目标ndarray
的维度时,会变得相当直接。
以下示例获取了ndarray
对象中每一行指定列的一个元素。 因此,行索引包含所有行号,列索引指定要选择的元素。
import numpy as np
x = np.array([[1, 2], [3, 4], [5, 6]])
print(x)
# 表示取第0行0列,1行1列,2行0列的数
y = x[[0, 1, 2], [0, 1, 0]]
print(y)
#该结果包括数组中(0,0),(1,1)和(2,0)位置处的元素。
下面的示例获取了 4X3 数组中的每个角处的元素。 行索引是[0,0]
和[3,3]
,而列索引是[0,2]
和[0,2]
。
import numpy as np
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print('我们的数组是:')
print(x)
print('\n')
rows = np.array([[0, 0], [3, 3]])
cols = np.array([[0, 2], [0, 2]])
y = x[rows, cols]
print('这个数组的每个角处的元素是:')
print(y)
术语广播是指 NumPy 在算术运算期间处理不同形状的数组的能力。 对数组的算术运算通常在相应的元素上进行。 如果两个阵列具有完全相同的形状,则这些操作被无缝执行。
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
# 就是顺序相乘
c = a * b
print(c)
NumPy 包包含一个迭代器对象
numpy.nditer
。 它是一个有效的多维迭代器对象,可以用于在数组上进行迭代。 数组的每个元素可使用 Python 的标准Iterator
接口来访问。
让我们使用arange()
函数创建一个 3X4 数组,并使用nditer
对它进行迭代。
迭代的顺序匹配数组的内容布局,而不考虑特定的排序。 这可以通过迭代上述数组的
转置
来看到。也就是说遍历的是原来的数组
import numpy as np
# 创建一个从0到60(不包含60)步长为5的一维数组
a = np.arange(0, 60, 5)
# 将数组的形状从一维数组变成3行4列的数组
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
print('修改后的数组是:')
# numpy.nditer遍历一个或者多个数组
for x in np.nditer(a):
# end – 用来设定以什么结尾。默认值是换行符 n,我们可以换成其他字符串
print(x, end=" ")
返回一个二维数组,其对角线元素为1,其余位置元素为0,类似于对角矩阵
变量名 | 数据类型 | 功能 |
---|---|---|
N | 整数 | 返回数组的行数 |
k | 整数,可选参数 | 对角线的索引:0(默认值)代表主对角线,正整数代表上三角内的对角线,负整数代表下三角内的对角线。 |
dtype | 数值类型,可选参数 | 返回数组的数值类型 |
order | {‘C’, 'F},可选参数 | 是否在内存中以C或fortran(行或列)顺序存储多维数据,版本1.14.0中的新特性 |
import numpy as np
print(np.eye(2, dtype=int))
print(end="\n")
print(np.eye(3, k=1))
print(end="\n")
print(np.eye(3, k=-1))
以一维数组的形式返回方阵的对角线(或非对角线)元素,或将一维数组转换成方阵(非对角线元素为0).
import numpy as np
a = np.arange(1, 4)
print(a)
print(end="\n")
print(np.diag(a))
print(end="\n")
b = np.arange(1, 10).reshape(3, 3)
print(b)
print(end="\n")
print(np.diag(b))
Numpy中的random模块用于生成随机数
生成一个[0,1)之间的随机浮点数或N维浮点数组。dn表示维度
import numpy as np
a = np.random.rand(4, 2)
print("数组的内容为:\n", a)
print("数组的形状为:", a.shape)
print("数组的维数为:", a.ndim)
- 返回随机整数,范围区间为[low,high),包含low,不包含high
- 参数:low为最小值,high为最大值,size为数组维度大小,dtype为数据类型,默认的数据类型是np.int
- high没有填写时,默认生成随机数的范围是[0,low)
import numpy as np
a = np.random.randint(-5, 5, size=(2, 2))
print("数组的内容为:\n", a)
print("数组的形状为:", a.shape)
print("数组的维数为:", a.ndim)
random()函数用于生成一个0~1的浮点型随机数的数组,如果填写单个的数字时将随机的生成对应数量的元素数组,也可以通过元组的形式为数组设置形状。
import numpy as np
a = np.random.random(5)
b = np.random.random()
c = np.random.random((2, 3))
print("数组的内容为:\n", a)
print("数组的内容为:\n", b)
print("数组的内容为:\n", c)