链接:https://pan.baidu.com/s/1yGnpfq4ZHeKpt4V0J_PTSg
提取码:hmzs
print(type(int('8'))) # 将字符串8转化为整型
print(type(str(123))) # 将整型123转为字符串类型
print(type(bool(123))) # 将整型123转为布尔类型
print(bool(0)) # 将整型0转为布尔类型 非0为True,0为False
a为变量名称,=为变量赋值,123为变量得到的值
# 网络带宽计算
print(100/8)
bandwidth = 100
ratio = 8
print(bandwidth/ratio)
Python编码风格指南
特点:成员都是有序排列,并且可以通过下标偏移量访问到它的一个或几个成员
字符串、列表、元组三种类型都属于序列
字符串:“abcd”
列表:[0, “abcd”]
元组:(“abc”, “def”)
思考:元组和列表的区别?
答:相同点:都是序列,可以通过索引访问,可以存储任何数据类型
不同点:写法不同,列表是可变的,元组是不可变的
无关知识点 :在Python单引号跟双引号字符串没有区别,只是当你的字符串内容中有单引号出现时可以用双引号将整个字符串圈起来
chinese_zodiac = '鼠牛虎兔龙蛇马羊猴鸡狗猪'
print(chinese_zodiac[0:4]) # 下标从0开始
print(chinese_zodiac[-1]) # 取最后一个元素
# 记录生肖,根据年份来判断生肖
chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊'
year = 2022
print(year%12)
print(chinese_zodiac[year%12])
chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊'
print('狗' in chinese_zodiac)
print('狗' not in chinese_zodiac)
print(chinese_zodiac + 'abcd')
print(chinese_zodiac * 3)
a = (4)
b = (5)
print(a > b) # 元组当中只有一个数时是按这一个元素的大小去比较
print(a < b)
c = (1,50)
d = (1,200)
print(c > d) # 当元组中有两个元素的时候是将这两个元素结合之后进行比较,此处是150 > 1200
print(c < d)
# 输入一个日期判断其是哪个星座
zodiac_name = (u'魔羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', u'巨蟹座',
u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') # 在这u是指unicode编码,防止乱码
zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), (7, 23),
(8, 23), (9, 23), (10, 23), (11, 23), (12, 23))
(month, day) = (2, 15)
zodiac_day = filter(lambda x: x <= (month, day), zodiac_days)
# print(zodiac_day)
zodiac_len = len(list(zodiac_day))
print(zodiac_name[zodiac_len])
常用操作:
a_list = ['abc', 'xyz']
a_list.append('X')
print(a_list)
a_list.remove('xyz')
print(a_list)
if语句:
格式:
if 表达式:
代码块
if 表达式:
代码块
elif 表达式:
代码块
else:
代码块
for语句:
for 迭代变量 in 可迭代对象:
代码块
# 例子
chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊'
for cz in chinese_zodiac:
print(cz)
for i in range(3): # 输出0-2
print(i)
for i in range(1, 3): # 输出1-2
print(i)
for year in range(2000, 2023):
print('%s 年的生肖是 %s' %(year, chinese_zodiac[year % 12]))
while语句:
while 条件表达式:
代码块
for循环+if判断:
# 输入一个日期判断其是哪个星座
zodiac_name = (u'魔羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', u'巨蟹座',
u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') # 在这u是指unicode编码,防止乱码
zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), (7, 23),
(8, 23), (9, 23), (10, 23), (11, 23), (12, 23))
# 用户输入月份和日期
int_month = int(input('请输入月份:'))
int_day = int(input('请输入日期:'))
for zd_num in range(len(zodiac_days)):
if zodiac_days[zd_num] >= (int_month, int_day):
print(zodiac_name[zd_num])
break
elif int_month == 12 and int_day > 23:
print(zodiac_name[0])
break
while循环+if判断:
# 输入一个日期判断其是哪个星座
zodiac_name = (u'魔羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', u'巨蟹座',
u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') # 在这u是指unicode编码,防止乱码
zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), (7, 23),
(8, 23), (9, 23), (10, 23), (11, 23), (12, 23))
# 用户输入月份和日期
int_month = int(input('请输入月份:'))
int_day = int(input('请输入日期:'))
n = 0
while zodiac_days[n] < (int_month, int_day):
if int_month == 12 and int_day > 23:
break
n += 1
print(zodiac_name[n])
字典:
特性:包含哈希值和指向的对象
格式:{"哈希值":"对象"}
简单使用:
dict1 = {}
print(type(dict1))
dict2 = {'x':1, 'y':2}
dict2['z'] = 3
print(dict2)
列表推导式与字典推导式:
# 1. 列表一般写法
even_list = []
for i in range(1, 11): # 记录1-10中所有偶数的平方
if (i % 2) == 0:
even_list.append(i * i)
print(even_list)
# 1. 列表的列表推导式写法
even_list2 = [i * i for i in range(1, 11) if (i % 2) == 0]
print(even_list2)
zodiac_name = (u'魔羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', u'巨蟹座',
u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座')
# 2. 字典的一般写法
z_dict = {}
for i in zodiac_name:
z_dict[i] = 0
print(z_dict)
# 2. 字典的字典推导式写法
z_dict2 = {k: 0 for k in zodiac_name}
print(z_dict2)
读取一行:readline()
读取多行:readlines()
得到一个列表,列表中每一个元素都是一行的内容
读取整个内容:read()
直接得到整个文章的内容,用字符串的形式去存储
读取固定数字符:read(x)
x代表读取的字符数量
移动文件读取指针:
seek(x)
代表移动到文章第几个字符处,从0开始seek(a, b)
第一个参数代表偏移位置 第二个参数0表示从文件开头偏移1表示从当前位置偏移2表示从文件结尾例子:
# # 将小说的主要人物记录在文件中
# # file1 = open('name.txt') # 默认以只读的方式打开文件
# file1 = open('name.txt', 'w') # 以写入的方式打开文件
# file1.write('诸葛亮')
# file1.close()
#
# file2 = open('name.txt')
# print(file2.read())
# file2.close()
#
# file3 = open('name.txt', 'a') # 如果是以写入的方式打开文件在新写内容时会覆盖,这里用增加的方式进行写入
# file3.write('刘备')
# file4 = open('name.txt')
# print(file4.readline()) # 读一行
#
# file5 = open('name.txt')
# # print(file5.readlines()) # 读取多行
# for line in file5.readlines():
# print(line)
file6 = open('name.txt')
print('当前文件指针的位置 %s' % (file6.tell())) # 文件指针在哪个位置
# print(file6.read()) # 读取所有文件
print('当前读取到了一个字符,字符的内容是 %s' % file6.read(1)) # 默认是读取所有文件,此处表读取一个字符
print('当前文件指针的位置 %s' % (file6.tell()))
file6.seek(2, 0) # 第一个参数代表偏移位置 第二个参数 0表示从文件开头偏移 1表示从当前位置偏移 2从文件结尾
print('我们进行了seek操作')
print('文件指针回到了位置 %s' % (file6.tell()))
print('当前读取到了一个字符,字符的内容是 %s' % file6.read(1)) # 默认是读取所有文件,此处表读取一个字符
print('当前文件指针的位置 %s' % (file6.tell()))
file6.close()
异常:
产生:出现错误时采用正常控制流以外的动作
异常处理的一般流程:
异常处理代码格式:
try:
<监控异常>
except Exception[,reason]:
<异常处理代码>
finally:
<无论异常是否发生都执行> # 常用于文件关闭
简单试验:
# try:
# year = int(input('input year:'))
# except ValueError:
# print('年份要输入数字!')
# except (ValueError, AttributeError, KeyError) 捕获多个异常时使用元组将其整合成一个对象
# try:
# print(1 / 0)
# except Exception as e: # Exception代表所有错误信息
# print('0不能做除数 %s' % e)
# 自己定义错误信息
try:
raise NameError('helloError')
except NameError:
print('my Custom error')
定义:对程序逻辑进行结构化的一种编程方法
定义格式:
def 函数名称():
代码
return 需要返回的内容
函数的调用:函数名称()
函数传参时使用指定关键字:
print('abc', end='\n') # end是指定关键字参数,好处是不用按顺序输入参数
def func(a, b, c):
print('a = %s' %a)
print('b = %s' %b)
print('c = %s' %c)
func(1, 2, 3)
func(1, c = 2, b = 3) # 指定关键字,不用按顺序输入参数
# 取得参数的个数
def howlong(first, *other):
print(1 + len(other))
howlong(1, 2, 3)
var1 = 123
def func():
var1 = 456 # 它的影响范围只是在这个函数内,如果要让它的影响范围变大的话,要加上关键字global,即global var1
print(var1) # 输出456
func()
print(var1) # 输出的还是123
list1 = [1, 2, 3]
it = iter(list1)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
list2 = ['a', 'b', 'c']
for i in iter(list2):
print(i)
# 自己手写一个浮点数range
def frange(start, stop, step): # 使用了yield的函数我们称为生成器,也是迭代器的一种
x = start
while x < stop:
yield x
x += step
for i in frange(10, 20, 0.5):
print(i)
def add(x, y):
return x + y
lambda x,y: x + y
filter(func, iterable):将符合指定函数的项给选出来
a = [1, 2, 3, 4, 5, 6, 7]
list(filter(lambda x:x>2, a)) # 将符合指定函数的项给取出来
map():对每个元素依次进行操作变变换
a = [1, 2, 3]
b = [4, 5, 6]
list(map(lambda x:x+1, a)) # 对a列表中的每一项进行加一
list(map(lambda x,y:x+y, a, b))# a列表中的每一项加上b列表中的每一项
reduce():序列的所有项和初始值依次按照函数做运算注意:reduce虽然是内建函数,但是得用from functools import reduce
导入
reduce(lambda x,y: x+y, [2,3,4], 1) # (( 1 + 2 ) + 3 ) + 4
# 初始值可以省略,当省略时,默认为0
zip():可以使两个元组纵向合并。可以实现字典的key、value对调
a = (1, 2, 3)
b = (4, 5, 6)
tuple(zip(a, b))
for i in zip(a, b): # zip是一个可迭代的函数,其有一个iter方法
print(i)
dicta = {'a':'aaa', 'b':'bbb'}
dictb = dict(zip(dicta.values(), dicta.keys()))
dictb
补充:
定义:嵌套的函数,且当外部函数的参数被内部函数给引用的情况下我们称其为闭包。
小示例:
# 使用闭包实现计数器
def counter(FIRST=0):
cnt = [FIRST]
def add_one():
cnt[0] += 1
return cnt[0]
return add_one
num1 = counter(5)
num2 = counter(10)
print(num1())
print(num1())
print(num2())
print(num2())
运行结果:
6
7
11
12
发现:
互不影响,这也是闭包的好处。
# 使用闭包实现线段
def a_line(a, b):
def arg_y(x):
return a * x + b
return arg_y
line1 = a_line(3, 5)
line2 = a_line(10, 5)
print(line1(5))
print(line2(5))
'''
闭包优雅写法
def a_line(a, b):
return lambda x:a*x+b
'''
定义与闭包类似,只不过它传递的参数是一个函数,使用方法经过不断演化后得到了简化。
示例:
import time
# 未用装饰器前
def I_sleep():
time.sleep(3)
start_time = time.time()
I_sleep()
stop_time = time.time()
print("程序运行了%s" %(stop_time-start_time))
# 用装饰器后
def timer(func):
def wrapper():
start_time = time.time()
func()
stop_time = time.time()
print("程序运行了%s" %(stop_time-start_time))
return wrapper
@timer # 语法糖,修饰I_sleep2
def I_sleep2():
time.sleep(3)
I_sleep2() # 实际上是(timer(I_sleep2))()这么运行的
带参数的装饰器:
# 带参数的装饰器
def out(func):
def inner(a,b):
print('start')
func(a,b)
print('stop')
return inner
@out
def add(a,b):
print(a + b)
add(7,3) # 实际上可以理解为运行的时候是这样的(out(add))(7,3),所以实际上是inner(7,3)
针对不同函数装饰器做适应:
# 带参数的装饰器
def new(argv):
def out(func):
def inner(a,b):
print('start %s %s' %(argv, func.__name__)) # __name__取传入函数的名字
func(a,b)
print('stop')
return inner
return out
@new('add_module')
def add(a,b):
print(a + b)
@new('sub_module')
def sub(a,b):
print(a - b)
add(3, 5)
sub(5, 3)
好处:
先来看看一般打开文件的方法
fd = open('name.txt')
try:
for line in fd:
print(line)
finally:
fd.close()
上面这种方法是不优雅的
下面我们使用with
上下文管理器的方法去精简
with open('name.txt') as f:
for line in f:
print(line)
通过这种方法省去了我们写finally,因为在出现异常的时候,它会自动帮我们做关闭的操作。
在代码量变得相当大之后,将需要重复使用的有组织的代码段放在一起组成一个文件,这个文件就是模块。可以附加到现有的程序中。
导入:附加的过程
导入的一般写法:
import 模块名称 as 别名
from 模块名称 import 方法名
# 传统表示玩家信息的方法
user1 = {'name':'tom','hp':100}
user2 = {'name':'jerry','hp':80}
def print_role(rolename):
print('name is %s,hp is %s' %(rolename['name'], rolename['hp']))
print_role(user1)
print_role(user2)
# 使用类的方法
class Player():
def __init__(self, name, hp):
self.name = name
self.hp = hp
def print_role(self): # 定义了一个方法
print('name is %s,hp is %s' %(self.name, self.hp))
user1 = Player('Tom', 100) # 类的实例化
user2 = Player('Jerry', 80)
user1.print_role()
user2.print_role()
# 使用类的方法
class Player():
def __init__(self, name, hp, occu):
self.__name = name # 变量被称作属性
self.hp = hp
self.occu = occu
def print_role(self): # 定义了一个方法(函数被称作方法)
print('name is %s,hp is %s,occupation is %s' %(self.__name, self.hp, self.occu))
def updateName(self, newname):
self.__name = newname
user1 = Player('Tom', 100, 'war') # 类的实例化
user2 = Player('Jerry', 80, 'master')
user1.print_role()
user2.print_role()
user1.updateName('wilson')
user1.print_role()
其中name默认是公有成员,也可以通过实例.name的方式去访问和更改。
如果想使得name不能使用.name 的方式去访问和更改,可以在其类中使用__name
。
class Monster():
# 定义怪物类
pass # 告知系统我们定义了一个Monster,但是现在我们还不想去实现它
class Animals(Monster): # 继承自Monster类
# 普通怪物
pass
class Boss(Monster):
# Boss类怪物
pass
# version 2
class Monster():
# 定义怪物类
def __init__(self, hp = 100):
self.hp = hp
def run(self):
print('移动到某个位置')
def whoami(self):
print('我是怪物父类')
class Animals(Monster): # 继承自Monster类
# 普通怪物
def __init__(self, hp = 10):
super().__init__(hp)
class Boss(Monster):
# Boss类怪物
def __init__(self, hp=800):
super().__init__(hp)
def whoami(self): # 有重名的方法,使用时会覆盖父类的方法
print('我是Boss')
a1 = Monster(200)
a1.run()
print(a1.hp)
a2 = Animals(100)
a2.run()
print(a2.hp)
a3 = Boss(1000)
a3.whoami()
print('a1的类型 %s' %type(a1))
print('a2的类型 %s' %type(a2))
print('a3的类型 %s' %type(a3))
print(isinstance(a2, Monster)) # 判断对象是否是一个已知类型
class Testwith():
def __enter__(self):
print('run')
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
with Testwith():
print('test is running')
运行结果:
run
test is running
exit
class Testwith():
def __enter__(self):
print('run')
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_tb is None: # 没有异常它的值就是None
print('正常结束')
else:
print('has error %s' %exc_tb)
with Testwith():
print('test is running')
raise NameError('testNameError') # 手动抛出异常
定义:同时处理多个请求的方法
线程的简单使用:
import threading
import time
from threading import current_thread
def myThread(arg1, arg2):
# print(current_thread().getName(),'start')
time.sleep(1)
print('%s %s' %(arg1, arg2))
# print(current_thread().getName(),'stop')
for i in range(1, 6, 1):
t1 = threading.Thread(target=myThread,args=(i, i + 1))
t1.start()
让主线程等待其他线程结束之后再结束
import threading
from threading import current_thread
class Mythread(threading.Thread):
def run(self):
print(current_thread().getName(), 'start')
print('run')
print(current_thread().getName(), 'stop')
t1 = Mythread()
t1.start() # 线程使用start启动的时候实际上是调用了run方法
t1.join() # 等待t1线程结束才会向下执行
print(current_thread().getName(), 'end')
生产者和消费者:
from threading import Thread,current_thread
import time
import random
from queue import Queue
queue = Queue(5) # 定义队列的长度
class ProducerThread(Thread):
def run(self):
name = current_thread().getName() # 获取线程的名字
nums = range(100)
global queue
while True:
num = random.choice(nums)
queue.put(num)
print('生产者 %s 生产了数据 %s' %(name, num))
t = random.randint(1, 3)
time.sleep(t)
print('生产者 %s 睡眠了 %s 秒' %(name, t))
class ConsumerThread(Thread):
def run(self):
name = current_thread().getName()
global queue
while True:
num = queue.get()
queue.task_done() # 封装好了关于线程等待和线程同步的代码
print('消费者 %s 消耗了数据 %s' %(name, num))
t = random.randint(1, 5)
time.sleep(t)
print('消费者 %s 睡眠了 %s 秒' %(name, t))
p1 = ProducerThread(name = 'p1')
p1.start()
p2 = ProducerThread(name = 'p2')
p2.start()
p3 = ProducerThread(name = 'p3')
p3.start()
c1 = ConsumerThread(name = 'c1')
c1.start()
c2 = ConsumerThread(name = 'c2')
c2.start()
导入import re
单个字符的匹配:
import re
p = re.compile('a')
print(p.match('a'))
print(p.match('b'))
运行结果:
<re.Match object; span=(0, 1), match='a'> # 匹配到的位置
None # 匹配失败
正则表达式元字符:
.
匹配任意一个字符除换行符\d
匹配任意一个数字匹配日期:
p = re.compile(r'(\d+)-(\d+)-(\d+)') # r是告知python字符串中的特殊符号不要进行转义
print(p.match('2022-05-05').group()) # 获取匹配到的内容
print(p.match('2022-05-07').group(1)) # 获取年
print(p.match('2022-05-07').groups()) # 获取年月日,用元组去存
year,month,day = ('2022', '05', '07')
正则表达式match与search的区别
正则表达式库替换函数sub
sub(str1, str2, str3):
使用:
# 删去电话号码结尾不合法部分
phone = '123-456-789 # 这是一个电话号码'
p = re.sub(r'#.*$', '', phone)
print(p)
# 删去-
p2 = re.sub(r'\D','',p)
print(p2)
运行结果:
123-456-789
123456789
补充:
时间库:
引入import time
函数:
使用:
import time
print(time.time()) # 查19700101到现在过了多少秒
print(time.localtime())
print(time.strftime('%Y%m%d'))
以当前时间为准,计算指定偏移后的时间
import datetime
print(datetime.datetime.now())
newtime = datetime.timedelta(minutes = 10) # 计算十分钟偏移量
print(datetime.datetime.now() + newtime) # 显示十分钟后的时间
one_day = datetime.datetime(2008,5,27)
new_date = datetime.timedelta(days = 10)
print(one_day + new_date)
math
random
import random
print(random.randint(1, 5))
print(random.choice([1, 2, 'a', 'b']))
os.path
引入:import os
或者from os import path
使用:
from os import path
print(path.abspath('..')) # 根据相对路径.获得绝对路径v
print(path.exists('./01 hello_world.py')) # 判断文件是否存在
print(path.isfile('./01 hello_world.py')) # 判断是否是文件
print(path.isdir('./01 hello_world.py')) # 判断是否是目录
print(path.isdir('.'))
print(path.join('/tmp/','01 hello_world.py')) # 路径拼接
pathlib
引入:from pathlib import Path
使用:
from pathlib import Path
p = Path('.')
print(p.resolve()) # 根据相对路径获得绝对路径,跟我们的path.abspath()一样
print(p.is_dir()) # 判断当前位置是否是目录
q = Path('./a/b/c')
Path.mkdir(q, parents=True) # parents=True是当父级目录不存在时会创建父级目录
特点:两者大多数功能类似,但pathlib好的是可以创建目录。
用途:主要用于高性能科学计算和数据分析,是常用的高级数据分析库的基础包。
简单使用:
import numpy as np
arr1 = np.array([2, 3, 4])
print(arr1)
print(arr1.dtype)
arr2 = np.array([2.1, 3.1, 4.1])
print(arr2)
print(arr2.dtype)
print(arr1 + arr2)
# Numpy数组和标量的计算
print(arr2 * 10)
data = [[1,2,3], [4,5,6]]
arr3 = np.array(data) # 将列表转为二维矩阵
print(arr3)
print(arr3.dtype)
print(type(arr3))
print(np.zeros(10)) # 定义了一个一维的长度为10的数组,这个数组的所有值都是0
print(np.zeros((3, 5))) # 定义一个3x5的矩阵,这个矩阵的所有值为0
print(np.ones((4, 6))) # 定义一个4x6的矩阵,初始值都为1
print(np.empty((2,3,2))) # 定义了一个三维矩阵,初始值为随机值
# Numpy数组的索引和切片
arr4 = np.arange(10)
print(arr4[5])
print(arr4[5:8])
arr4[5:8] = 0
print(arr4)
arr_slice = arr4[5:8]
arr_slice[:] = 1 # 由于python这里是引用,故而这么做会影响到arr4的内容
print(arr4)
arr_slice = arr4[5:8].copy()
arr_slice[:] = 0 # 这样子做操作不会影响arr4,因为它是arr4的一个副本
print(arr4)
print(arr_slice)
arr5 = np.array(['a', 'b', 'c', 'd'])
print(arr5[1]) # 下标从0开始计算
好处(相比于Numpy):
特点:
简单使用:
import pandas as pd
obj = pd.Series([4, 5, 6, -7])
print(obj)
print(obj.index) # 打印索引
print(obj.values) # 打印值
obj2 = pd.Series([4, 5, 6, 3], index = {'a', 'b', 'd', 'c'})
print(obj2)
obj2['c'] = 6
print(obj2)
print('c' in obj2) # 判断是否存在键'c'
print('f' in obj2)
# 将字典转化到我们的series中
sdata = {'beijing' : 35000, 'shanghai' : 70000, 'guangzhou' : 16000, 'shenzhen' : 5000}
obj3 = pd.Series(sdata)
print(obj3)
obj3.index = ['bj', 'sh', 'gz', 'sz'] # 修改索引为它们的缩写
print(obj3)
# 将字典转化到我们的dataframe中
data = {'city' : ['shanghai', 'guangzhou', 'beijing', 'shenzhen'],
'year' : [2016, 2017, 2018, 2019],
'pop' : [1.5, 1.8, 1.3, 2.0]}
frame = pd.DataFrame(data)
print(frame)
frame2 = pd.DataFrame(data, columns = ['year', 'city', 'pop']) # 调换列的顺序
print(frame2)
# 将二维表格转换为一维的数据
print(frame2['city'])
print(frame2.year)
# 为pandas增加一个新的列
frame2['cap'] = frame2.city == 'beijing'
print(frame2)
# 求转置
pop = { 'beijing' : {2008:1.5, 2009:2.0},
'shanghai' : {2008:2.0, 2009:3.6}
}
frame3 = pd.DataFrame(pop)
print(frame3)
# 行和列的转换
print(frame3.T)
obj4 = pd.Series([4.5, 7.2, -5.3, 3.6], index = ['b', 'd', 'c', 'a'])
obj5 = obj4.reindex(['a', 'b', 'c', 'd', 'e']) # 按索引顺序排序,不存在的索引将出现空值
print(obj5)
obj6 = obj4.reindex(['a', 'b', 'c', 'd', 'e'], fill_value = 0) # 给空值填充0
print(obj6)
obj7 = pd.Series(['blue', 'yellow', 'pink'], index = [0, 2, 4])
print(obj7.reindex(range(6)))
print(obj7.reindex(range(6), method = 'ffill')) # 空值填充为其前一个数值
from numpy import nan as NA
# 删除缺失值的一行数据
data = pd.Series([1, NA, 2])
print(data.dropna())
# 在DataFrame删除缺失值的情况
# 1. 某一列的某一行有缺失
data = pd.DataFrame([[1., 6.5, 3], [1., NA, NA], [NA, NA, NA]])
data[4] = NA
print(data)
print(data.dropna()) # 发现只要出现了na的一行就会被全部删掉
print(data.dropna(how = 'all')) # 只删掉全部出现na的一行
# 2. 某一列的某一列有缺失
print(data.dropna(axis = 1, how = 'all')) # 删掉全部出现na的一列
data.fillna(0) # 这种方法是对data副本进行填充0,并返回,并不会直接修改data
data.fillna(0, inplace = True) # 使用了inplace参数则代表是对data进行填充修改
print(data)
# 层次化索引
import numpy as np
data3 = pd.Series(np.random.randn(10),
index = [['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 2, 3, 1, 2, 2, 3]])
# 层次化索引的用途
print(data3)
print(data3.unstack()) # 将一维数据转化为二维数据
print(data3.unstack().stack()) # 再转换回来
用途:绘图
简单使用:
import matplotlib.pyplot as plt
# 绘制简单的曲线
plt.plot([1, 3, 5], [4, 8, 10])
plt.show()
import numpy as np
x = np.linspace(-np.pi, np.pi, 100) # x轴的定义域为-3.14·3.14,中间间隔100个元素
print(x)
plt.plot(x, np.sin(x))
# 显示所画的图
plt.show()
x = np.linspace(-np.pi * 2, np.pi * 2, 100)
plt.figure(1, dpi = 50) # 创建图表,dpi代表精度,精度越高,画的图就越大就越清晰
for i in range(1, 5): # 画四条线
plt.plot(x, np.sin(x / i))
plt.show()
plt.figure(1, dpi = 50) # 创建图表1,dpi代表图片精细度,dpi越大文件越大,杂志要300以上
data = [1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 4]
plt.hist(data) # 只要传入数据,直方图就会统计数据出现的次数
plt.show()
x = np.arange(1, 10)
y = x
fig = plt.figure()
plt.scatter(x, y, c = 'r', marker = 'o') # c = 'r' 表示散点的颜色为红色,marker表示指定三点多边形为圆形
plt.show()
import pandas as pd
iris = pd.read_csv('./iris_training.csv')
print(iris.head())
# 绘制散点图
iris.plot(kind = 'scatter', x = '120', y = '4')
# 没啥用,只是让pandas的plot方法显示
plt.show()
# 使用seaborn来绘制图
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
iris = pd.read_csv('./iris_training.csv')
# 设置样式
sns.set(style = 'white', color_codes = True)
# 设置绘制格式为散点图
# sns.jointplot(x = '120', y = '4', data = iris, size = 5)
# distplot绘制曲线
# sns.distplot(iris['120'])
sns.FacetGrid(iris, hue = 'virginica', size = 5).map(plt.scatter, '120', '4').add_legend() # 按virginica属性分类,给点分配不同颜色
sns.FacetGrid(iris, hue = 'virginica', size = 5).map(plt.scatter, 'setosa', 'versicolor').add_legend()
网络库:
urlib跟requests库都是用于收集数据的库,BeautifulSoup是用于数据处理的库
urlib库:
使用:from urllib import request
例子:
from urllib import request
url = 'http://www.baidu.com'
response = request.urlopen(url, timeout = 1)
print(response.read().decode('utf-8')) # read直接读是按照单个字节解释出来的,而中文往往要占多个字节,所以要用decode做编码解析
专门用于测试get和post请求的网页:http://www.httpbin.org/
发送get请求:
from urllib import request
response = request.urlopen('http://httpbin.org/get', timeout=1)
print(response.read())
# 超时异常捕获处理
import urllib
import socket
try:
response3 = request.urlopen('http://httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
if isinstance(e.reason, socket.timeout):
print('TIME OUT')
发送post请求:
from urllib import parse # 处理post数据
from urllib import request
data = bytes(parse.urlencode({'word':'hello'}), encoding='utf8')
# print(data)
response2 = request.urlopen('http://httpbin.org/post', data=data)
print(response2.read().decode('utf-8'))
HTTP头部信息的模拟:
from urllib import parse # 处理post数据
from urllib import request
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-627a1828-401ed66a579dbc0173b7ee85"
}
dict = {
'name' : 'value'
}
data = bytes(parse.urlencode(dict), encoding = 'utf8')
req = request.Request(url = 'http://httpbin.org/post', data = data, headers = headers, method = 'POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))
使用:import requests
get请求:
import requests
url = 'http://httpbin.org/get'
data = {'key': 'value'}
response = requests.get(url, data)
print(response.text)
post请求:
import requests
url = 'http://httpbin.org/post'
data = {'key' : 'value'}
response = requests.post(url, data)
print(response.text) # 返回类型转为为json格式 response.json()
爬虫小栗子:
import requests import re content = requests.get('http://www.mnw.cn/news/china/') content.encoding = 'utf8' # print(content.text) pattern = re.compile(r'
, re.S) results = re.findall(pattern, content.text) # print(results) for result in results: print(re.sub('\s', '', result)) # 去除空白符
re.S的作用:
不使用re.S时,则只在每一行内进行匹配,如果存在一行没有,就换下一行重新开始,使用re.S参数以后,正则表达式会将这个字符串看做整体,在整体中进行匹配 。
作用:处理请求得到的html文本,一般情况下比使用正则更容易处理得到想要内容
简单使用:
html_doc = """
网页标题
这是一个段落
这是第二个段落
百度一下
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.prettify()) # 格式化显示
# 找到title标签
print(soup.title)
# 找到title标签里面的内容
print(soup.title.string)
# 找到第一个p标签
print(soup.p)
# 找到第一个p标签里面的内容
print(soup.p.string)
# 找到第一个p标签里面class的名字
print(soup.p['class'])
# 找到所有p标签
print(soup.find_all('p'))
# 找到id为first的标签
print(soup.find(id='first'))
# 找到所有a标签的链接
for link in soup.find_all('a'):
print(link.get('href'))
爬取百度新闻:
from bs4 import BeautifulSoup # 编码解码库 import requests # 请求访问库 # 用 dict 定义http头,伪装浏览器访问,避免被拒之门外 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" } #目标网址为 百度新闻 url = "http://news.baidu.com" # 创建函数,传入 URL 获取新闻标题 和对应链接 def craw2(url): response = requests.get(url, headers=headers) # 获取 指定 URL 内容, 头部用 headers ,把这个动作 赋予给 response soup = BeautifulSoup(response.text, "lxml") # 用 BeautifulSoup 把 response 正文内容,用lxml 格式 整理,并赋值给Soup # print(soup) #尝试打印, 能否获取内容 # 把 soup 里面 ,class= mod-tab-pane active 的
标签,全部找出来,并 逐一赋值 给 title_href for title_href in soup.find_all("div", class_="mod-tab-pane active"): for title in title_href.find_all("a"): # 然后把 title_href里的 标签 全部找出来,并逐一赋值给 title title_url=title.get("href") #在title 中,找出href 的值,并赋予给 title——url print(title.text,title_url) #输出 标题和对应链接 craw2(url)
爬取图片网站的图片:
import os # 引入目录操作相关库
import shutil
# 用 dict 定义http头,伪装浏览器访问,避免被拒之门外
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
}
url = "http://www.netbian.com/"
def download_jpg(image_url, image_localpath):
response = requests.get(image_url, stream = True)
if response.status_code == 200: # 图片存在
with open(image_localpath, 'wb') as f: # 打开本地路径
response.raw.deconde_content = True
shutil.copyfileobj(response.raw, f)
# 获取图片
def craw3(url):
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
# print(soup.prettify())
for div in soup.find_all('div', class_="list"):
for img in div.find_all('img'):
imgurl = img.get('src')
dir = os.path.abspath('./爬取的图片/')
filename = os.path.basename(imgurl) # 自动帮我们把https://th.wallhaven.cc/small/k7/k7v9yq.jpg前面的目录路径给去掉剩余k7v9yq.jpg
imgpath = os.path.join(dir, filename)
print('开始下载 %s' % imgurl)
download_jpg(imgurl, imgpath)
craw3(url)