Python
贴菜鸟的教程:
https://www.runoob.com/python,注:本资料部分文档来源于菜鸟教程。
数据类型
| 数据类型 | 描述 | 例子 |
|---|---|---|
| int | 整数 | 1 |
| float | 浮点数 | 1.00 |
| String | 字符串 | "test" |
| bool | 布尔类型,True /False | t=5>1 # True |
查看数据类型
type(数据),用于查看数据类型,
python中变量没有类型
例:
print(type(1)) # 查看结果,type(1)具有返回值可以被变量所接受
# 整数
数据类型转换
| 函数 | 描述 | 例子 |
|---|---|---|
| int(x) | 将x转换为整数,可将字符转换为数字 | num_1 = int("1") |
| float(x) | 将x转换为单精度数据 | float_1 = float(23) |
| str(x) | 将x转换为字符串 | str_1 = str(123) |
例:
# 数据类型转换
# int转换 String转换
num_1 = int("1")
print(num_1)
# 双精度装为int精度丢失
num_2 = int(12.34)
print(num_2)
# 数字转字符
str_1 = str(123)
print(type(str_1), str_1)
# 双精度转换
float_1 = float(23)
print(type(float_1), float_1)
操作运算符
| 操作符 | 描述 | 例子 |
|---|---|---|
| // | 整除,得到的结果是整数 | 9//2==4 |
| ** | 指数运算,得到一个数的指数次结果 | 2**10==1024 |
| / | 除操作,得到的结果是单精度数据类型float | 9/2==4.5 |
例:
# 操作运算符
# // 整除符
num_3 = 9 // 2
print(num_3)
# ** 指数操作符
num_4 = 2 ** 10
print(num_4)
# python的/得到的是双精度数据类型
num_5 = 9 / 4
print(num_5)
字符串的定义方式
- 第一种单引号,'我是字符串1'
- 第二种双引号,"我是字符串2"
- 第三种三双引号,也是注释,支持多行,""" 我是字符串3 """
- 同时单引号和双引号可以互相包裹,不能包裹自身,不过可以通过转义字符实现
\+或者是\+"
字符串拼接
通过
+拼接,不能与int或者float进行拼接
字符串格式化
# 格式化单个
print("my name is %s"%"唐志峰")
# 格式化多个
print("my name is %s and age is %d"%("唐志峰",20)) # 多个占位符通过()填充数据
# 设置数字的精度,%m.nf 其中f是float,m是宽度,n是小数位数,遵循四舍五入,宽度不够用空格占位
print("my name is %s and age is %.0f" % ("唐志峰", 20))
常用占位符
| 符号 | |
|---|---|
| %s | 字符串 |
| %d | 整数 |
| %f | 单精度浮点数 |
同时还可以通过如下方式格式化字符串,通过
f""标识字符串,然后通过{数据}进行占位
age=20;
print(f"my name is {age}") # {}动态占位
控制语句
python的层级通过缩进实现,一般缩进四个空格,tab键即可
input
这是输入语句,可接受到键盘输入的内容,类型为String,输入的内容在同一行
age=input("输入你的年龄")
print(f"年龄是:{age}")
if-elif-else
# 基本格式
if 18>10:
print ("hi!")
elif 18>15:
print ("hi!")
else:
print ("hi!!!")
# python中,if内部的语句通过缩进实现,缩进四个空格
# elif是else-if的简写
# 与input语句结合
if int(input("输入你的年龄?"))>18:
print("你已经成年了")
elif str(input("输入你的性别?"))=="男":
print("虾头男!真虾头")
elif float(input("输入你的存款?"))>=10000.0:
print("小有存款")
while
# while
a = 1
while 1:
print(a)
a += 1
if a == 10:
break
# while-else
a=1
while a<5:
print(a)
a+=1
else:
print("a more than 5!")
for
有点类似于vue中v-for循环, 关键字
in后面跟的是具体的对象(数组对象),字符串也可以range(start,end)
range()是内置函数,可以给定一定区间的序列,包前不包后,也可以给定一个参数,即参数end位置
len()是内置参数,用户获取字符串或者数组长度
# 简单for循环
arr = [1, 2, 3, 4]
str_arr = "abcdefghijklmnopqrstu"
for a in str_arr:
print(f"当前字符是{a}")
# for-range循环
# for-range
for idx in range(len(arr)):
print(arr[idx])
pass
用于在函数定义时,未想好函数具体的实现时,用作占位使用
# python2.x:
def function():
# 空函数在Python2.x版本中pass是必须的
pass
# python3.x:
def function():
# 在Python3.x的时候pass可以写或不写
pass
# 或者是其他需要具体内容地方
if a>1:
pass
函数定义
基本定义格式
def functionName(参数名): 函数体 return
参数
给定默认参数
在python函数定义中,参数值可以给定一个默认值,当该参数未传入时,择使用默认参数
def defaultParams(a,b=1):# 给定b一个默认参数
return
关键字参数匹配
在python函数中,传入参数时,可以根据参数名称匹配,如下,顺序此时可不遵循,python底层会进行匹配,不过需要再
def keyWordParams(a,b,c):
return
# 调用函数
keyWordParams(b=1,c=3,a=2) # 此时的abc的值与函数的参数列表的参数根据名称一一对应,如果未对应,程序运行会出错
不定长参数
python的函数定义中,如果参数的个数无法确定,可以使用不定长参数,通过
*params定义不定长参数列表
def add5(*args):
print(args)
return sum(args)
d = add5(1, 2, 3, 4, 5)
print(d)
return返回值
默认返回为
None,可返回任意类型
数据容器
序列切片,像list,tuple,string等支持索引的序列都满足
list=[1,2,3,4,5,6,7,8,9,10] print(list[::1]) # 正向输出,步长为1 print(list[::-1]) # 逆向输出,步长为1
- 第一个
:是起始索引,默认为0- 第二个
:是结束索引位置,默认为len(list)-1- 第三个
:是索引的步长
list
更多在
[Python 列表(List) | 菜鸟教程 (runoob.com)](https://www.runoob.com/python/python-lists.html),或者到官网学习
- 基本的定义格式为
list=[1,2,3,4,5],在java或者其他的高级语言中通常不会这么随意,同时元素包裹符号为[]list,可以存放不同类型的元素,可以近似的看成Object类型的数组list,有常见的添加元素方法和删除方法等,
# 对list初始化 *后面跟的是初始化数组的长度
list=[0]*10;
# 定义list
list1 = [1, 2, 3, 4, 5]
for i in list1:
print(i)
# # list可以存放不同类型的数据
list2 = [1, 2, 3, "hello", True, None]
for i in list2:
print(i)
# list可以嵌套存放list
list3 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for i in list3:
print(i)
for j in i:
print(j)
# 追加元素至list
list4 = []
list4.append(1)
list4.append(2)
list4.append(3)
print(list4)
# 删除元素
list4.remove(2)
print(list4)
# list4.clear()
min = min(list4)
max = max(list4)
print("最小值是:%d" % min)
print("最大值是:%d" % max)
print(list4.count(3))
list4.insert(1, 4) # 第一个参数是插入的索引的位置,第二个参数是元素值
print(list4)
# 排序
# 对list4进行升序排序
list4.sort()
print(list4)
# 对list4进行降序排序
list4.sort(reverse=True)
print(list4)
元组
t=(a,b,c,d) # define tuple
集合set
集合特点,无序,无重复,可修改,不支持索引
# 定义空集合
myset = set()
# 添加元素
myset.add(1)
myset.add(2)
myset.add(3)
myset.add(3)
myset.add(4)
myset.add(5)
# 输出
print(myset)
# 删除元素3
myset.remove(3)
# 输出
print(myset)
# 弹出元素,数字有序
myset.pop()
print(myset)
# 清空
myset.clear()
print(myset)
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 取两集合的差集,可用-或者difference方法
print(set1 - set2)
print(set1.difference(set2))
# 取并集合,使用|或者union方法
print(set1 | set2)
print(set1.union(set2))
# 遍历
for i in set1.union(set2):
print(i)
字典
# 定义字典
dict1 = {'name': '小明', 'age': 18, 'gender': '男', 'height': 175, 'weight': 55, 78: 78}
# 根据键名获取值
print(dict1['age'])
# 修改值
dict1['age'] = 20
print(dict1['age'])
# 直接添加key:value
dict1['address'] = '上海'
print(f"添加地址元素后{dict1}")
# 常用api
# 获取所有键名
print(f"获取所有键名{dict1.keys()}")
# 获取所有键值
print(f"获取所有键値{dict1.values()}")
# 获取元祖数组
print(f"获取元祖数组{dict1.items()}")
# 根据键名获取键值
print(f"标准键名{dict1.get('name', '暂无')}") # 第二个参数是默认参数,当键名不存在时
# 清空字典
dict1.clear()
print(dict1)
# 删除字典,释放内存
del dict1
日期和时间
time模块
python中时间日期格式化符号:
- %y 两位数的年份表示(00-99)
- %Y 四位数的年份表示(000-9999)
- %m 月份(01-12)
- %d 月内中的一天(0-31)
- %H 24小时制小时数(0-23)
- %I 12小时制小时数(01-12)
- %M 分钟数(00-59)
- %S 秒(00-59)
- %a 本地简化星期名称
- %A 本地完整星期名称
- %b 本地简化的月份名称
- %B 本地完整的月份名称
- %c 本地相应的日期表示和时间表示
- %j 年内的一天(001-366)
- %p 本地A.M.或P.M.的等价符
- %U 一年中的星期数(00-53)星期天为星期的开始
- %w 星期(0-6),星期天为星期的开始
- %W 一年中的星期数(00-53)星期一为星期的开始
- %x 本地相应的日期表示
- %X 本地相应的时间表示
- %Z 当前时区的名称
- %% %号本身
import time # 导入time模块
# 获取时间戳
now = time.time()
# 打印上面的now时间,时间戳
print(now)
# 时间戽数表示的时间
print(time.localtime(now))
# 时间元组表示的时间
# 格式化日期
print(time.strftime("%Y-%m-%d %H:%M:%S"))
# 标准样式
print(time.asctime())
calendar
# 导入日历模块
import calendar
# 获取指定日期的日历
print(calendar.month(2023, 8))
# 判断年份是否是闰年
print(calendar.isleap(2023))
模块
搜索路径
当你导入一个模块,Python 解析器对模块位置的搜索顺序是:
- 1、当前目录
- 2、如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录。
- 3、如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/。
模块搜索路径存储在 system 模块的 sys.path 变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
包是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的 Python 的应用环境。
简单来说,包就是文件夹,但该文件夹下必须存在 init.py 文件, 该文件的内容可以为空。init.py 用于标识当前文件夹是一个包。
考虑一个在 package_runoob 目录下的 runoob1.py、runoob2.py、init.py 文件,test.py 为测试调用包的代码,目录结构如下:
test.py package_runoob |-- __init__.py |-- runoob1.py |-- runoob2.py
# 导入整个模块
import BrainySearch
list = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57,
59, 61, 63, 65, 67, 69, ]
res = BrainySearch.binary_search(list, 69)
print(res)
# 导入模块中单一的函数
from BrainySearch import binary_search
res2 = binary_search(list, 35)
print(res2)
# 导入模块中全部的函数
from BrainySearch import *
res3 = binary_search(list, 37)
print(res3)
文件IO
Python 文件I/O | 菜鸟教程 (runoob.com)
open()函数的编码格式通过encoding指定,一般使用
utf-8
| 方法 | 解释 |
|---|---|
| open(mode,Path,encoding) | 用于打开文件,mode是打开模式,具体模式有如下表所示,path是文件路径,encoding是编码格式,一般使用utf-8 |
| read(count) | 读取文件内容,按字节数读取 |
| readline() | 读取一行 |
| readlines() | 读取全部内容,以list形式存储,可遍历 |
| write() | 写入内容,这里要求文件打开模式为可写入,个人推荐使用a+模式,可读可写. |
| writelines() | 写入一行,可自己添加换行符,writelines("hello world\n") |
| flush() | 将内容从缓存写入到硬盘中 |
| close() | 关闭文件 |
| closed() | 判断文件是否已经关闭 |
| tell() | 返回文件当前的位置,即处于第几个字符的索引位置 |
| seek(start,offset) | 设置文件的指针位置,start是参照位置的索引,offset是偏移的索引值,默认是0,0即文件开头的位置 |
| with open() as f: | 是一种打开文件的语法,读取结束后,会自动关闭文件流,f是整个文本内容(readlines()),可遍历f[本质还是list]。 |
不同模式打开文件的完全列表:
| 模式 | 描述 |
|---|---|
| t | 文本模式 (默认)。 |
| x | 写模式,新建一个文件,如果该文件已存在则会报错。 |
| b | 二进制模式。 |
| + | 打开一个文件进行更新(可读可写)。 |
| U | 通用换行模式(不推荐)。 |
| r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
| rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
| r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
| rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
| w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
| w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
| ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
fileObj = open("test.txt", "a+",encoding="utf-8") # opens the file in read mode
print(fileObj.name) # prints the name of the file
print(fileObj.mode) # prints the mode in which the file was opened
position = fileObj.tell() # prints the current position of the file pointer
print(position)
fileObj.seek(0) # moves the file pointer to the beginning of the file
ContentStr = fileObj.read(10)
print(ContentStr) # prints the content of the file
fileObj.close() # closes the file
print(fileObj.closed) # prints whether the file is closed or not
# 导入os模块
import os
os.rename("test.txt", "test1.txt") # 重命名文件
os.remove("test1.txt") # 删除文件
os.mkdir("test") # 当前目录下创建新的文件夹
os.rmdir("test") # 删除文件外目录
Exception异常
Python 异常处理 | 菜鸟教程 (runoob.com)
基本语法
try: except: # 捕获所有异常或者采用except Exception: # 捕获单个异常,except NameError: # 捕获多个时,用()括上 # except Exception as e: # print(e) 打印异常信息 # 可选有else和finallyexcept是发生异常时执行
else是异常未发生时执行
finally是异常无论发生都会执行
个人感觉else很奇怪
try:
fh = open("testfile", "w")
fh.write("这是一个测试文件,用于测试异常!!")
except IOError as e:
print "Error: 没有找到文件或读取文件失败"
print(e) # 打印异常信息
else:
print "内容写入文件成功"
finally:
fh.close()
面向对象
class parent:
# 公共变量
name = "tzf"
age = 20
# 私有变量
__sex = "男"
def __init__(self, name, age):
self.name = name
self.age = age
print("parent init")
# 定义公共方法
def getSex(self):
return self.__sex
# 定义私有方法 __methods
def __privateMethods(self):
return f"用户信息:用户名{self.name}\n年龄:{self.age}\n性别:{self.getSex()}"
# 重写str方法
def __str__(self):
return self.__privateMethods()
# 重写add方法
def __add__(self, other):
return f"用户年龄之和:{self.age + other.age}"
# 创建对象
p1 = parent("tzf", 20)
print(p1.getSex())
print(p1)
p2 = parent("ymj", 19)
print(p2.getSex())
print(p2)
数据注解&形参注解&方法注解
相当于提示,对数据类型的提示,多的不说,上代码
UNION
# 数据类型的
a: int = 10
b: dict[str, int] = {"age": 10}
c: list[int] = [1, 2, 3]
d: tuple[int, int] = (1, 2)
# 或者注释
a=10 # type:int
# 形参的
def add(a:int):
pass
# 方法的
def str_substr(string: str, start: int, end: int) -> str:
# 判断参数str是否是合法字符中
if not isinstance(string, str):
raise TypeError('str_reverse() only accepts string')
return string[start:end]
mysql连接
import pymysql
db = pymysql.connect(host='localhost', user='root', password='root', port=3306, db='reggie')
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# 使用 execute() 方法执行 SQL 查询
cursor.execute('select * from orders')
# 使用 fetchone() 方法获取单条数据.
data = cursor.fetchone()
print(data)
多线程
# 下面的例子是基于threading中Thread模块的
# 引入线程
from threading import Thread
def runStart():
for t in range(1000):
print(f"子线程:{t}")
if __name__ == '__main__':
# 开启子线程
Thread(target=runStart).start()
for i in range(1000):
print(f"主线程:{i}")
协程
[协程与任务 — Python 3.11.4 文档](https://docs.python.org/zh-cn/3/library/asyncio-task.html)
# 导入协程模块,开启异步任务
import asyncio
import time
async def f1():
await asyncio.sleep(3)
print("3s")
async def f2():
await asyncio.sleep(4)
print("4s")
async def f3():
await asyncio.sleep(5)
print("5s")
async def main():
# 创建两个任务
task1 = asyncio.create_task(f1())
task2 = asyncio.create_task(f2())
print(f"started at {time.strftime('%X')}")
# 开启挂载
await task1
await task2
print(f"started at {time.strftime('%X')}")
if __name__ == '__main__':
asyncio.run(main())
爬虫
需要用到的库有
requests,发送网络请求菜鸟:Python requests 模块 | 菜鸟教程 (runoob.com)
BeautifulSoup库,用于解析html css等网页内容练习的网站:
demo1,解析<p>
import requests
from bs4 import BeautifulSoup
res = requests.get("http://books.toscrape.com/").text
soup = BeautifulSoup(res, "html.parser")
all_price = soup.findAll("p", {"class": "price_color"})
print("书单价格:")
for price in all_price:
print(price.string[1:])
demo2,爬取豆瓣
import requests
from bs4 import BeautifulSoup
# 添加请求头,模拟网站发送请求
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36 Edg/88.0.705.74"
}
i = 1;
for start in range(0, 250, 25):
content = requests.get(f"https://movie.douban.com/top250?start={start}", headers=headers).text
soup = BeautifulSoup(content, "html.parser")
for item in soup.findAll("span", attrs={"class": "title"}):
if "/" not in item.string:
print(f"排名第{i}的电影是--->{item.string}")
i += 1
demo3,爬取知乎,需要cookie
也可以使用
request.session(),保存会话状态,保存自动获取cookie
import requests
import os
from bs4 import BeautifulSoup
import time
# 解析cookie
cookies = "cookies"
# 模拟网站发送请求
# 添加请求头,模拟网站发送请求
# h2-->HotItem-title
headers = {
"cookie": cookies,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
url = "https://www.zhihu.com/hot"
res = requests.get(url, headers=headers).text
soup = BeautifulSoup(res, "html.parser")
context = soup.findAll("h2", attrs={"class": "HotItem-title"})
hot = soup.findAll("div", attrs={"class": "HotItem-content"})
idx = 1
createFileUrl = "D:\\pythonProject\\zhihuHot.txt"
zhihuHotFile = open(createFileUrl, "a+", encoding="utf-8")
title = f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}的知乎热榜:"
print(title)
zhihuHotFile.writelines(title + "\n")
for i in context:
zhihuHotFile.writelines(f"热度第{idx}的标题是<<" + i.string + f">>,热度:{hot[idx - 1].select('div')[0].text}\n")
idx += 1
# 写入文件
zhihuHotFile.close()
print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}的知乎热榜文件保存至{createFileUrl}")
demo4,梨视频
主要防反爬的措施是,防盗链,和地址的
url的改变
import requests
# 获取session
session = requests.session()
# 具体的请求的资源路径,即referer
referer = "https://www.pearvideo.com/video_1497209"
# 获取contId
contId = referer.split("_")[1]
# 发起登录请求,保存会话状态
url = f"https://www.pearvideo.com/videoStatus.jsp?contId={contId}&mrd=0.9779566895867053"
# 请求头
headers = {
"Referer": referer,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
}
# 请求参数使用字典存放
data = {
}
result = session.get(url, headers=headers, data=data)
# 设置编码
result.encoding = "utf-8"
dt = result.json()
# 获取视频资源链接
srcUrl = dt["videoInfo"]["videos"]["srcUrl"]
# 获取时间戳
systemTime = dt["systemTime"]
# 对srcUrl进行替换
srcUrl = str(srcUrl)
srcUrl = srcUrl.replace(systemTime, f"cont-{contId}")
print(f"{referer}的视频资源路径为:{srcUrl}")
# 对视频资源进行下载
# 地址
address = f"D:/Temp/{contId}.mp4"
with open(address, mode="wb") as f:
f.write(session.get(srcUrl).content)
print(f"梨视频站点的{referer}的视频资源已下载完毕!,保存地址:{address}")
demo5,爬取西游记,异步
asyncio.wait(),从3.11开始,需要通过asyncio.create_task创建task
import requests
import asyncio
import aiohttp
import json
import aiofiles
async def Download(bookId, cid, title):
data = {
"book_id": bookId,
"cid": f"{bookId}|{cid}",
"need_bookinfo": 1
}
url = f"https://dushu.baidu.com/api/pc/getChapterContent?data={json.dumps(data)}"
async with aiohttp.ClientSession() as s:
async with s.get(url) as res:
dit = await res.json()
content = dit['data']['novel']['content']
async with aiofiles.open(title, mode="w", encoding='utf-8') as f:
await f.write(content)
async def getBookInfo():
# 书籍id
bookId = "4306063500"
# 下载路径
baseUrl = f"C:/book/"
# cookie
cookies = "BAIDUID=635FE5371F9F52EC90558D9B6E49B2F5:FG=1; BAIDUID_BFESS=635FE5371F9F52EC90558D9B6E49B2F5:FG=1"
# header
headers = {
"Sec-Ch-Ua": "Chromium';v = '116', 'Not)A;Brand';v = '24','Microsoft Edge';v = '116'",
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": "Windows",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"cookie": cookies,
"Host": "dushu.baidu.com",
"If-None-Match": 'W/"2b7d-ZsELp86aJawrzgjq9ti2Mw"',
"Referer": f"https://dushu.baidu.com/pc/detail?gid={bookId}",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.0.0"
}
# 请求书籍基本内容的url
url = 'https://dushu.baidu.com/api/pc/getCatalog?data={"book_id":' + bookId + '}'
resp = requests.get(url, headers=headers)
resp.encoding = 'utf-8'
dit = resp.json()
task = []
for item in dit['data']['novel']['items']:
task.append(
asyncio.create_task(Download(bookId=bookId, cid=item['cid'], title=baseUrl + item['title'] + ".txt")))
await asyncio.wait(task)
if __name__ == '__main__':
# 下载图书
asyncio.run(getBookInfo())
技巧
解析cookies
cookies="cookies"
cookies = {i.split("=")[0]: i.split("=")[1] for i in cookies.split(";")}