python重试、异常捕获、迭代器、生成器

八周内容笔记

day22

很多笔记内容都在代码块里

01-高阶函数练习题

简单的回忆了一下map和reduce

1.将下列每个学生及其成绩组合为一个字典,再转换为列表。
列表形式:[{‘name’:‘张三’, math:90},{‘name’:‘李四’, math:89},…]

names = ['张三', '李四', '小明', '小红']
math = [90, 89, 88, 99]
english = [98, 78, 66, 82]
chinese = [23, 98, 100, 72]
print(list(map(lambda x, y, m, n: {'name': x, 'math': y, 'english': m, 'chinese': n}, names, math, english, chinese)))

2.使用reduce求10的阶乘

from  functools import reduce
list1 = [i for i in range(1, 11)]
print(reduce(lambda x, y: x * y, list1, 1))

02-有参装饰器

装饰器是真的有点绕

一个登录系统,判断某位用户是会员还是白嫖用户

def id_judge(kind):
    def outter(func):
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            if result == '登录成功':
                print('尊敬的VIP用户' if kind == 'VIP' else '万恶的白嫖用户', end=',')
                return '登录成功'
            else:
                return '登录失败'
        return wrapper
    return outter


@id_judge('VIP')
def login(user, password):
    if user == 'admin' and password == '123456':
        return '登录成功'
    else:
        return '登录失败'

print(login('admin', '123456'))

装饰器的应用场景:

插入日志,性能测试,事务处理,web权限校验,Cache有效性测试等位置可以使用(web开发)。

装饰器优点:能够不改变原函数从而使其具有新功能。

缺点:不好理解,性能不太好

似乎数据分析不太用得上装饰器?

03-重试机制

import requests
from retrying import retry

# python中的retrying模块提供的retry方法,可以直接以语法糖的形式装饰给需要重试的函数
# @retry -> 这样的写法等于永久性的重试
# stop_max_attempt_number = 5最多重试五次
# wait_fixed=2000等待2000毫秒再重试
# wait_random_min=1000, wait_random_max=3000 -> 最少等待1000毫秒,最多等待3000毫秒,在这之间随机
@retry(stop_max_attempt_number = 5, wait_random_min=1000, wait_random_max=3000)
def requests_get(href):
    print('正在请求或正在重试', href)
    response = requests.get(url=href)
    print(response)

URL_List = [
    'https://www.baidu.com/',
    'https://www.jd.com/',
    'https://a123b.123/',
    'https://www.taobao.com/'
]

for i in URL_List:
    requests_get(i)

04-请求缓存

cache:缓存

requests-cache模块可以借助install_cache方法在本地留存请求网站的缓存,当有了这个网站的缓存以后,再次请求此网站,优先使用缓存下来的网页内容,缓存内容会以sqlite文件的形式保存在当前文件夹。

import requests
import requests_cache
requests_cache.install_cache(cache_name='cache_file')
# 如果网页更新了,我们需要重新加载缓存,先删除已存在缓存,再重新加载
# requests_cache.clear() -> 删除缓存
# requests_cache.clear()

URL = 'https://movie.douban.com/top250?start=0'
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)
print(response.status_code)
print(response.text)

day23

01-异常捕获

一、错误和异常

1.语法错误,编辑器直接提示某个位置有错误。

2.逻辑错误,程序在运行过程中产生的错误。

二、异常捕获

有些时候程序报了错必须要将bug解决掉;但是有些时候我们明知道程序可能会在某些地方产生错误,但是这个错误不影响正常的工作、程序的运行等,并且这个错误解决起来花费的人力、物力与解决这个bug产生的价值严重不匹配,我们选择性忽视掉bug的存在,就可以借助异常捕获来实现这个功能。

1.try…except语法

for i in range(-5, 6):
    try:
        print(10 / i)
        print(1 + '2')
        print('12345, 上山打老虎')
    except ZeroDivisionError as err:
        print(f'出错了,出错原因:{err}')
    except Exception as err:
        print(err)

异常捕获语法一:

try:

可能会报错的代码(注意:只要此处一报错,立马执行except)

except Exception as err:

Exception --> python中最大的异常类(所有异常原因的集合)
出错后执行的代码

except …:

出错后执行的代码

多个except可以报了什么类型的错误,执行相应的解决的代码。

2.异常捕获的else语句

try:
    a = int(input('请输入一个整数:'))
    b = int(input('请输入一个整数:'))
    result = f'{a} / {b} = {a / b}'
except ZeroDivisionError as err:
    print(f'报错了,报错原因:{err},0不能作为除数')
except ValueError as err:
    print(f'报错了,报错原因:{err},输入错误')
else:
    print(result)

异常捕获中,try中的代码是可能产生错误的代码,一般我们将额外的代码添加到else子句中。

3.finally子句

