Python元组、集合、字典、初识爬虫

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路径选择器解析数据

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老树盘根_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值