Python元组、集合、字典、初识爬虫
day10
01-元组
1.元组是不可变数据类型
思考:有列表了为什么还要创建一个元组?
程序需要考虑性能,元组要比列表更加的轻量,变相的说,元组的性能优于列表。python在后台有一个垃圾回收机制(内存回收),对静态数据(不可变)做一些资源缓存,垃圾回收机制的存在,使得一些不被使用的变量释放出它所占用的内存,返还给操作系统,以便其他变量或者其他应用使用。对于静态数据,例如元组
,如果它不被使用并且所占内存空间很小时,python不会将其回收,会暂时缓存这部分内存,这样,下次再创建同样大小的元组时,不需要再向系统申请,可以直接拿过来使用,这样就大大加快了程序的速度
2.元组和列表的性能比较
# timeit --> 也能够测试程序的执行时间
import timeit
t1 = timeit.Timer('x = [1, 2, 3, 4, 5]')
# timeit()方法有个默认值number,number的默认值位1000000,也就是说,
# 调用timeit方法变相的相当于将Timer类接收到的一小段代码执行1000000次,得到的最终的时间累计和
print(t1.timeit())
# 返回:0.0469096
t2 = timeit.Timer('y = (1, 2, 3, 4, 5)')
print(t2.timeit())
# 返回:0.013794600000000004
02-元组基础知识点
1.性质:
a.元组是不可变的容器型数据类型(没有增删改)
b.元组是有序的容器型数据类型(有下标)
c.元组中的元素可以是任意类型的元素
d.元组的类型:tuple;容器符号:();元组元素之间使用逗号隔开
2.创建元组
创建空元组
t1 = ()
print(t1, type(t1))
# 返回:() <class 'tuple'>
创建单个元素的元组时注意逗号
t2 = (1,)
print(t2, type(t2))
# 返回:(1,) <class 'tuple'>
t3 = (1)
print(t3, type(t3))
# 返回:1 <class 'int'>
3.下标、切片、循环遍历
元组、列表、字符串的下标、切片、循环遍历是一模一样的。
4.拼接、重复
print((1, 2, 3) + (1, ))
print((1,) * 10)
# 返回:(1, 2, 3, 1)、(1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
5.成员运算:in、not in
判断元素是否在容器中存在
print(2 in (1, 2, 3))
print((2,) in (1, 2, 3))
# 返回:True、False
6.元组的打包操作和容器的解包操作
x = 1, 2, 3
print(x)
# 返回:(1, 2, 3)
# python中允许一个变量同时等于多个值,这多个值会被打包成元组。
# 解包操作
i, j, z = x
print(i, j, z)
# 返回:1 2 3
# python中两个变量和三个变量值的交换是应用了python字节码指令中的
# ROT_TWO和ROT_THREE指令,当需要交换值的变量大于三时,才是应用了解包和打包操作
# 更高级的解包操作
x = (1, 2, 3, 4, 5)
# 情况一:解包的变量和容器中元素个数相同
i, j, z, a, b = x
print(i, j, z, a, b)
# 返回:1 2 3 4 5
# 情况二:解包的变量数量小于容器中元素的个数
# *放在变量前,可以使变量变成不定长变量
i, *j = x
print(i, j)
# 返回:1 [2, 3, 4, 5]
i, *j, z = x
print(i, j, z)
# 返回:1 [2, 3, 4] 5
# 情况三:解包的变量数量大于容器中元素个数(几乎遇不到)
# 注意:如果解包操作涉及到不定长变量,不定长变量只能有一个。
7.元组的相关方法
max、min、count、sum、sorted、index等在元组中同样适用
max、min:求最大值、最小值(注意:容器中元素的类型要一致)
sum:求和(要求容器中元素都得是数值)
count:求某个元素出现的次数
sorted:默认将元素从小到大排序(注意:容器中元素的类型要一致)
index:从左向右查找元素,找到此元素就停止查找,没找到报错
8.元组的删除
元组是不可变数据类型,不能进行元素CUD(增删改)操作,但是可以对整个元组进行删除操作
t = (1, 2)
print(t)
del t
print(t)
# 返回:直接将元组t删除 name 't' is not defined
day11
01-集合
1.集合的性质:
a.python中的集合和数学中的集合很相似
b.集合是一个无序的容器型的数据类型(没有下标)
c.集合是一个可变的容器型数据类型(增删)
d.集合的容器符号:{}、数据类型:set
e.集合具有无序性、确定性、互异性、(从数学角度,集合的定义为:由一个或多个元素构成的确定的整体)
2.创建集合
创建一个空集合
s1 = set()
print(s1, type(s1))
# 返回:set() <class 'set'>
s2 = {} # 创建字典的写法
print(s2, type(s2))
# 返回:{} <class 'dict'>,此时返回的是字典数据类型
3.集合的运算
a.交(&)并(|)差(-)对称差(^)的运算
s1 = {1, 2, 3, 4, 5}
s2 = {2, 4, 6, 8, 10}
print(s1 & s2)
# 返回:{2, 4}
print(s1 | s2)
# 返回:{1, 2, 3, 4, 5, 6, 8, 10}
print(s1 - s2)
# 返回:{1, 3, 5}
print(s2 - s1)
# 返回:{8, 10, 6}
print(s1 ^ s2)
# 返回:{1, 3, 5, 6, 8, 10},将两个集合中独有的元素合并到一起
b.成员运算:in、not in
4.子集(<=)、真子集(<)、超集(>)
子集:是原集中任意个数元素排列组合的个体
真子集:是原集除本身之外任意个数元素排列组合的个体
超集:就是原集对真子集
s3 = {1, 2}
s4 = {1, 2, 3}
print(s4 > s3)
# 返回:True
print(s4 > s4)
# 返回:Fasle
print(s3 < s4)
# 返回:True
print(s3 <= s4)
# 返回:True
print(s3 <= s3)
# 返回:True
4.集合的循环遍历
for i in s4:
print(i)
5.集合的互异性
集合中的元素都是独一无二的
问题:给列表去重
list1 = ['a', 'b', 'c', 'd', 'a', 'b', 'd', ]
print(list(set(list1)))
# 返回:['c', 'd', 'a', 'b']
6.集合中的元素只能是不可变数据类型
可变:列表、集合、字典
不可变:整型、浮点型、复数、字符串、布尔值、空值、元组
7.集合的增删
s1 = set()
# add:将元素添加到集合中
# update:将容器中的元素添加到集合中
s1.add('python')
s1.add('Java')
s1.update(['html', 'c', 'c++'])
print(s1)
# 返回:{'html', 'Java', 'c++', 'python', 'c'}
# discard:删除集合中指定元素,元素不存在不报错
# remove:删除集合中的指定元素,元素不存在报错
# pop:删除集合中本次排名第一的元素并能返回删除的是哪个元素(随机删一个)
# clear:清空集合
s1.pop()
print(s1)
# 随机删除一个元素
# 返回:{'Java', 'c++', 'python', 'c'}
8.集合的用处
a.如果不考虑元素的顺序,可以使用集合进行快速去重
b.利用集合的交并差对称差、子集、真子集、超集等运算操作,可以快速的查看数据之间的关系
练习:用三个集合表示三门学科的选课学生姓名(一个学生可以同时选多门课)
A = {'小刚', '小李', '小红', '小明'}
B = {'小明', '小刚', '小王'}
C = {'小赵', '小王', '小张'}
# 1.求选课学生共有多少人
result1 = A | B | C
print(result1, len(result1))
# 返回:{'小明', '小张', '小赵', '小刚', '小红', '小王', '小李'} 7
# 2.求只选了第一个学科的人的数量和对应的名字
print(A - B - C, len(A - B - C))
# 返回:{'小李', '小红'} 2
# 3.求只选了一门学科的学生的数量和对应的名字
# 自己写的
list2 = []
for i in A:
if i not in B and i not in C:
list2.append(i)
for j in B:
if j not in A and j not in C:
list2.append(j)
for z in C:
if z not in A and z not in B:
list2.append(z)
print(list2, len(list2))
# 返回:['小红', '小李', '小刚', '小赵'] 4
# 老师写的
print((A - (B | C)) | B - (A | C) | C - (A | B))
# 4.求只选了两门学科的学生的数量和对应的名字
# 自己写的
list3 = []
for i in A:
if i in B:
if i not in C:
list3.append(i)
for j in B:
if j in C:
if j not in A:
list3.append(j)
for z in A:
if z in C:
if z not in B:
list3.append(z)
print(list3, len(list3))
# 返回:['小明', '小刚', '小王'] 3
# 老师写的
print((A & B - C) | (A & C - B) | (B & C - A))
# 5.求选了三门学生的学生的数量和对应的名字
# 自己写的
list4 = []
for i in A:
if i in B and i in C:
list4.append(i)
print(list4, len(list4))
# 返回:[] 0
# 老师写的
print(A & B & C)
day12
01-字典的相关操作
举例:需要用一个容器保存一个学生的各项信息
stu1 = ['小赖', 20, 70, 80, '地球村']
stu2 = ('小赖', 20, 70, 80, '地球村')
stu3 = {'小赖', 20, 70, 80, '地球村'}
# 用字典表示
stu4 = {'name': '小赖', 'age': 20, 'address': '地球村', 'english': 70, 'math': 80}
1.字典的性质
a.字典是可变的容器型数据类型(增删改)
b.python3.6之前字典是无序的容器型数据类型;python3.6之后规定字典是有序的容器型数据类型(虽然字典有序,但是没有下标)
c.字典中的元素是以键值对(key: value)形式存在的;字典中的键必须是不可变的数据类型,键是解释说明的作用;字典中的值可以是任意数据,值是最终想要的数据
d.字典以{}作为容器符号,元素使用逗号分隔,数据类型dict
2.字典不支持拼接、重复等操作
3.成员运算:字典的成员运算是判断某个键在或者不在字典中
print('name' in stu4)
# 返回:True
print(20 not in stu4)
# 返回:True
4.循环遍历
for i in stu4:
print(i)
# 返回:name、age、address、english、math
# 除非有特殊说明,否则对字典做的操作都是针对于键的操作
02-字典的相关方法
dict1 = {'name': '张三', 'qq': '100001', 'tel': 123}
# 1.keys:获取字典中所有的键,返回一个容器
print(dict1.keys())
# 返回:dict_keys(['name', 'qq', 'tel'])
for i in dict1.keys():
print(i)
# 2.values:获取字典中所有的值,返回一个容器
print(dict1.values())
# 返回:dict_values(['张三', '100001', 123])
# 3.items:获取字典中所有的键值对,返回一个容器
print(dict1.items())
# 返回:dict_items([('name', '张三'), ('qq', '100001'), ('tel', 123)])
for i in dict1.items():
print(i)
for key, value in dict1.items():
print(key, value)
# 4.sum、max、min、sorted、len等方法,都可以作用于字典,但操作对象都是字典中的键(key)
# 5.dict():将指定数据转为字典
# a.数据本身是容器
# b.容器中的元素还必须是一个容器
# c.容器中的容器必须只有两个元素
# d.这两个元素的第一个元素必须是不可变数据类型
list1 = [[1, 2], ('name', '张三'), 'ab']
print(dict(list1))
# 返回:{1: 2, 'name': '张三', 'a': 'b'}
03-字典的增删改查
dict1 = {}
print(dict1, type(dict))
# 字典中添加元素
# 1.直接添加:如果字典中不存在某个键,那么直接添加能将这个键值对添加进去
dict1['name'] = '张三'
print(dict1)
# 返回:{'name': '张三'}
# 2.setdefault:向字典中添加键值对,如果这个键已经存在,不做修改;
# 如果不存在,就添加到字典中
dict1.setdefault('name', '李四')
dict1.setdefault('age', 66)
print(dict1)
# 返回:{'name': '张三', 'age': 66}
# 3.update:更新字典中的元素
# a.传入一个字典
dict1.update({'address': '地球村', 'sex': '男'})
print(dict1)
# 返回:{'name': '张三', 'age': 66, 'address': '地球村', 'sex': '男'}
# b.传入关键字,可以在update方法中传入key=value
dict1.update(english=66)
print(dict1)
# 返回:{'name': '张三', 'age': 66, 'address': '地球村', 'sex': '男', 'english': 66}
# c.传入一个包含一个或多个二元组的列表
dict1.update([('math', 0), ('chinese', 100)])
print(dict1)
# 返回:{'name': '张三', 'age': 66, 'address': '地球村', 'sex': '男', 'english': 66, 'math': 0, 'chinese': 100}
# 字典中元素的查找:通过键获取值(确保键是存在的)
print(dict1['name'])
# 返回:张三
# 字典的修改,如果字典中已经存在某个键,这种写法是修改这个键对应的值
dict1['name'] = '法外狂徒张三'
print(dict1)
# 返回:{'name': '法外狂徒张三', 'age': 66, 'address': '地球村', 'sex': '男', 'english': 66, 'math': 0, 'chinese': 100}
# 使用update修改键对应的值,确保这个键是存在的,否则是向字典中添加元素
dict1.update({'age': 10})
print(dict1)
# 删除操作
# a.del 字典['键']:删除字典中指定键对应的键值对(如果键不存在,报错)
del dict1['sex']
# b.字典.pop(键):从字典中删除指定的键值对,返回删除的key对应的值
print(dict1.pop('english'))
print(dict1)
# 返回:{'name': '法外狂徒张三', 'age': 10, 'address': '地球村', 'math': 0, 'chinese': 100}
# c.clear:清空字典
04-推导式
不仅仅列表有推导式,元组、集合、字典也都有
复习一下列表推导式
list1 = [i for i in range(1, 11)]
list2 = [i for i in range(1, 11) if i % 2 == 0]
import random
list3 = [[random.randint(1, 100) for _ in range(3)] for _ in range(5)]
list4 = [f'{i} * {j} = {i * j}' for i in range(1, 10) for j in range(1, i + 1)]
从列表推导式,换个容器符号就是元组、集合推导式的写法;字典推导式不仅需要换容器符号,还需要换添加元素的表达式,需要构造成key:value的形式
dict1 = {i: i ** 2 for i in range(10)}
print(dict1)
# 返回:{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
dict2 = {f'{i} * {j} : {i * j}' for i in range(1, 10) for j in range(1, i + 1)}
print(dict2)
05-字典练习题
stu = [
{'name': '小明', 'age': 18, 'score': 80, 'tel': '1234', 'sex': '男'},
{'name': '小刚', 'age': 17, 'score': 70, 'tel': '12399', 'sex': '女'},
{'name': '小红', 'age': 19, 'score': 90, 'tel': '1237', 'sex': '性别不明'},
{'name': '小强', 'age': 20, 'score': 90, 'tel': '1236', 'sex': '男'},
{'name': '小李', 'age': 15, 'score': 40, 'tel': '1235', 'sex': '女'},
{'name': '小王', 'age': 21, 'score': 95, 'tel': '1238', 'sex': '性别不明'}
]
# 申明一个列表,在列表中保存6个学生的信息
# 1.统计不及格学生的个数
# 自己写的
total = 0
for i in stu:
if i['score'] < 60:
total += 1
print(f'不及格学生人数有{total}人')
# 老师写的
print(len([i for i in stu if i['score'] < 60]))
# 2.打印不及格学生的名字和对应的成绩
for i in stu:
if i['score'] < 60:
print(i['name'], i['score'])
# 3.统计未成年学生的个数
total = 0
for i in stu:
if i['age'] < 18:
total += 1
print(f'未成年学生有{total}人')
# 4.打印手机尾号是8的学生的名字
for i in stu:
if i['tel'][-1] == '8':
print(i['name'])
# 5.打印最高分和对应的学生的名字
max = 0
for i in stu:
if i['score'] > max:
max = i['score']
print(f'最高分是{max}分', end=',')
for i in stu:
if i['score'] == max:
print(i['name'])
# 6.删除性别不明的所有学生
# 自己写的
for i in stu:
if i['sex'] == '性别不明':
stu.remove(i)
print(stu)
# 老师写的
start = 0
while start < len(stu):
if stu[start]['sex'] == '性别不明':
del stu[start]
else:
start += 1
print(stu)
06-HTML简单了解
HTML基础
HTML,全称:超文本标记语言,文件后缀名为.html,html主要负责显示网页中的内容,除了html,构建一个网页还需要:css、JavaScript
css负责渲染网页,梅花网页,对网页进行布局
JavaScropt负责实现处理网页上的一些行为
网页上的内容被卸载html的一种叫做”标签“的东西里面,网页的标签分为:一般标签、自闭合标签
一般标签:由起始标签合结束标签组成,起始标签内可以添加属性,起始标签和结束标签间可以添加内容或其他标签
例如:<h1 属性1=属性值1 属性2=属性值2…>内容或其他标签
自闭合标签:只有一个标签,只能在标签内编写属性
例如:<img 属性1=属性值1 属性2=属性值2…>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!--网页内容就是写在body标签的-->
<h1>我是一级标题标签</h1>
<h2>我是二级标题标签</h2>
<a href="https://www.bilibili.com/" target="_blank">我是超链接标签</a>
<video controls src="https://www.bilibili.com/video/BV1AT411z7dw/?spm_id_from=333.1007.tianma.1-1-1.click&vd_source=94120adf88237c1af620a6d1a08bc690"></video>
</body>
</html>
07-python安装三方模块
python修改镜像源相当于是从网上下载插件,python的三方模块全部存储在模块仓库
模块仓库:https://pypi.org/
python默认的官方仓库服务器在国外,如何快速的从国外服务器安装模块?
修改镜像源,国内有很多像豆瓣、阿里云、清华云等与国外服务器实时同步的服务器,我们可以将镜像源修改成国内服务器镜像源
windows:pip config set global.index-url https://pypi.com/simple
mac/linux:pip3 config set global.index-url https://pypi.com/simple
python安装三方模块
方法一:使用命令安装
windos系统:pip install 模块名
mac、linux系统:pip3 install 模块名
方法二:使用pycharm自带的可视化界面安装
08-requests的使用
作用:requests从本机(本地网络ip地址)向目标网站服务器发送请求,目标网站服务器给本机返回响应结果
# 模块(包、库)的使用都需要导包
import requests
# 目标网站网址
URL = 'https://www.baidu.com'
# headers:标头,将headers赋给爬虫,是为了将爬虫伪装给浏览器
# User-Agent:对应的值包含了浏览器、操作系统的各项信息
Headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.34'
}
# 发送请求,得到相应结果
response = requests.get(url=URL, headers=Headers)
# response变量中存储了目标网站服务器返回给我们的所有的信息
print(response)
# 返回:<Response [200]>
# 查看状态码:statis_code
# 状态码可以查看目标网站服务器的状态
# 200:表示爬虫可用(此处的网站不一定没发现你是爬虫)
# 402:表示服务器直到我们的请求,但是拒绝了我们(服务器发现我们是爬虫,拒绝了我们)
# 400:网页没找到
# 500:服务器崩了
print(response.status_code)
# 返回:200
# 如果拿到的源代码出现了乱码,再添加这段代码
# 从网页源代码中找到编码方式,拿过来改变原来的编码即可
# 小技巧:在输出区ctrl + f,搜索charset
response.encoding = 'utf-8'
# 查看字符串类型的网页源代码:text
print(response.text)
有了字符串类型的源代码,便可以提取网页中我们所需要的信息
方式一:使用正则表达式匹配
方式二:使用BeautifulSoup4模块解析数据
方式三:使用XPath路径选择器解析数据