存在于finally下的代码,无论程序是否出错都会被执行

file = open('./01-异常捕获.py', 'r', encoding='utf-8')
try:
    result = file.write('写入测试内容')
except Exception as err:
    print('文件操作失败')
finally:
    file.close()

02-重试机制添加异常捕获

import requests
from retrying import retry
@retry(stop_max_attempt_number=10)
def requests_get(link):
        response = requests.get(url=link)
        print(f'访问{link}成功,访问状态码{response.status_code}')
URL_List = [
    'https://www.baidu.com/',
    'https://jd.com/',
    'https://a123b.123/',
    'https://www.taobao.com/'
]
for i in URL_List:
    try:
        requests_get(i)
    except Exception as err:
        print(f'访问{i}出错,出错原因{err}')
    # 为什么添加异常捕获,上方重试了10次却只打印了一次错误
    # retry方法自带异常捕获,直到最后一次重试结束才会将最终报错抛出来

03-迭代器

一、什么是迭代?

迭代在python中是一个非常强大的功能,它可以用于访问字符串、列表、集合、字典、元组等容器中的元素,还可以节省内存。

迭代是通过for循环遍历这些容器中的元素的过程,所以我们也可以称能够使用for循环的容器为可迭代对象,还有一个东西也可以被for循环遍历,它叫做迭代器。

二、什么是迭代器(iter)?

迭代器是可迭代对象的一个子集,它可以记住遍历的位置。

三、迭代器的性质

1.可以进行遍历。

2.打印迭代器无法查看其中的元素,也无法使用len方法统计迭代器中元素个数。

3.如果要获取迭代器中的元素,就必须按照顺序一个一个的取元素。

4.某个元素被从迭代器中取出以后,那么迭代器中就不会再有这个元素

四、如何创建迭代器?

# 1.使用iter方法将容器转为迭代器。
# 2.创建一个生成器。(迭代器包含生成器,生成器一定是迭代器,但是迭代器不一定是生成器)
str1 = 'abcde'
a = iter(str1)
print(a, type(a))
# 返回:<str_iterator object at 0x00000221C00697C0> <class 'str_iterator'>
# print(len(a)) # TypeError: object of type 'str_iterator' has no len()

五、获取迭代器中的元素

print(next(a)) #a
print(next(a)) #b
for i in a:
    print(i) #c、d、e
# print(next(a)) #StopIteration -> 停止迭代

这个迭代器就是一次性的,迭代器中元素取完,迭代器中就没有元素,失去利用价值,迭代器中元素取完,自动销毁迭代器。

day24

01-生成器

一、什么是生成器(generator)?

生成器一定是迭代器,但是迭代器不一定是生成器。

能生成迭代器的并且使用yield关键字的函数被称为生成器。

二、生成器的性质

a.生成器返回的是一个迭代器。

b.在调用生成器函数时,函数体并不执行,只是返回一个生成器对象。

c.在对生成器对象使用next方法或者循环遍历时,生成器函数才真正执行。

三、生成器的使用

1.验证在调用生成器函数时,函数体并不执行,只是返回一个生成器对象。

def func_1():
    print('我是一个生成器函数')
    yield

result = func_1()
print(result)
# 返回:<generator object func_1 at 0x000001E19AECCC10>

2.空值生成器产生的数据的个数和数值

# 生成器能产生多少数据取决于函数体内有多少个yield会被执行。
def func_2():
    yield 100
    yield 200
    if 10 > 20:
        yield 300
    return 400
    yield 500

result = func_2()
print(result)
# 返回:<generator object func_1 at 0x0000022982C89660>
#      <generator object func_2 at 0x0000022982C89510>
print(next(result))     #100
print(next(result))     #200
# print(next(result))     #StopIteration: 400

3.生成器产生数据的原理(生成器内部代码如何执行,执行顺序?)

def func_3():
    print('#########')
    yield 100
    print('*********')
    yield 200
    print('+++++++++')
    yield 300
result = func_3()
print(result)
print(next(result))
print(next(result))
print(next(result))
# 返回:<generator object func_3 at 0x000001CF6C5D9660>
#      #########
#      100
#      *********
#      200
#      +++++++++
#      300

02-生成器和迭代器对比

一、生成器和迭代器的区别

1.迭代器是访问容器的一种方式,也就是说,容器已经出现。我们只是从容器中copy了一份副本,将这个副本转为迭代器,而生成器是我们通过代码生成的。

2.迭代器在开发中很难被用到,生成器使用频率高很多。

二、为什么使用生成器?

python的生成器提供了延迟操作,在需要的时候才执行产生结果。

1.节省资源消耗:和声明容器不同,容器一产生就占用了内存,但是生成器不使用时几乎不占用内存。

2.使用的时候,生成器是随用随生成,用完立即释放,不占用内存。

三、return和yield区别

