目录
1. 函数补充
1.1 参数的内存地址
函数执行传参时,传递的是内存地址
# 查看某个值的在内存中的地址
data = [11, 22, 33]
addr = id(data)
print(addr) # 1476589905352
v1 = [11, 22, 33]
v2 = [11, 22, 33]
print(id(v1)) # 2469738598920
print(id(v2)) # 2469738599432
v1 = [11, 22, 33]
v2 = v1
print(id(v1)) # 2192460370440
print(id(v2)) # 2192460370440
对于可变类型在函数中修改元素的内容,所有的地方都会修改。可变类型:列表、字典、集合
# 可变类型 & 修改内部修改
def func(data):
data.append(999)
v1 = [11, 22, 33]
func(v1)
print(v1) # [11,22,33,999]
# 特殊情况:可变类型 & 重新赋值
def func(data):
data = ["a", "b"]
v1 = [11, 22, 33]
func(v1)
print(v1) # [11,22,33]
# 特殊情况:不可变类型,无法修改内部元素,只能重新赋值。
def func(data):
data = "a"
v1 = "b"
func(v1)
print(v1) # b
1.2 函数的返回值是内存地址
def func():
data = [11, 22, 33] # 如果是字符串或者数字会有内存驻留机制,内存地址不变
print(id(data))
return data
v1 = func() # 3156157354504
print(v1, id(v1)) # [11, 22, 33] 3156157354504
v2 = func() # 3156157909832
print(v2, id(v2)) # [11, 22, 33] 3156157909832
# 两次的内存地址是不一样的(变量释放,重新创建)
上述代码执行过程:
- 执行第一次函数
v1 = func()
data = [11,22,33]
创建一块内存区域,内部存储[11,22,33]
,data变量指向这块存储地址3156157354504
return data
返回data指向的内存地址- v1接收返回值,所以 v1 和 data 都指向
[11,22,33]
的内存地址 (两个变量指向此内存,引用计数器为2) - 由函数执行完毕之后,函数内部的变量都会被释放 (删除data变量,引用计数器-1)
- v1最终执行函数内部创建的那块存储地址
3156157354504
- v1最终执行函数内部创建的那块存储地址
- 第二次执行函数
v2 = func()
data = [11,22,33]
创建一块内存区域,内部存储[11,22,33]
,data变量指向这块存储地址3156157909832
return data
返回data指向的内存地址- v2接收返回值,所以 v2 和 data 都指向
[11,22,33]
的内存地址 (两个变量指向此内存,引用计数器为2) - 由函数执行完毕之后,函数内部的变量都会被释放 (删除data变量,引用计数器-1)
- v2最终执行函数内部创建的那块存储地址
3156157909832
1.3 参数的默认值
def func(a1,a2=18):
print(a1,a2)
Python在创建函数(未执行)时,如果发现函数的参数中有默认值,则在函数内部会创建一块区域并维护这个默认值。
- 执行函数未传值时,则让a2指向函数维护的那个值的地址
func("root") # root 18
- 执行函数传值时,则让a2指向新传入的值的地址
func("admin",20) # admin 20
# 在函数内存中会维护一块区域存储 [1,2,666,666,666] 100010001
def func(a1, a2=[1, 2]):
a2.append(666)
print(a1, a2)
func(100) # 100 [1,2,666]
# a1=100
# a2 -> 100010001
func(200) # 200 [1,2,666,666]
# a1=200
# a2 -> 100010001
func(99, [77, 88]) # 99 [77,88,666]
# a1=99
# a2 -> 1111111101
func(300) # 300 [1,2,666,666,666]
# a1=300
# a2 -> 100010001
# 在内部会维护一块区域存储 [1,2,10,20,40 ] ,内存地址 1010101010
def func(a1, a2=[1, 2]):
a2.append(a1)
return a2
v1 = func(10)
print(v1) # [1, 2, 10]
# a1=10
# a2 -> 1010101010
# v1 -> 1010101010
v2 = func(20)
print(v2) # [1, 2, 10, 20 ]
# a1=20
# a2 -> 1010101010
# v2 -> 1010101010
v3 = func(30, [11, 22])
print(v3) # [11, 22,30]
# a1=30
# a2 -> 11111111111 [11, 22,30]
# v3 -> 11111111111
v4 = func(40)
print(v4) # [1,2,10,20,40 ]
# a1=40
# a2 -> 1010101010
# v4 -> 1010101010
# 内存中创建空间存储 [1, 2, 10, 20, 40] 地址: 1010101010
def func(a1, a2=[1, 2]):
a2.append(a1)
return a2
# a1=10
# a2 -> 1010101010
# v1 -> 1010101010
v1 = func(10)
# a1=20
# a2 -> 1010101010
# v2 -> 1010101010
v2 = func(20)
# a1=30
# a2 -> 11111111111 [11,22,30]
# v3 -> 11111111111
v3 = func(30, [11, 22])
# a1=40
# a2 -> 1010101010
# v4 -> 1010101010
v4 = func(40)
print(v1) # [1, 2, 10, 20, 40]
print(v2) # [1, 2, 10, 20, 40]
print(v3) # [11,22,30]
print(v4) # [1, 2, 10, 20, 40]
1.4 动态参数
动态参数,定义函数时在形参位置用 *
或 **
可以接任意个参数
def func(*args, **kwargs):
print(args, kwargs)
func("a", "b", n1='aaaaaa', n2='bbbbbb') # ('a', 'b') {'n1': 'aaaaaa', 'n2': 'bbbbbb'}
在执行函数时,也可以用 *
或 **
- 形参固定,实参用
*
或**
def func(a1, a2):
print(a1, a2)
func(11, 22)
func(a1=11, a2=22)
func(*(11, 22))
func(**{"a1": 11, "a2": 22})
# 需要字典键必须为字符串类型,否则报错:TypeError: keywords must be strings,因为**本质为形参和实参对的传递,而参数变量名不可以数字开头
- 形参和实参都用
*
或**
def func(*args, **kwargs):
print(args, kwargs)
func(11, 22) # (11, 22) {}
func(11, 22, name='小明', age=18) # (11, 22) {'name': '小明', 'age': 18}
func([11, 22], {'k1': 1, 'k2': 2}) # ([11, 22], {'k1': 1, 'k2': 2}) {}
func(*[11, 22], **{'k1': 1, 'k2': 2}) # (11, 22) {'k1': 1, 'k2': 2}
# 按照这个方式将数据传递给args和kwagrs时,数据会重新拷贝一份 (可理解为内部循环每个原始并设置到args和kwargs中)
# 原来格式化方式:
v1 = "姓名:{} 年龄:{}".format('小明', 18)
v2 = "姓名:{} 年龄:{}".format(*['小明'], 18)
# 在使用format字符串格式化时可以这样:
v3 = "姓名:{name},年龄:{age}".format(name='小明', age=18)
v4 = "姓名:{name},年龄:{age}".format(**{'name': '小明', 'age': 18})
练习题
- 看代码写结果
def func(*args, **kwargs):
print(args, kwargs)
params = {'k1': 'v1', 'k2': 'v2'}
func(params)
func(**params)
- 读取文件中的 URL 和 标题,根据URL下载视频到本地(以标题作为文件名)
import requests
def download(title, url):
"""下载并保存视频"""
res = requests.get(
url=url,
headers={
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
}
)
with open('{}.mp4'.format(title), mode='wb') as f:
f.write(res.content)
url_list = [
["测试1", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0d00fg10000c820qnrc77u1ofqasjdg&ratio=720p&line=0"],
["测试2", "h ttps://aweme.snssdk.com/aweme/v1/play/?video_id=v0d00fg10000c4tlq83c77u8tcoaf3cg&ratio=720p&line=0"],
["测试3", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c8s5sbrc77ubpv4as270&ratio=720p&line=0"]
]
for item in url_list:
title, url = item
download(title, url)
2. 函数和函数名
2.1 函数做元素
函数相当于是一个变量,在列表等元素中可以把函数当做元素
def func():
return 123
data_list = ["小明", "func", func, func()]
print(data_list[0])
print(data_list[1])
print(data_list[2])
print(data_list[3])
res = data_list[2]()
print(res)
注意:函数同时也可被哈希,所以函数名同时也可以当做 集合的元素
、字典的键
- 情景1:开发一个类似于微信的功能
def send_message():
"""发送消息"""
pass
def send_image():
"""发送图片"""
pass
def send_emoji():
"""发送表情"""
pass
def send_file():
"""发送文件"""
pass
def xxx():
"""收藏"""
pass
function_dict = {
"1": send_message,
"2": send_image,
"3": send_emoji,
"4": send_file,
"5": xxx
}
print("欢迎使用xx系统")
print("请选择:1.发送消息;2.发送图片;3.发送表情;4.发送文件")
choice = input("输入选择的序号:") # "1"
func = function_dict.get(choice)
if not func:
print("输入错误")
else:
# 执行函数
func()
- 情景2:某个特定情况,要实现发送短信、微信、邮件
def send_msg():
"""发送短信"""
pass
def send_email():
"""发送图片"""
pass
def send_wechat():
"""发送微信"""
pass
func_list = [ send_msg, send_email, send_wechat ]
for item in func_list:
item()
上述两种情景,在参数相同时才可用,如果参数不一致,会出错。
所以,在项目设计时就要让程序满足这一点,如果无法满足,也可以通过其他手段实现,例如:
- 情景1:
def send_message(phone, content):
"""发送消息"""
pass
def send_image(img_path, content):
"""发送图片"""
pass
def send_emoji(emoji):
"""发送表情"""
pass
def send_file(path):
"""发送文件"""
pass
function_dict = {
"1": [send_message, ['15131255089', '你好呀']],
"2": [send_image, ['xxx/xxx/xx.png', '消息内容']],
"3": [send_emoji, ["😁"]],
"4": [send_file, ['xx.zip']]
}
print("欢迎使用xx系统")
print("请选择:1.发送消息;2.发送图片;3.发送表情;4.发送文件")
choice = input("输入选择的序号:") # 1
item = function_dict.get(choice) # [ send_message, ['15131255089', '你好呀']],
if not item:
print("输入错误")
else:
# 执行函数
func = item[0] # send_message
param_list = item[1] # ['15131255089', '你好呀']
func(*param_list) # send_message(*['15131255089', '你好呀'])
- 情景2:
def send_msg(mobile, content):
"""发送短信"""
pass
def send_email(to_email, subject, content):
"""发送图片"""
pass
def send_wechat(user_id, content):
"""发送微信"""
pass
func_list = [
{"name": send_msg, "params": {'mobile': "15131255089", "content": "你有新短消息"}},
{"name": send_email, "params": {'to_email': "xxx@live.com", "subject": "报警消息", "content": "硬盘容量不够用了"}},
{"name": send_wechat, "params": {'user_id': 1, 'content': "在吗"}},
]
for item in func_list:
func = item['name'] # send_msg
param_dict = item['params'] # {'mobile': "15131255089", "content": "你有新短消息"}
func(**param_dict) # send_msg(**{'mobile': "15131255089", "content": "你有新短消息"})
2.2 函数名赋值
- 将函数名赋值给其他变量,函数名其实就个变量,代指某函数;如果将函数名赋值给另外一个变量,则此变量也会代指该函数,例如:
def v1(a1, a2):
print(a1, a2)
v2 = v1 # 此时,xxxxx和func都代指上面的那个函数,所以都可以被执行
v1(1, 1)
v2(2, 2)
def func(a1, a2):
print(a1, a2)
func_list = [func, func, func]
func(11, 22)
func_list[0](11, 22)
func_list[1](33, 44)
func_list[2](55, 66)
- 对函数名重新赋值,如果将函数名修改为其他值,函数名便不再代指函数,例如:
def func(a1, a2):
print(a1, a2)
# 执行func函数
func(11, 22)
# func重新赋值成一个字符串
func = "小明"
print(func) # 小明
- 注意:由于函数名被重新定义之后,就会变量新被定义的值
在自定义函数时,不要与python内置的函数id,bin,hex,oct,len...
同名,否则会覆盖内置函数的功能,例如:
# len内置函数用于计算值得长度
v1 = len("小明")
print(v1) # 2
# len重新定义成另外一个函数
def len(a1, a2):
return a1 + a2
# 以后执行len函数,只能按照重新定义的来使用
v3 = len(1, 2)
print(v3)
2.3 函数名做参数和返回值
函数名其实就一个变量,代指某个函数,所以,它和其它的数据类型一样,也可以当做函数的参数和返回值
- 参数
def plus(num):
return num + 100
def handler(func):
res = func(10) # 110 # handler(func) -> handler(plus) -> plus(10)
msg = "执行func,并获取到的结果为:{}".format(res)
print(msg) # 执行func,并获取到的结果为:110
# 执行handler函数,将plus作为参数传递给handler的形式参数func
handler(plus)
- 返回值
def plus(num):
return num + 100
def handler():
print("执行handler函数")
return plus
result = handler()
data = result(20) # 等于plus(20)
print(data) # 120
3. 返回值和print
- 在函数中使用print,只是用于在某个位置输出内容而已
- 在函数中使用return,是为了将函数的执行结果返回给调用者,以便于后续其他操作
def add(n1, n2):
print(n1 + n2)
v1 = add(1, 3)
print(v1)
4. 作用域
作用域,可以理解为一块空间,这块空间的数据是可以共享的。通俗点来说,作用域就类似于一个房子,房子中的东西归里面的所有人共享,其他房子的人无法获取。
4.1 函数为作用域
Python以函数为作用域,所以在函数内创建的所有数据,可以此函数中被使用,无法在其他函数中被使用。
学会分析代码,了解变量到底属于哪个作用域且是否可以被调用:
def func():
name = "小明"
data_list = [11, 22, 33, 44]
print(name, data_list)
age = 20
print(name, age, data_list)
for num in range(10):
print(num)
print(num)
if 1 == 1:
value = "admin"
print(value)
def handler():
age = 18
print(age)
func()
handler()
4.2 全局和局部
Python中以函数为作用域,函数的作用域其实是一个局部作用域
# 全局变量(变量名大写)
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]
def download():
# 局部变量
url = "http://www.xxx.com"
...
def upload():
# 局部变量
file_name = "rose.zip"
...
COUNTRY
和CITY_LIST
是在全局作用域
中,全局作用域中创建的变量称之为全局变量
,可以在全局作用域中被使用,也可以在其局部作用域中被使用。download
和upload
函数内部维护的就是一个局部作用域,在各自函数内部创建变量称之为局部变量
,且局部变量只能在此作用域中被使用。局部作用域中想使用某个变量时,寻找的顺序为:优先在局部作用域中寻找,如果没有则去上级作用域(全局)中寻找。
- 全局变变量一般都是大写
- 示例1:在局部作用域中读取全局作用域的变量
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]
def download():
url = "http://www.xxx.com"
print(url)
print(COUNTRY)
print(CITY_LIST)
def upload():
file_name = "rose.zip"
print(file_name)
print(COUNTRY)
print(CITY_LIST)
print(COUNTRY,CITY_LIST) # "中国" ["北京","上海","深圳"]
download() # "http://www.xxx.com"...
upload() # "rose.zip"...
print(file_name) # 在全局作用域执行的,全局作用域没有,报错
print(url) # 在全局作用域执行的,全局作用域没有,报错
- 示例2:局部作用域和全局作用域变量同名
COUNTRY = "中国"
CITY_LIST = ["北京", "上海", "深圳"]
def download():
url = "http://www.xxx.com"
CITY_LIST = ["河北", "河南", "山西"]
print(url)
print(COUNTRY)
print(CITY_LIST)
print(COUNTRY) # "中国" # 在全局作用域执行的,取全局
print(CITY_LIST) # ["北京", "上海", "深圳"] # 在全局作用域执行的,取全局
download()
# 输出:
# "http://www.xxx.com" # 局部有,取局部的
# COUNTRY = "中国" # 局部没有,取全局的
# CITY_LIST = ['河北', '河南', '山西'] # 局部有,取局部的
4.3 global关键字
默认情况下,在局部作用域对全局变量只能进行:读取
和 修改内部元素(可变类型)
,对全局变量 无法进行重新赋值
- 读取
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]
def download():
url = "http://www.xxx.com"
print(COUNTRY)
print(CITY_LIST)
download()
- 修改内部元素(可变类型)
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]
def download():
url = "http://www.xxx.com"
print(CITY_LIST)
CITY_LIST.append("广州")
CITY_LIST[0] = "南京"
print(CITY_LIST)
download()
- 无法对全局变量重新赋值
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]
def download():
url = "http://www.xxx.com"
# 不是对全部变量赋值,而是在局部作用域中又创建了一个局部变量 CITY_LIST 。
CITY_LIST = ["河北","河南","山西"]
print(CITY_LIST)
def upload():
file_name = "rose.zip"
print(COUNTRY)
print(CITY_LIST)
download()
upload()
- 如果想要在局部作用域中对全局变量重新赋值,则可以基于
global
关键字实现,例如:
COUNTRY = "中国"
CITY_LIST = ["北京", "上海", "深圳"]
def download():
url = "http://www.xxx.com"
global CITY_LIST
CITY_LIST = ["河北", "河南", "山西"]
print(CITY_LIST)
global COUNTRY
COUNTRY = "中华人民共和国"
print(COUNTRY)
def upload():
file_name = "rose.zip"
print(COUNTRY)
print(CITY_LIST)
download()
upload()
print(COUNTRY, CITY_LIST)
5. 练习题
- 看代码写结果
def func(k, v, info={}):
info[k] = v
return info
v1 = func(1, 2)
print(v1) # {'1':2}
v2 = func(4, 5, {})
print(v2) # {4: 5}
v3 = func(5, 6)
print(v3) # {1: 2, 5: 6}
# 执行时机不同,结果不同
- 看代码写结果
def func(*args, **kwargs):
return (args, kwargs)
# print(func(11, 22, 33))
# print(func([11, 22, 33]))
# print(func(*[11, 22, 33]))
# print(func(k1=123, k2=456))
# print(func({"k1": 123, "k2": 456}))
# print(func(**{"k1": 123, "k2": 456}))
# print(func([11, 22, 33], **{"k1": 123, "k2": 456}))
# print(func(*[11, 22, 33], **{"k1": 123, "k2": 456}))
- 看代码写结果
def func(*args,**kwargs):
prev = "-".join(args)
data_list = []
for k,v in kwargs.items():
item = "{}-{}".format(k,v)
data_list.append(item)
content = "*".join(data_list)
return prev,content
v1 = func("北京","上海",city="深圳",count=99)
print(v1) # ('北京-上海', 'city-深圳*count-99')
v2 = func(*["北京","上海"],**{"city":"深圳","count":99})
print(v2) # ('北京-上海', 'city-深圳*count-99')
- 获取天气信息并按照指定格式写入到文件中
# 获取天气信息示例
import requests
import os
# 补充代码
base_dir = os.path.dirname(os.path.abspath(__file__))
db_file_path = os.path.join(base_dir, 'files', 'weather.txt')
if not os.path.exists(base_dir):
os.makedirs(base_dir)
def write_file(**kwargs):
row_dict = kwargs["weatherinfo"]
data_list = []
# data_list = [f"{k}-{v}" for k, v in kwargs["weatherinfo"].items()]
for k, v in row_dict.items():
group = "{}-{}".format(k, v)
data_list.append(group)
row_string = ",".join(data_list)
with open(db_file_path, mode='a', encoding="utf-8") as file_object:
file_object.write("{}\n".format(row_string))
def get_weather(code):
url = "http://www.weather.com.cn/data/ks/{}.html".format(code)
res = requests.get(url=url)
res.encoding = "utf-8"
weather_dict = res.json()
return weather_dict
city_list = [
{'code': "101020100", 'title': "上海"},
{'code': "101010100", 'title': "北京"},
]
for item in city_list:
# 101020100
result_dict = get_weather(item["code"])
write_file(**result_dict)
- 看代码写结果
def func():
return 1, 2, 3
val = func()
print(type(val) == tuple) # True
print(type(val) == list) # False
- 看代码写结果
def func(v1):
return v1 * 10
def bar(arg):
return "{}".format(arg)
val = func('=')
data = bar(val)
print(data)
- 看代码写结果
def func():
data = 2 * 3
return data
data_list = [func,func,func]
for item in data_list:
v = item()
print(v) # 返回值 6 6 6
- 看代码写结果
def func(handler, **kwargs):
# v1: handler() -> something()
# v1: kwargs = {'k1':123,'k2':456}
# v2: handler() -> killer()
# v2: kwargs = {"name":"小明","age":18}
extra = {
"code": 123,
"name": "小明"
}
kwargs.update(extra)
# v1: {'k1':123,'k2':456,'code':123,'name':'小明'}
# v2: {"name":"小明","age":18,'code':123} # 有重复去掉
return handler(**kwargs)
def something(**kwargs):
# len({'k1':123,'k2':456,'code':123,'name':'小明'})
return len(kwargs) # 4
def killer(**kwargs):
# {"name":"小明","age":18,'code':123}
key_list = []
for key in kwargs.keys():
key_list.append(key)
# return key_list # 如果return放在这则只返回name便结束
return key_list
v1 = func(something, k1=123, k2=456)
print(v1) # 4
v2 = func(killer, **{"name": "小明", "age": 18})
print(v2) # ['name','age','code']
- 看代码写结果
def func():
return 123
v1 = [func, func, func, func]
print(v1)
# [<function func at 0x000000D25BA4E440>, <function func at 0x000000D25BA4E440>, <function func at 0x000000D25BA4E440>, <function func at 0x000000D25BA4E440>]
v2 = [func(), func(), func(), func()]
print(v2)
# [123, 123, 123, 123]
# v1没有执行函数,只接收了内存地址,v2列表内的函数元素被执行得到了返回值
- 看代码写结果
NUM_LIST = []
SIZE = 18
def f1():
NUM_LIST.append(8)
SIZE = 19
def f2():
print(NUM_LIST)
print(SIZE)
f2() # [] 18
f1() # 无输出,但执行了一次 NUM_LIST.append(8) SIZE = 19
f2() # [8] 18
- 看代码写结果
NUM_LIST = []
SIZE = 18
def f1():
global NUM_LIST
global SIZE
NUM_LIST = "嘿嘿"
SIZE = 19
def f2():
print(NUM_LIST)
print(SIZE)
f2() # [] 18
f1() # 无输出,但执行了一次 NUM_LIST = "嘿嘿" SIZE = 19
f2() # "嘿嘿" 19
- 根据要求实现资源下载器。
- 启动后,让用户选择专区,每个专区用单独的函数实现,提供的专区如下:
1. 下载 花瓣网图片专区
2. 下载 抖音短视频专区
3. 下载 NBA锦集 专区 - 在用户选择了某个功能之后,表示进入某下载专区,在里面循环提示用户可以下载的内容选项(已下载过的则不再提示下载)
提醒:可基于全部变量保存已下载过得资源。 - 在某个专区中,如果用户输入(Q/q)表示 退出上一级,即:选择专区。
- 在选择专区如果输入Q/q则退出整个程序。
- 每个专区实现下载的案例如下:
1. 图片
# 可供用户下载的图片如下
image_dict = {
"1":("吉他男神","https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V"),
"2":("漫画美女","https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO"),
"3":("游戏地图","https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd"),
"4":("美女","https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz"),
}
2. 短视频
# 可供用户下载的短视频如下
video_dict = {
"1":{"title":"东北F4模仿秀",'url':"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"},
"2":{"title":"卡特扣篮",'url':"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"},
"3":{"title":"罗斯mvp",'url':"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg"},
}
3. NBA
# 可供用户下载的NBA视频如下
nba_dict = {
"1":{"title":"威少奇才首秀三双","url":"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg&ratio=720p&line=0"},
"2":{"title":"塔图姆三分准绝杀","url":"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag&ratio=720p&line=0"}
}
初始版本:
import requests
SELECTED_IMAGE_SET = set() # 已下载图片ID(序号)
SELECTED_VIDEO_SET = set()
SELECTED_NBA_SET = set()
def download(file_path, url):
res = requests.get(
url=url,
headers={
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
}
)
with open(file_path, mode='wb') as f:
f.write(res.content)
def download_image():
total_image_dict = {
"1": ("吉他男神", "https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V"),
"2": ("漫画美女", "https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO"),
"3": ("游戏地图", "https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd"),
"4": ("美女", "https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz"),
}
while True:
# 构造 1.吉他男神;2.漫画美女;
text_list = []
for num, item in total_image_dict.items():
if num in SELECTED_IMAGE_SET:
continue
data = "{}.{}".format(num, item[0])
text_list.append(data)
if text_list:
text = ";".join(text_list)
else:
text = "无可下载选项"
# 输出:1.吉他男神;2.漫画美女;3.游戏地图;4.美女
print(text)
# 返回上一步
index = input("请输入要选择的序号(Q/q退出):")
if index.upper() == "Q":
return
# 选择序号 3
if index in SELECTED_IMAGE_SET:
print("已下载,无法再继续下载,请重新选择!")
continue
group = total_image_dict.get(index)
if not group:
print("序号不存在,请重新选择")
continue
# 下载图片
file_path = "{}.png".format(group[0])
download(file_path, group[1])
# 已下载集合中
SELECTED_IMAGE_SET.add(index)
def download_video():
total_video_dict = {
"1": {"title": "东北F4模仿秀",
'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"},
"2": {"title": "卡特扣篮",
'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"},
"3": {"title": "罗斯mvp",
'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg"},
}
while True:
text_list = []
for num, item in total_video_dict.items():
if num in SELECTED_VIDEO_SET:
continue
data = "{}.{}".format(num, item["title"])
text_list.append(data)
if text_list:
text = ";".join(text_list)
else:
text = "无可下载选项"
print(text)
index = input("请输入要选择的序号(Q/q退出):")
if index.upper() == "Q":
return
if index in SELECTED_VIDEO_SET:
print("已下载,无法再继续下载,请重新选择!")
continue
group = total_video_dict.get(index)
if not group:
print("序号不存在,请重新选择")
continue
file_path = "{}.mp4".format(group["title"])
download(file_path, group["url"])
SELECTED_VIDEO_SET.add(index)
def download_nba():
total_nba_dict = {
"1": {"title": "威少奇才首秀三双",
"url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg&ratio=720p&line=0"},
"2": {"title": "塔图姆三分准绝杀",
"url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag&ratio=720p&line=0"}
}
while True:
text_list = []
for num, item in total_nba_dict.items():
if num in SELECTED_NBA_SET:
continue
data = "{}.{}".format(num, item["title"])
text_list.append(data)
if text_list:
text = ";".join(text_list)
else:
text = "无可下载选项"
print(text)
index = input("请输入要选择的序号(Q/q退出):")
if index.upper() == "Q":
return
if index in SELECTED_NBA_SET:
print("已下载,无法再继续下载,请重新选择!")
continue
group = total_nba_dict.get(index)
if not group:
print("序号不存在,请重新选择")
continue
file_path = "{}.mp4".format(group["title"])
download(file_path, group["url"])
SELECTED_NBA_SET.add(index)
print("欢迎使用xxx系统")
func_dict = {
"1": download_image,
"2": download_video,
"3": download_nba
}
while True:
print("1.花瓣网图片专区;2.抖音短视频专区;3.NBA锦集专区 ")
choice = input("请选择序号:")
if choice.upper() == "Q":
break
func = func_dict.get(choice)
if not func:
print("输入错误,请重新选择!")
continue
# 进入专区
func()
v2:
import requests
DB = {
"1": {
"area": "花瓣网图片专区",
"total_dict": {
"1": ("吉他男神", "https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V"),
"2": ("漫画美女", "https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO"),
"3": ("游戏地图", "https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd"),
"4": ("美女", "https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz"),
},
"ext": "png",
"selected": set()
},
"2": {
"area": "抖音短视频专区",
"total_dict": {
"1": {"title": "东北F4模仿秀",
'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"},
"2": {"title": "卡特扣篮",
'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"},
"3": {"title": "罗斯mvp",
'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg"},
},
"ext": "mp4",
"selected": set()
},
"3": {
"area": "NBA锦集专区",
"total_dict": {
"1": {"title": "威少奇才首秀三双",
"url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg&ratio=720p&line=0"},
"2": {"title": "塔图姆三分准绝杀",
"url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag&ratio=720p&line=0"}
},
"ext": "mp4",
"selected": set()
},
}
def download(file_path, url):
res = requests.get(
url=url,
headers={
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
}
)
with open(file_path, mode='wb') as f:
f.write(res.content)
def handler(area_info):
# 进入专区提醒
summary = "欢迎进入{}".format(area_info['area'])
print(summary)
# 专区中选择下载
while True:
text_list = []
for num, item in area_info['total_dict'].items():
if num in area_info['selected']:
continue
if type(item) == tuple:
data = "{}.{}".format(num, item[0])
else:
data = "{}.{}".format(num, item["title"])
text_list.append(data)
if text_list:
text = ";".join(text_list)
else:
text = "无可下载选项"
print(text)
index = input("请输入要选择的序号(Q/q退出):")
if index.upper() == "Q":
return
if index in area_info['selected']:
print("已下载,无法再继续下载,请重新选择!")
continue
group = area_info['total_dict'].get(index)
if not group:
print("序号不存在,请重新选择")
continue
if type(group) == tuple:
title, url = group
else:
title, url = group['title'], group['url']
file_path = "{}.{}".format(title, area_info['ext'])
download(file_path, url)
area_info['selected'].add(index)
print("欢迎使用xxx系统")
while True:
print("1.花瓣网图片专区;2.抖音短视频专区;3.NBA锦集 专区 ")
choice = input("请选择序号(Q/q退出):")
if choice.upper() == "Q":
break
# 选择序号: 去db中找对应的字典信息
area_dict = DB.get(choice)
if not area_dict:
print("输入错误,请重新选择!")
continue
# 进入专区(area_dict选择的专区信息)
handler(area_dict)