1.相同点:return和yiled都返回函数的结果。

2.不同点:return一执行,函数立即结束,yield是让函数变成生成器,不迭代时,函数被冻结;迭代时,函数再被唤醒,按照迭代次数返回相应数量的元素。

03-生成器练习题

写一个生成器,可以创建python学生的学号。例如:python1001、python1002、python1003等,一直到python1999。

# 自己写的,只能一次性生成全部,不能做到随用随取,说到底还是没吃透
def creat():
    list = [i for i in range(1, 1000)]
    for i in list:
        str1 = 'python' + str(1000 + i)
        print(str1)
    yield
# result = creat()
print(creat())
print(next(creat()))

# 老师写的
def stu_id(num):
    for i in range(1001, num+1):
        yield f'python{i}'

result = stu_id(1999)
# 获取200个学生的学号
for i in range(200):
    print(next(result))
# 再取一个
print(next(result))
# 取完剩下的所有
for i in result:
    print(i)

04-python模块基本认知

一、什么是模块

模块,又叫做库;python中存在很多模块,模块就是实现了某一个或者某一类功能代码的集合。

二、python中模块分类

模块主要分两类:内置模块(安装python时自带的)、三方模块

三方模块其实也分成两种:自定义模块(我们在本地创建的)、其他人发布的模块(需要安装的)

三、常用的一些模块

内置模块

random:随机模块

time:时间模块

os:包含很多操作系统指令的模块

re:正则表达式模块

四、其他人发布的模块

pygame:常用的游戏模块

flask、django:后端开发的框架

requests:发送请求的模块

scrapy:世界排名第一的最流行的爬虫框架

seleium、playwright:web自动化测试框架

BeautifulSoup4、lxml:网页解析框架

五、自定义模块:我们自己根据实际需求开发的模块,通常是对某段逻辑或某些函数的防撞,可以供我们使用(重复调用)。

05-python导入模块

python提供了很多种导包方式,不同情况下可以择优选择。为什么要导包?内置模块、三方模块不导包无法使用。

1.import模块1, 模块2, 模块3…

这种导包方式,会将模块中所有的成员(变量、函数、类等)全部导入到你的程序中会造成性能低下,不仅如此,想使用某个方法还需要使用模块名.方法名的形式。

import random, time
print(random.randint(1, 100))
print(time.altzone)

2.from 模块名 import *

等价于import 模块,只是在调用某个方法时,不需要再模块名.方法名

from time import *
print(sleep(1))

3.from 模块名 import 方法1, 方法2, 方法3…

性能最好,需要什么方法,就只导入什么方法,不需要的方法没有导入不会使程序中方法、变量等冗余。

from os import listdir
# listdir根据指定的路径,查看该路径下的所有子文件和子文件夹。默认当前文件夹。
print(listdir())

4.import 模块名 as 别名

我需要用到某个模块下面的很多方法,但是模块名比较长,可以给模块名设置别名,使用简短的别名进行方法调用。

import random as rd
print(rd.randint(1, 2))

5.from 模块名 import 方法 as 别名

有些模块中的某些方法名字很长,我需要多次调用这个方法,但是又不想写特别长的名字,就可以给这个方法也设置个别名。

from random import randint as ri
print(ri(100, 200))

使用频率比较:1、3 > 4、5 > 2

07-transfer_module

自定义模块

# 随意的定义一些内容

def twoSum(x, y):
    return x + y

c = 50
# 上方代码是实现的功能
# 下方代码是功能的测试
# 能不能不对外展示程序的测试部分?能

if __name__ == '__main__':
    a = 10
    b = 20
    print(twoSum(a, b))
    print(a, b)

注意:name和main两侧的两条下划线被markdown用上了,不知道怎么给他拿出来

if name == ‘main’:的作用?

导包时,被导包的模块中的所有的print都会被执行,防止这种情况发生,将不应该执行的代码全部放入到if name == ‘main’:中,另一个代码中,调用此模块,处于if name == ‘main’:中的代码就不会被调用到。

一个py文件就是一个模块,py文件名就是模块名

调用自定义模块

import define_module
# 能够将整个模块中的所有的成员导入

from define_module import twoSum, c
print(c)
print(twoSum(100, 200))

from define_module import a, b
print(a, b)
# 返回:ImportError: cannot import name 'a' from 'define_module' (D:\Qianfeng01\day24\define_module.py)

虽然a,b可以被调用到,但是不能使用,a,b已经是私有化的变量了

08-反反爬虫手段

1.写爬虫,一定要添加伪装:User-Agent(UA)

2.休眠:time.sleep(),防止访问过于频繁,被封ip

3.封ip之后,可以换手机热点,手机每次开关飞行模式,ip地址会发生变化

4.封ip之后,使用代理ip

5.随机UA

6.fake-useragent 模块,可以随时更换随机的UA

09-豆瓣电影爬虫调用自定义的请求模块

自定义模块

import requests
from random import choice

def fake_UA():
    global ua_list
    with open('./UserAgent.txt', 'r', encoding='utf-8') as f:
        ua_list = eval(f.read())

fake_UA()

def requests_get(link:str):
    # print(ua_list)
    Headers = {'User-Agent': choice(ua_list)}
    response = requests.get(url=link, headers=Headers)
    return response.text if response.status_code == 200 else response.status_code


if __name__ == '__main__':
    # URL = 'https://taobao.com/'
    # print(requests_get(URL))
    result = fake_UA()
    print(result, type(result))

调用自定义模块实现爬虫功能

from requests_func import requests_get
import time
from random import randint
from bs4 import BeautifulSoup
for i in range(0, 10):
    print(f'---------这是第{i + 1}页----------')
    URL = f'https://movie.douban.com/top250?start={i * 25}&filter='
    # 调用自定义模块
    result = requests_get(URL)
    soup = BeautifulSoup(result, 'html.parser')
    lilist = soup.select('html > body > div#wrapper ol > li')
    # print(lilist)
    for i in lilist:
        # 电影标题
        movieTitle = i.select('li > div.item > div.info > div.hd > a > span.title')
        movieList = [i.text for i in movieTitle]
        movieTitle = ''.join(movieList)
        # 电影评分
        movieScore = i.select_one('li div.bd > div.star > span.rating_num').text
        # # 电影评论人数
        commPeople = i.select_one('li div.bd > div.star > span:nth-child(4)').text
        # 中心思想
        middIdea = i.select_one('li div.bd > p.quote > span.inq')
        middIdea = middIdea.text if middIdea != None else ''
        print(movieTitle, movieScore, commPeople, middIdea)
    # 每一页爬取完毕,休眠一下,防止我们被检测到
    # sleep:休眠,强制等待几秒钟
    time.sleep(randint(1, 3))

10-random模块

random模块是python提供一系列随机方法的模块

from random import *
# 1.randint()
# 返回区间[a, b]内随机整数
print(randint(10, 11))  #10、11

# 2.randrange()
# 相当于从range方法产生的序列中随机抽取一个元素(int)
print(randrange(10, 11))    #10

# 3.choice()
# 从非空容器中随机选取一个元素
print(choice([1, 2, 3]))    #1、2、3

# 4.choices()
# 从非空容器中随机选取k个元素,k默认为1,choices是有放回的抽取
print(choices([1, 2, 3, 4], k=5))   #[2, 3, 1, 1, 2]

# 5.sample()
# 从有序容器中无放回的抽取k个元素,k无默认值
print(sample([1, 2, 3, 4], k=4))    #[1, 3, 2, 4]

# 6.shuffle()
# 将有序可变的容器中元素的位置打乱(洗牌)
list1 = [6, 7, 8, 9]
shuffle(list1)
print(list1)    #[8, 6, 7, 9]

# 7.random()
# 从区间(0.0, 1.0)范围中随机选取一个浮点数(左闭右开区间)
print(random())     #0.5776464281608823

# 8.uniform()
# 从[a, b]范围随机返回一个浮点数
print(uniform(1, 10))   #6.030000853904442
# 爬虫的休眠中,其实uniform比randint更合适

随机生成长度为4的包含数字、字母的验证码

# 自己写的
list1 = [chr(i) for i in range(48, 58)] + [chr(i) for i in range(65, 91)] + [chr(i) for i in range(97, 123)]
str = ''
for i in range(4):
    str += choice(list1)
print(str)
# 老师写的
list1 = [chr(i) for i in range(48, 58)] + [chr(i) for i in range(65, 91)] + [chr(i) for i in range(97, 123)]
print(''.join(choices(list1, k=4)))

11-pip模块常用指令

pip:python的包管理工具

1.获取pip帮助
pip help

2.安装模块
pip install 模块名

3.安装指定版本的模块
pip install 模块名==版本号

4.卸载模块
pip uninstall 模块名

5.列举已安装的模块
pip list

版本号的规范模式:A.B.C

A:大版本,软件整体升级
B:中版本,功能性更新
C:小版本,修复bug,提升稳定性

6.查看哪些模块有新的版本可以更新
pip list -o

7.模块升级

a.重新指定安装什么版本的模块
pip install tqdm==4.65.0

b.指定升级模块
pip install -U 模块名
需要特别注意的是,如果你升级的是pip包管理工具,在windows系统下,还要添加–user命令,以表示提供管理员权限
pip install -U pip --user所以,pip包管理工具只要能用,绝不升级

8.批量导出已安装过的模块
pip freeze > requirements.txt

9.批量安装已导出的模块
pip install -r requirements.txt

10.查看某个已安装的模块的信息
pip show 模块名

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

老树盘根_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值