导图社区 Python入门笔记精炼
这是一篇关于Python的思维导图,主要内容包括:基础数据对象,基础,系统库,未深入使用库,openpyxl,xlwings,requests,beautifulsoup4,pandas,pyautogui,pyperclip,pyecharts,selenium,python-docx,pyinstall,爬虫与反爬虫,根据用途整理。
编辑于2025-08-31 21:19:43Python
基础数据对象
str对象
capitalize():把字符串的第一个字符大写
center:'字符串'.center(int,'制表符'),以“字符串”居中,前后分别用“制表符”填充,最终形成int长度的新字符串
count(str, beg=0, end=len(string)):在字符串beg至end区间内查找str出现的次数
endswith(""):str.endswith(".xlsx") 判断字符串是否以指定文本结尾,多用于文件筛选和判断
expandtabs(tabsize=8):把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8
format
a='{0}{2:03d}{0}{1}{0}'.format('1','2',4) b='{:03d}'.format(4) print(a) print(b) 输出: 1004121 004
find():查找指定字符位置
find() 没找到指定字符(串)的,返回值为“-1”
filename_tmp = filename_tmp[str(filename_tmp).find('-') + 1:] 视作从第一个'-'字符后开始截取字符,阶段'-'及之前字符
isalnum():如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False
isalpha():如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False
isdecimal():如果 string 只包含十进制数字则返回 True 否则返回 False
isdigit():如果 string 只包含数字则返回 True 否则返回 False
isnumeric():如果 string 中只包含数字字符,则返回 True,否则返回 False
isspace():如果 string 中只包含空格,则返回 True,否则返回 False.
join(seq):"str".join(seq)表示以str作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
lower():字符串转小写
lstrip():截掉 string 左边的空格
replace(str1, str2, num=string.count(str1)):把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次
rfind(str, beg=0,end=len(string) ):返回字符串最后一次出现的位置,如果没有匹配项则返回 -1。
rstrip():删除 string 字符串末尾的空格.
s = '###hello###'.strip('#') 指定要删除的字符
split(str="", num=string.count(str)):以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+1 个子字符串
title()
# 字符串首字母大写 s = "program" print(s.title()) --->Program
upper():字符串转大写
用“切片”方式截取字符创,str[0:4] 相当取前4位
重复N遍:str(x)*N,将字符串重复N次后组成新字符串
datatime
islcalendar():返回周数
to_datetime()
一般要先通过处理,将str对象整理成可以变化为日期数据的样式,如通过replace方法,替换分隔符、中文描述等 pd.to_datatime(df['日期'], format='%Y-%m', exact=True) format参数:年用大写的Y表示,月用小写的m表示,大写的M表示分
pd.DateOffset(n=-1, months=1) n表示偏移量,-1表示往前一个月
strftime():将日期转换为指定的字符串格式的形式
# 控制日期对象的字符串格式展现形式 time = datetime.datetime.today() time1 = time.strftime("%Y-%m-%d") time2 = datetime.datetime.strftime(time, "%Y-%m-%d") time3 = time.strftime("%H:%M:%S")
%Y表示4位字符的年份,%m表示2位字符的月份,%d表示2位字符的日,%H表示2位字符(24小时制)的小时数,%M表示2位字符的分钟数,%S表示2位字符的秒针数(最大值61,支持润秒)
strptime()将字符串转为日期类型
# 字符串转为日期对象 date_obj = datetime.datetime.strptime(str("2023-12-16"), "%Y-%m-%d") --->2023-12-16 00:00:00
date类:日期类,用于处理年、月、日
# 构建date对象,整数传入参数,默认月、日按两位数输出(str强制转换) time1 = datetime.date(2023, 7, 4) 输出结果:2023-07-04
datetime.date.today():日期YYYY-MM-DD格式
year、month、day属性:提取datatime对象的年、月、日属性值
fromordinal():依据一个int对象生成日期数据
time1 = datetime.date.fromordinal(100) -->0001-04-10,以天为单位
toordinal():依据一个datetime对象生成一个int对象,相当fromordinal()的逆过程
weekday():返回日期对象是“星期X”,返回值为0-6的int对象,默认0表示周一、1表示周二
isoweekday():与weekday一样返回“星期X”,差异在于0表示周日、1表示周一
isocalendar():将日期转换为datetime.IsoCalendarDate对象,有year(年份)、week(年内的第几周)、weekday(周X,int对象,2表示周二)
strftime(format):把日期按照format指定的格式进行格式化,
replace(year, month, day):用传入的参数值更新原日期数据
today():
timetuple():
isoformat():
time类:时间类,用于处理时、分、秒
#构建time对象,整数传入参数 time1 = time(10, 58,59) -->10:58:59
hour、minute、second、microsecond:时、分、秒、微秒
replace():方法
isoformat():返回“HH:MM:SS”格式的时间字符串
timetuple():返回一个time.struct_time对象,包含tm_year(年)、tm_mon(月)、tm_mday(日)、tm_min(分)、tm_sec(秒)、tm_wday(周X,1表示周二)、tm_yday(年内第X天)、tm_isdst()
datetime类:日期时间类,综合处理日期数据
timedelta类:时间间隔类,对两个时间点做“加、减”法
参数包括:days、seconds、microseconds、milliseconds、minutes、hours、weeks。通过加减法做日期偏移
one_week_ago= datetime.datetime.now() - datetime.timedelta(weeks=1) one_day_later = datetime.datetime.now() + detetime.timedelta(days=1)
timezone(offset=timedelta, name=str):反映时区概念,以UTC为基准,设定偏移的时区数;name是指通过地址字符(只接受已预定义的)描述时区,部分地址因季节等原因在年内会归属于不同时区的,不支持该调用发方法。
tzinfo类:时区的有关信息
根据6位数字返回“上月”“次月”日期代码
date_str = '202412' date_pre = datetime.datetime.strftime(datetime.datetime.strptime(date_str, "%Y%m") - datetime.timedelta(days=1), "%Y%m") date_next = datetime.datetime.strftime(datetime.datetime.strptime(date_str, "%Y%m") + datetime.timedelta(days=31), "%Y%m")
判断两个日期之间的间隔
from datetime import datetime # 定义两个日期时间字符串 date_string_1 = '2023-03-01 10:00:00' date_string_2 = '2023-03-01 15:30:00' # 将字符串转换为datetime对象 date_1 = datetime.strptime(date_string_1, '%Y-%m-%d %H:%M:%S') date_2 = datetime.strptime(date_string_2, '%Y-%m-%d %H:%M:%S') # 计算两个日期之间的时间差 delta = date_2 - date_1 # 输出间隔的小时数 print(delta.total_seconds() / 3600) --->5.5
元组对象
不可变更内部元素的序列,内部元素可以引用可变对象(如列表),不能变更引用的对象,但是引用对象的内部数据是可以变动并更新到元组对象 t1=() 空元组 t2=tuple() 空元组 t3=tuple(('Python','hello',90)) 有元素的元组
列表对象
区别于数组(或字典),不能用二维索引的方式“(行,列)”调取数据,要用“:"(冒号)连接列表中的位置,列表位置从0开始计算 [::-1]:所有元素,从末位开始,倒着取数 [:5:-1]:所有元素,从末位开始,倒着取5个数 #正向取数,前一个参数表示开始位置,后一个参数表示终止位置,如若,前小后大,可以取到元素;前大后小,是取不到数值的。翻过来,反向取数的时候,就要前大后小了 list[8:5:-1]:表示从0开始索引位置8的元素,倒着取数,去到大于5的位置(即6),结束的3个元素
正向取数
[0:]:取出所有元素 [1:3],选中内部排序(从0起算位置)2、3的两个元素,当列表元素数量少于指定数值,显示到末位元素截止 [0:10:2]:先限定从0开始到索引位置9的元素作为候选范围,按照每2个“步长”取数(偶数位)的规则,筛选出列表内部元素 [0::2]:将所有元素作为候选范围,每隔2个筛选出来
逆向取数
list[-2:]:取倒数2个元素
提取list对象内符合条件的对象
my_list = [10, 20, 30, 40, 50] filtered_list = [element for element in my_list if element > 30] print(filtered_list) # 输出:[40, 50]
推导列表
# 创建平方数列表 squares = [x**2 for x in range(1, 6)] print(squares) # 输出:[1, 4, 9, 16, 25] # 筛选偶数列表 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] even_numbers = [x for x in numbers if x % 2 == 0] print(even_numbers) # 输出:[2, 4, 6, 8, 10]
获取重复元素
my_list = [10, 20, 30, 20, 40] duplicates = [element for element in my_list if my_list.count(element) > 1] print(duplicates) # 输出:[20]
获取指定类型的元素
my_list = [10, "apple", 30, "banana", 40] strings = [element for element in my_list if isinstance(element, str)] print(strings) # 输出:["apple", "banana"]
list[1:3] = [] 将索引位置1-2的元素替换成指定对象,当替换值为空,相当于删除;当替换值数量大于原数量的,相当于增补
append()方法:
在列表尾部增加一个元素(可以是单一值,也可以是集合)
file_list.append(sheet_ori.cell(row=i, column=j).value
clear()方法:清空对象内容,保留一个空对象
copy()方法:从结果上与赋值一样,区别在于直接赋值公用内存空间,对象的id一致,copy则新建一个内存空间,id不一样了
count()方法:统计列表中与输入参数相同元素的个数
del方法:del list 删除一个对象。del list[2]表示删除列表中索引为2(即第3个元素)
extend()方法:在列表尾部至少添加一个元素
filter():用于根据指定的条件筛选可迭代对象中的元素,并返回一个新的可迭代对象,其中包含满足条件的元素
# 筛选列表中的偶数 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] even_numbers = list(filter(lambda x: x % 2 == 0, numbers)) print(even_numbers) # 输出:[2, 4, 6, 8, 10] # 筛选长度大于等于5的字符串 words = ["apple", "banana", "cherry", "date", "elderberry"] long_words = list(filter(lambda x: len(x) >= 5, words)) print(long_words) # 输出:['apple', 'banana', 'cherry', 'elderberry']
find():
list.find(obj, [start, [stop]]) list可以是列表也可以是字符串 obj是查找的元素 start: 开始索引, 默认为0 stop: 结束索引, 默认为列表长度 --->找到了就返回首次发现的位置,找不到返回-1
index()方法
list.index('des',1,4) 在索引位置1-3的位置(不含3)上找'des',找不到会返回错误(异常)
num = list.index(值) 会返回查找值在list对象内的索引值,如果查找值在列表对象内出现多次的,仅返回第一次出现的位置
insert(位置索引序号,元素)方法:插入元素
map():将一个函数应用于一个可迭代对象的每个元素,并返回一个新的可迭代对象,其中包含应用函数后的结果
# 对列表中的每个元素进行平方运算 numbers = [1, 2, 3, 4, 5] squared_numbers = list(map(lambda x: x**2, numbers)) print(squared_numbers) # 输出:[1, 4, 9, 16, 25] # 将字符串列表中的单词转换为大写 words = ["apple", "banana", "cherry"] uppercase_words = list(map(str.upper, words)) print(uppercase_words) # 输出:['APPLE', 'BANANA', 'CHERRY']
pop(索引位置序号):删除指定位置的元素
sort()方法:list.sort(Reverse=True) 将列表对象按降序排序,不指定Reverse参数值,默认升序排列
sorted()方法:new_list = sorted(list , Reverse = True)
remove(元素值)发放:删除首个与元素值相等的对象
reverse()方法:无参数且不返回任何对象,运行方法后,列表对象原有元素排序反转
对存储内容均为数值的列表对象求和,可以用sum(list)
比对两个list对象的差异,通过集合set操作
list1 = ['一级机构', '二级机构', '三级机构', '四级机构'] list2 = ['一级机构', '机构路径'] set1 = set(list1) set2 = set(list2) print(list(set1 - set2))
字典对象
字段对象由 key+value 元组形式组成,key不允许重复,value则无限制。浪费内存,是一种占用较大内存空间,提高短时间频繁处理数据时的速度
score = {'张三':100,'李四':95,'王五':97} '类似数组对象 socre.get('张三') '返回100,找不到会返回None score['王五'] '返回97,找不到会抛出keyError score.get('张麻子',99) '当找不到索引对象,返回指定值
判断:if '张三' in scores
删除:del scores['张三']
清空:scores.clear()
新增/修改:scores['Jack']=90 如果字段中本来没有该对象,执行新增,如果有了,执行数据修改
视图
keys = socres.keys() '返回dict_keys类,字段的索引列 list(keys) '将索引列存入一个列表
values = scores.values() '返回一个dict_values类 list(values) '将数据列存入一个列表
items = scores.items() list(items) '将字典每个元素key+value作为一个“元组”对象,逐一存入列表
遍历
for item in scores: print(item, scores[item]) print(item, scores.get(item)) '与上一行代码结果一致
快速生成
items = ['fruit','books','others'] prices = [96,78,85] d = {item:price for item,price in zip(items,prices)} 'item:price 为数据字典形式,后续描述数据来源 list(zip(items,prices)) '将各元组以列表的形式存储
range对象
'表示从1开始,到stop的整数序列 range(stop) '表示从start开始,到stop的整数序列 range(start,stop) '表示从start开始到stop,步长为step的整数序列 range(start,stop,step)
基础
语法
注释:单行注释以#开头,多行注释以'''(三个英文单引号)开头和结尾
接收手工输入参数:a = input('请输入一个参数:'),人工输入数据后,程序继续执行
数据声明: row_num:int
多参数赋值:a,b,c = 20,30,40
数据类型转换
pd.to_datetime()
pd.to_datetime(m, errors='coerce')
pd.to_datetime(df[['year', 'month', 'day']])
pd.to_timedelta()
pd.to_numeric()
pd.to_numeric(c, errors='ignore')
pd.to_numeric(m, errors='coerce').fillna(0) 托底填充0
if...else...
if XXX==XXX : XXX else: XXX
# 含公式的if判断,要用括号将条件框选起来 if (check_add > 0) & (check_minus == 0) 和 if check_add > 0 & check_minus == 0 的判断结论不一样,&的运算优先级会高于大于、等于的判断优先级
while循环
# 根据 条件 的取值情况,开展循环 while 条件: 代码段…… else 表示当条件为否的时候,执行的语句
continue 表示跳过本次循环,不再执行本次循环的剩余代码,即便有else也不执行
break 表示退出循环,执行循环代码段后面的代码
for...in...循环
for 变量 in 数值集合 代码 else 代码 变量在数值集合内的各个数值条件下执行一遍代码,超出数值集合后执行可选的else段代码。Python中的for循环类似C++中的foreach循环语句
continue 表示跳过本次循环,不再执行本次循环的剩余代码,即便有else也不执行
break 表示退出循环,执行循环代码段后面的代码
print方法
pd.set_option('display.unicode.ambiguous_as_wide', True) pd.set_option('display.unicode.east_asian_width', True) pd.set_option('display.max_columns', None) 显示全部列
format
将变量引入字符串构建语句中,快速调整格式化字符串内容 name = 'Peter' age = 23 print('{} is {} years old'.format(name, age)) print(f'{name} is {age} years old.')
将“公式”引入字符串构建语句中,快速调整格式化字符串内容 salary = '15000' num = 12 print('This position income is {salary * num}')
控制日期的显示格式 now = datetime.datetime.now() print(f'{now:%Y-%m-%d %H:%M}') 输出结果:2023-05-25 16:06
控制浮点数显示位数,预计是采取截断数据的方式 val = 12.3 print(f'{val:.2f}') --->12.30 print(f'{val:.5f}') --->12.30000
控制字符长度, print(f'{x:02}') ---->01 2个字符宽度,不足的前方补0 print(f'{x:>10}') -->" 1",字符宽度10,右对齐,前方补空格
异常处理机制
代码段中必须指定异常类型,才能继续处理 try: XXX exception BaseException as a: XXXX else: XXXX
常见异常类型
ZeroDivisionError:除数为0的异常
IndexError:索引不存在的异常
KeyError:索引映射不存在
NameError:未声明对象的异常
SyntaxError:语法错误
ValueError:传入无效参数
上下文管理器
with
with open('example.txt', 'r') as file: content = file.read() print(content)
封装exe文件
安装pyinstaller:命令窗口界面,pip install pyinstaller 在Pycharm窗口“终端”(terminal)窗口:pyinstaller -F --onefile main.py 在dist目录下:新形成了一个main.exe文件
转义字符
\\,\',\",\n(换行),\r(回车),\t(tab制表符),\b(退格),当字符串前方加r前缀的,则串内转义字符不再起作用
正则表达式
. 表示匹配除了换行符之外的所有字符
* 表示匹配前面的子表达式任意次,包括0次
+ 表示匹配前面的子表达式一次或多次,不包括0次
? 表示匹配前面的子表达式0次或1次
{} 表示前面的字符匹配指定的次数
a{6}表示a出现6次
a{1,6}表示a出现1-6次
a{1,}表示a出现两次以上
\ 表示对元字符进行转义
\d 匹配0-9之间任意一个数字字符,等价于表达式[0-9]
\D 匹配任意一个不是0-9之间的数字字符,等价于表达式[^0-9]
\s 匹配任意一个空白字符,包括空格、tab、换行等等,等价于表达式[\t\n\r\f\v]
\S 匹配任意一个非空白字符,等价于表达式[^\t\n\r\f\v]
\w 匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式[a-zA-Z0-9];缺省情况也包括Unicode文字字符,如果指定ASCII码标记,则只包括ASCII字母。
\W 匹配任意一个非文字字符,等价于表达式[^a-zA-Z0-9]
[\s,.] 表示匹配:任何空白字符,或者逗号,或者点
[abc] 可以匹配a,b或者c里面的任意一个字符。等价于[a-c]
[a-c] 中间的-表示一个范围:从a到c
[a-z] 表示匹配所有的小写字母
[akm.] 表示匹配a k m .里面任意一个字符,这里的.在方括号里面不再表示匹配任意字符了,而就是表示匹配.这个字符
^ 表示匹配文本的起始位置:
如果是单行模式,表示匹配整个文本的开头位置;
如果是多行模式,表示匹配文本每行的开头位置。
[^] 方括号中使用^表示非方括号里面的字符集合。
例如:[^\d]表示选择非数字的字符,等同于表达式[^0-9]
$ 表示匹配文本的结尾位置:
如果是单行模式,表示匹配整个文本的结尾位置;
如果是多行模式,表示匹配文本每行的结尾位置。
() 组选择
<.+> 默认贪婪匹配“任意字符”
<.+?> 懒惰匹配“任意字符”
(a|b) 匹配a或者b
(ab)|(cd) 匹配ab或者cd
(?=-)表示取到“-”字符之前的内容
companyname = "BAGH00-鞍钢集团轧辊技术有限公司" # 使用()分组,match.group(0)的值是“BAGH00-”,match.group(1)的值是“BAGH” match = re.search(r'(.*)-', companyname) # 不使用()分组,match.group(0)的值是“BAGH00-”,match.group(1)的值报错,不存在分组 match = re.search(r'.*-', companyname)
enumerate
通过枚举的方式迭代读取对象 animals = ['cat','dog','cow'] test = enumerate(animals) print(list(test)) # [(0, 'cat'), (1, 'dog'), (2, 'cow')] animals = ['cat','dog','cow'] test = enumerate(animals, 100) print(list(test)) # [(100, 'cat'), (101, 'dog'), (102, 'cow')] animals = ['cat','dog','cow'] for index, animal in enumerate(animals): print(index, animal)
# 使用range() data = ["a", "b", "c"] for i in range(len(data)): print(i, data[i]) # 使用enumerate() for idx, val in enumerate(data): print(idx, val)
zip()
将多个迭代对象聚合在一个元组中,然后返回它。zip 可以接受任何类型的可迭代对象,例如文件、列表、元组、字典、集合等
city_list = [list(z) for z in zip(df_tmp_1['地区'], df_tmp_1['地区收入倍数'])] 将两个一元数据序列合并成二元数据(如抽取两列数据,作为二维坐标的横纵坐标),合并后的对象还是list
将两个列表转化为字典对象,用dict创建字典对象,用zip函数将两个list分别作为“索引”和“数值” dict(zip(keys, values))
numbers = [1,2,3,4] characters = ['A','B','C','D'] zipped = zip(numbers,characters) print(zipped) # <zip object at 0x000001F8D8B8B848> print(list(zipped)) # [(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D')] print(tuple(zipped)) # (1, 'A'), (2, 'B'), (3, 'C'), (4, 'D')] zipped_2 = zip(numbers,characters) n , c = zip(*zipped_2) # ️ 有意思的用法。 print(n) # (1, 2, 3, 4) print(c) # ('A', 'B', 'C', 'D')
filter()
filter(func, iterable) numbers = [1,2,3,4,5,6,7,8,9,10] check_even = lambda x: x%2 == 0 # 判断是否是偶数 for i in filter(check_even,numbers): print(i) # 2 4 6 8 10
将文字存入文本文件
with open(sheetname + '-' + tmp_1.text + '-' + tmp_2.text + ".txt", mode='w', encoding='utf-8') as file: file.write(tmp_1.text + "\n" + tmp_2.text + "\n" + tmp_3.text) 使用open方法创建并打开指定文本文件,mode和encoding都要指定,便于后续文件的打开,写入字符串是可用转义字符“\n"换行
any与all
a='首先,你是一个脱离了低级趣味的人' (1)判断字符串中是否包含“任意个数指定内容” any([x in a for x in ['趣味','高级']]) --->True (2)判断字符串中是否包含“全部的指定内容” all([x in a for x in ['趣味','高级']]) --->False
data[(data.loc[:,['性能1', '性能2', '性能3']] >= 1).any(1)] --->筛选出“性能1、2、3”三列中,有任意个数取值大于等于1(即剔除三列数值全部小于1)的数据行 data[(data.loc[:,['性能1', '性能2', '性能3']] >= 1).all(1)] --->筛选出“性能1、2、3”三列中,取值全部大于等于1的数据行
系统库
OS
chdir()
os.chdir('../')改变当前工作目录
listdir()方法
list = [d for d in os.listdir()] for name in list: print(name)
for name in os.listdir(os.getcwd()): print(os.path.join(os.getcwd()) + '\\' + name)
# 在当前目录下的指定子目录下遍历文件清单存入 narray(或者list)对象 # 进一步遍历文件名集合的方式,逐一加载数据并存入制定Datafram对象 pre_process_files = os.listdir(os.getcwd() + r"\01-各社保主体缴费预处理" for file_num in range(0, len(pre_process_files)): filename = os.getcwd() + "\\01-各社保主体缴费预处理\\" + pre_process_files[file_num] df_sum = df_sum._append(pd.read_excel(filename, header=0, dtype={'单位编号': str, '费款所属期起': str, '征集通知流水号': str, '社保流水号': str}))
mkdir()方法
# 创建目录,单层用mkdir、多层用makedires mkdir("/path/to/new/directory")
path
abspath(): 获取绝对路径
basename(): 获取文件名
dirname(): 获取目录名
exists():判断参数对应的目录或文件是否存在,存在返回True,不存在返回False
getsize(): 获取文件大小
getmtime(): 获取最后修改时间
isfile(): 判断是否为文件
isdir(): 判断是否为目录
islink(): 判断是否为符号链接
join():os.path.join(os.getcwd(), 'XX报告.docx')
split(): 分割目录和文件名
splitext():获取文件的扩展名
反馈一个2个元素的数组对象,0表示文件名、1表示扩展名 file_extension = os.path.splitext(file_name)[1]
getcwd():获取当前程序工作目录
remove()方法
默认删除程序运行文件夹内的指定名称的文件或文件夹
removedirs()方法
删除目录及其内部文件
rmdir()方法
删除目录
rename()
文件(夹)重命名
os.rename(含完整路径和后缀的原文件名,含路径及后缀的新文件名)
两个参数不含完整路径的,视作运行程序的当前文件夹,指定完整路径的按指定路径【实测同一目录下没问题】
stat()
os.stat(FILE_PATH) 获取文件属性
walk()
遍历目录并返回根目录、子目录、文件名的集合
pathlib
from pathlib as Path # 判断文件是否存在 if Path("file.txt").exists() # 获取文件大小 file_size = Path("file.txt").stat().st_size # 删除文件 Path("file.txt").unlink()
Collections
Counter()
# 检查两个字符串是否由同样的组成元素 import collections x = "abcde" y = "dbcea" print(collections.Counter(x) == collections.Counter(y)) --->True
shutil
copy()
# 将文件从一个位置复制到另外一个位置 shutil.copy(basefile_model, basefile_path + '\\' + '企业年金交接单据.xlsx')
move()
移动文件 shutil.move("source.txt", "desctination.txt")
rmtree()
shutil.rmtree(directory)删除目录及其内容文件
zipfile
提供了对ZIP压缩文件的创建、读取和解压缩的功能
import zipfile # 创建ZIP压缩文件 with zipfile.ZipFile('archive.zip', 'w') as zip: zip.write('file.txt') # 解压缩ZIP文件 with zipfile.ZipFile('archive.zip', 'r') as zip: zip.extractall('destination_folder')
configparser
提供了对INI文件的读写操作的功能,用于处理配置文件
import configparser # 读取配置文件 config = configparser.ConfigParser() config.read('config.ini', encoding='ANSI') value = config.get('Section', 'Option') # 写入配置文件 config = configparser.ConfigParser() config['Section'] = {'Option': 'Value'} with open('config.ini', 'w') as file: config.write(file)
set()
# 可以清除列表对象中的重复元素 x = [1, 2, 2, 3, 4, 5, 5] print(set(x)) --->{1, 2, 3, 4, 5} # 判断列表对象中是否有重复元素,list包含元素数量与list唯一值数量一致,说明list对象中无重复值 if len(x)==len(set(x))
# set方法返回值是一个集合(集合中不允许有重复元素),有别于一般字符串,有多重衍生功能 x - y 相当“在x里,但不在y里的” x & y 相当“在x和y里都有的” x | y 相当“在x或y里有的” 特别注意的是以上“集合计算”会剔除 逻辑True 元素
未深入使用库
requests
get
r = requests.get('https://www.baidu.com') 返回一个responce对象
向网页请求中传递参数包 data = {'name':'John', 'age':20} r = request.get('https://……',params=data)
# 通过观察网址https://www.baidu.com/s?wb=python,可以视作在指定网址下,当wb对象的值为python时的“查询结果”,可以通过参数的方法打开指定页面 r
post
发送一个post通讯请求
爬取二进制数据
# open(文件名,数据格式) # 文件名:准备写入数据的文件名[可以含路径],需要指定后缀名。数据格式,'wb'表示二进制 import requests r = requests.get('https://www.baidu.com/favicon.ico') with open('favicon.ico','wb') as f: f.write(r.content)
文件上传
import requests files = {'file': open('favicon.ico', 'rb')} r = requests.post('http://……', files=files)
responce
type(responce):查看返回对象的数据类型
responce.status_code
状态码,用于判断网页请求是否成功响应,以及目前网络状态 #信息性状态码 100:('continue'), 101:('switching_protocols'), 102:('processing'), 103:('checkpoint'), 122:('uri_too_long','request_uri_too_long'), #成功状态码 200:('ok','okay','all_ok','all_okay','all_good','\\o/','√'), 201:('created'), 202:('accepted'), 203:('non_authoritative_info','non_authoritative_information'), 204:('no_content'), 205:('reset_content','reset'), 206:('partial_content','partial'), 207:('multi_status','multiple_status','multi_stati','multiple_stati'), 208:('already_reported'), 226:('im_used'), #重定向状态码 300:('multiple_choices'), 301:('moved_permanently','moved','\\o-'), 302:('found'), 303:('see_other','other'), 304:('not_modified'), 305:('user_proxy'), 306:('switch_proxy'), 307:('temporary_redirect','temporary_moved','temporary'), 308:('permanent_redirect'), #客户端请求错误 400:('bad_request','bad'), 401:('unauthorized'), 402:('payment_required','payment'), 403:('forbiddent'), 404:('not_found','-o-'), 405:('method_not_allowed','not_allowed'), 406:('not_acceptable'), 407:('proxy_authentication_required','proxy_auth','proxy_authentication'), 408:('request_timeout','timeout'), 409:('conflict'), 410:('gone'), 411:('length_required'), 412:('precondition_failed','precondition'), 413:('request_entity_too_large'), 414:('request_uri_too_large'), 415:('unsupported_media_type','unsupported_media','media_type'), 416:('request_range_not_satisfiable','requested_range','range_not_satisfiable'), 417:('expectation_failed'), 418:('im_a_teapot','teapot','i_am_a_teapot'), 421:('misdirected_request'), 422:('unprocessable_entity','unprocessable'), 423:('locked'), 424:('failed_dependency','dependency'), 425:('unordered_collection','unordered'), 426:('upgrade_required','upgrade'), 428:('precondition_required','precondition'), 429:('too_many_requests','too_many'), 431:('header_fields_too_large','fields_too_large'), 444:('no_response','none'), 449:('retry_with','retry'), 450:('blocked_by_windows_parental_controls','parental_controls'), 451:('unavailable_for_legal_reasons','legal_reasons'), 499:('client_closed_request'), #服务端错误状态码 500:('internal_server_error','server_error','/o\\','×'), 501:('not_implemented'), 502:('bad_gateway'), 503:('service_unavailable','unavailable'), 504:('gateway_timeout'), 505:('http_version_not_supported','http_version'), 506:('variant_also_negotiates'), 507:('insufficient_storage'), 509:('bandwidth_limit_exceeded','bandwith'), 510:('not_extended'), 511:('network_authentication_required','network_auth','network_authentication'),
responce.encodeing:查看编码格式
responce.headers:查看响应头
responce.text:查看网页内容
responce.cookies
responce.json()
如果返回对象判断为str且符合json规范的,可以通过此方法将数据转为字典格式
header
在get方法中添加header参数,可以让对方服务器认为当前的数据请求是从指定的浏览器中发起,是一种基础的反反爬虫方法
r = request.get(url, headers=header)
cookies
Sessioin
SSL证书验证
代理设置
超时设置
身份验证
HTTPBasicAuth r = requests.get('http://localhost:8080/manager/html', auth=HTTPBasicAuth('admin','123456')) 用户名和密码正确,返回的状态码为200,不正确返回的状态码为401 r = requests.get('http://localhost:8080/manager/html', auth=('admin','123456')) 上面的代码会“隐性”调用HTTPBasicAuth类
Numpy
where()
df[“column_name”] = np.where(df[“column_name”]==”some_value”, value_if_true, value_if_false) 通过调用Numpy库的方法,读取dataframe对象后,根据指定列的逻辑判断结果赋值
openpyxl
引用库和类
from openpyxl import Workbook '从openpyxl模块导入Workbook类 book = Workbook() 'book相当于工作簿对象,默认只有一个工作表
工作簿对象
active方法:调取活动工作表,返回Worksheet对象
caculation:返回openpyxl.workbook.properties.CalcProperties对象
chartsheets:返回图表工作表名的对象
close():使用完工作簿对象,保存(save)后还要关闭释放内存(close)
copy_worksheet():创建一个工作簿中所有表的副本
source = wb.active target = wb.copy_worksheet(source)
create_sheet("工作表名",位置参数) '位置参数采用阿拉伯数字形式,默认添加在最后一张表,0表示在最前面即现有第一张工作表前插入一张表,-1表示在倒数第2张表的位置插入一张新表
data_only:bool类型,是否只读取数值
defined_names:已命名区域
delete_sheet(sheet):删除指定的工作表
get_sheet_names(),将工作簿内所有工作表名存入数组,方便后续通过“切片”方式对工作表名称进行进一步处理
get_sheet_by_name(工作表名)
已作废的获取工作表对象的一种方法,不影响代码运行但调试时有提示,与sheet = book.worksheets[0]按位置顺序取表功能、sheet = book.worksheets["工作表名"]一样
目前使用的方法workbook["工作表名"]
load_workbook():book = openpyxl.load_workbook('sample.xlsx') '打开在main.py相同路径下的文件,将book设为工作簿对象
openpyxl打开工作簿文件
path:字符类型,返回xml格式文件的保存位置
properties:工作表属性,返回openpyxl.packaging.core.DocumentProperties对象
read_only:bool类型,数据是否只读
remove_sheet(sheet对象):book.remove(book['sheet1'])从工作簿里删除指定工作表
save("文件名.后缀名") '按指定文件名保存到 main.py相同目录下
sheetnames:返回工作表名的列表格式数据
style_names:一个列表,存储了近50项属性
views:返回一个列表对象,存储了openpyxl.workbook.views.BookView对象
worksheets:工作表数量,用数字索引工作表
工作表对象
active_cell:活动单元格
append() :追加数据
rows = ( (1,2,3), (4,5,6), (7,8,9)) for row in rows: sheet.append(row) 由序列组成的数组,作为对象增加到工作表现有数据末尾追加数据
cell
获取单元格数据 value = ws.cell(row=1, column=1).value
cols
与rows类似,用于迭代访问对象以达到遍历数据的目的
for col_cells in ws.cols: for cell in col_cells: print(cell.value, end=" ") print() # 换行
column_dimensions[]:列区域,sheet.column_dimensions["B"].width=20,调整B列列宽为20
delete_rows(): sheet.delete_cols() :删除行、删除列,参数为存储了数值型行序号、列序号的list对象
dimensions
dimension 可以帮助你确定工作表中实际包含数据的范围
基于数据区域的范围遍历单元格 for row in range(dimension.min_row, dimension.max_row + 1): for col in range(dimension.min_column, dimension.max_column + 1): cell = ws.cell(row=row, column=col) print(f"Cell ({row}, {col}) has value: {cell.value}")
复制数据到另外一个 from openpyxl import Workbook # 创建一个新的工作簿和工作表 new_wb = Workbook() new_ws = new_wb.active # 复制数据区域 for row in range(dimension.min_row, dimension.max_row + 1): cells = ws.row_dimensions[row].cells new_ws.append([cell.value for cell in cells[dimension.min_column - 1:dimension.max_column]])
调整列宽和行高以适应数据区域的内容 # 调整列宽 for col in ws.iter_cols(min_col=dimension.min_column, max_col=dimension.max_column, max_row=dimension.max_row): max_length = 0 for cell in col: if cell.value is not None and len(str(cell.value)) > max_length: max_length = len(cell.value) ws.column_dimensions[col[0].column_letter].width = max_length # 调整行高 for row in range(dimension.min_row, dimension.max_row + 1): ws.row_dimensions[row].height = 20 # 可以根据需要设置不同的高度
filter_sort
from openpyxl import Workbook wb = Workbook() sheet = wb.active data = [ ['Item', 'Colour'], ['pen', 'brown'], ['book', 'black'], ['plate', 'white'], ['chair', 'brown'], ['coin', 'gold'], ['bed', 'brown'], ['notebook', 'white'], ] for r in data: sheet.append(r) sheet.auto_filter.ref = 'A1:B8' sheet.auto_filter.add_filter_column(1, ['brown', 'white']) '二维表Colour列下筛选brown和white的数据列,命令只是增加了筛选条件,并未在窗口现实中应用(隐藏未筛选数据) sheet.auto_filter.add_sort_condition('B2:B8') '增加排序条件,并未明确排序规则 wb.save('filtered.xlsx')
freeze_panes
sheet.freeze_panes = 'B2' '以B2单元格为窗口冻结的起点
insert_rows()和insert_cols()
# 在第二行上方插入一行 sheet.insert_rows(2) # 在第2列前方插入一列 sheet.insert_cols(2) :插入行与列
iter_rows:sheet.iter_rows ,以元组形式输出所有行
for row in sheet.iter_rows(): a = row[3].value
iter_columns属性:sheet.iter_columns,以元组形式输出所有列
merge_cells():
sheet.merge_cells('A1:B2') '合并单元格,除了左上角的单元格内容,其他单元格内的所有数据都将删除
ws.merge_cells(start_row=1, start_col=1, end_row=1, end_col=2)
max_column属性:最大列
for i in range(1, sheet.max_column + 1): sheet.cell(row=1, column=i).alignment = Alignment(horizontal="center", vertical="center", wrap_text=True) 循环访问第一行的各列,设置对齐格式
max_row属性:最大行,多用于循环语句中控制遍历行数据、列数据时的行指针
merged_cells:返回所有合并单元格的区域描述,如A3:B5
min_column属性:最小列
min_row属性:最小行
page_margins:返回openpyxl.worksheet.page.PageMargins对象
page_setup:返回openpyxl.worksheet.page.PrintPageSetup对象,页面设置
parent:返回表格所属Workbook对象
print_area:字符串,用区域描述打印区域
print_title_cols:打印标题列
print_title_rows打印标题行
rows:
以“生成器”的方式,创建“行数据”,方便迭代调用以达到遍历数据的目的,不支持直接访问特定行列目标单元格
# 使用 rows 属性迭代行 for row_cells in ws.rows: for cell in row_cells: print(cell.value, end=" ") print() # 换行
row_dimensions[]:行区域,sheet.row_dimensions[2].height = 20,设置第2行的行高为20
sheet_properties.tabcol:sheet.sheet_properties.tabColor = "0072BA" '指定工作表的背景色
selected_cell:选中区域的字符串描述
sheet_properties:返回openpyxl.worksheet.properties.WorksheetProperties对象
sheet_state:有两个选项hidden和visible
sheet_view
show_gridlines:bool数值,是否显示网格线
tables:
title:sheet.title '展示工作表名称
实操代码
赋值
sheet['A1'] = 赋值 '方法1 sheet.cell(row=1,column=1).value = 赋值 '方法2 sheet.cell(row=1,column=1,value=赋值)
读值
a1 = sheet['A1'] a1 = sheet.cell(row=2,column=2) print(a1.value) '这里的a1、b2相当vba里的range对象 a1 = book['Sheet1'].cell(row=2,column=2).value row10 = sheet[10] '读取第10行 row_range = sheet[5:10] ‘读取第5-10行 cells = sheet['A1':'B6'] 读取一个区间 'iter_rows(起始行,起始列,终止行,终止列)方法 for row in sheet.iter_rows(min_row=1, min_col=1, max_row = 6, max_col = 3): for cell in row: '视作cell为单元格对象,在row行对象中逐一枚举后打印 print(cell.value,end=" ") '数据之间用空格隔断展示 print() '打印换行 'iter_cols(起始行,起始列,终止行,终止列)方法 for row in sheet.iter_cols(min_row=1, min_col=1, max_row = 6, max_col = 3): for cell in row: '视作cell为单元格对象,在“行-列”转换后的row行对象中逐一枚举后打印 print(cell.value,end=" ") '数据之间用空格隔断展示 print() '打印换行
工作表复制
copy_sheet = book.copy_worksheet(book['Sheet1']) copy_sheet.title = 'Sheet1副本'
工作表新增
for i in range(1,32): book.create_sheet('7月' + str(i)) + '日') 以7月日期为工作表名,新建31个工作表
工作表名称批量修改
sheet_list = book.worksheets for i in sheet_list: i.title = '北京' + '-' + i.title '给每个工作表的名称增加‘北京-’前缀 if i.title.split('-')[0] != '上海': new_sheet = book[i.title] book.remove(new_sheet) '删除工作表名不以上海开头的工作表
单元格对齐方式
Alignment(horizontal='',vertical='',text_rotation='',wrap_text=False,shrink_to_fit=False,indent=0) 参数 horizontal:justify两端对齐,fill填满对齐,left左对齐,general一般对齐,right右对齐,center居中对齐,distributed分散对齐 vertical:bottom靠下,justify两端对齐,center居中,distributed分散对齐,top靠上 text_rotation:输入旋转角度 wrap_text:True表示自动换行,False表示否 shrink_to_fit:True表示自适应填充 indent:输入需要缩进的字符数
单元格对象
赋值
cell.value = 'Sunny day'
cell = sheet.cell(row = 1,column = 3),需要将row=、column=两个表述带上 datavalue = sheet.cell(row=1, column=3).value
赋公式
cell.value = "=SUM(A1:B6)",只需要在输入的字符内容中完整写入公式即可
对齐方式
cell.alignment = Alignment(horizontal='center', vertical='center') '参数采取水平、垂直两个方向分别指定对齐方式确定。 其中:Alignment是openpyxl.styles模块中的类,引用方式from openpyxl.styles import Alignment
Border对象
Border(top='',bottom='',left='',right='',diagonal='') top、bottom、left、right四个参数的取值都是Side对象,Side对象的描述均为Side(border_style='',color="0000FF"),即边框格式和颜色,边框格式的可选参数有dashDot、dashDotDot、dashed、dotted、double、hair、medium、mediumDashDot、mediumDashDotDot、mediumDashed、slantDashDot、thick、thin
from openpyxl.styles.borders import Border,Side cell.border = Border(left=Side(style='thin'), right=Side(style='thin'),top=Side(style='thin'),bottom=Side(style='thin'))
Font对象
Font(name="字体名称",size=20,color="0000FF",bold=True,italic=True,strike=None,underline=None) color:16进制rgb表示 italic:是否斜体 strike:是否使用删除线 underline:是否使用下划线
cell.font = cell.font.copy(bold=True) ,单元格格式在现有基础上字体加粗
PatternFill:单元格填充颜色
from openpyxl.styles import colors, PatternFill # 设置单元格A1的颜色为黄色 yellow_fill = PatternFill(start_color='FFFF00', end_color='FFFF00', fill_type='solid') ws['A1'].fill = yellow_fill 或者 fill_mode = PatternFill('solid', fgColor='f8c600') sheet1.cell(row=2, column=8).fill = fill_mode
cell.column_letter 输出列名
cell.col_idx cell.column :输出列号
cell.row 输出行号
cell.coordinate 输出坐标
ailgnment:对齐方式
border:边框模式
font:字体属性
hypetlink:超链接
is_date:是否日期数据
protectiong:保护属性
style:样式
style_id:样式编码
插入图像
from openpyxl import Workbook from openpyxl.drawing.image import Image '增加引用openpyxl.drawing.image模块中的Image类 book = Workbook() sheet = book.active img = Image("icesid.png") '引用添加的图片对象在main.py目录下的文件名 sheet['A1'] = 'This is Sid' '单元格赋值 sheet.add_image(img, 'B2') '图像添加位置 book.save("sheet_image.xlsx")
插入图表
仅支持在工作表中增加条形图,折线图,面积图,气泡图,散点图和饼图,工作簿中的图表会被删除
from openpyxl import Workbook from openpyxl.chart import ( Reference, Series, BarChart ) book = Workbook() sheet = book.active '以下创建二维数据源 rows = [ ("USA", 46), ("China", 38), ("UK", 29), ("Russia", 22), ("South Korea", 13), ("Germany", 11) ] for row in rows: sheet.append(row) '定义第2行开始为图表数据源 data = Reference(sheet, min_col=2, min_row=1, max_col=2, max_row=6) '定义第1行为图表数据序列的名称 categs = Reference(sheet, min_col=1, min_row=1, max_row=6) chart = BarChart() chart.add_data(data=data) '增加数据源 chart.set_categories(categs) '增加数据序列名称 chart.legend = None chart.y_axis.majorGridlines = None chart.varyColors = True chart.title = "Olympic Gold medals in London" sheet.add_chart(chart, "A8") '添加设置完的图表到指定单元格 book.save("bar_chart.xlsx")
实操代码
将字符串输入文本文件
fp = open('D:\test.xlsx','a+') 'a+表述按读写模式打开文件 print('hello world',file = fp)
打开文件并逐行显示数据
from openpyxl import load_workbook wb = load_workbook(r'测试.xlsx') ws = wb.active for row in ws.values: print(row)
将数据存入excel文件
from openpyxl import Workbook wb = Workbook() ws = wb.active ws.append(['姓名', '学号', '年龄']) ws.append(['张三', 'M111', '17']) wb.save(r'测试.xls')
数据统计
import openpyxl import statistics as stats book = openpyxl.load_workbook('测试.xlsx', data_only=True) sheet = book.active rows = sheet.rows values = [] '定义数组对象 for row in rows: for cell in row: values.append(cell.value) '将所有数据存入数组,留备统计 print("Number of values: {0}".format(len(values))) print("Sum of values: {0}".format(sum(values))) print("Minimum value: {0}".format(min(values))) print("Maximum value: {0}".format(max(values))) print("Mean: {0}".format(stats.mean(values))) print("Median: {0}".format(stats.median(values))) print("Standard deviation: {0}".format(stats.stdev(values))) print("Variance: {0}".format(stats.variance(values)))
将字符串的网址转为可点击的超链接
if book["清单"].cell(row=row_id, column=6) is not None: book["清单"].cell(row=row_id, column=6).value = '=HYPERLINK("' + str(book["清单"].cell(row=row_id, column=6).value) + '")' 直接在单元格value属性中传入公式,能够被识别为一般公式
xlwings
Excel实例
app = xw.App(visible=False, add_book=False) book = xw.Book('test.xlsx') sheet = book.sheets[0] #sheet=book.sheets['XXX'] value = sheet.range['A1'].value #读取单元格数据 sheet.range('A1').value = 'A' #赋值单元格 sheet.range(1,5).value = ['总分', '平均分'] #试试效果再用 sheet.range((2,5)).expand('down').value = [row[4:] for row in data[1:] #代码需要测试后再使用
工作簿对象
属性
app: 返回与工作簿关联的 Application 对象,允许你访问 Excel 应用程序的属性和方法。
name: 工作簿的名称。
fullname: 工作簿的完整文件路径
readonly: 指示工作簿是否处于只读模式
active_sheet: 返回当前激活的工作表。
sheets: 返回一个包含工作簿中所有工作表的列表。
activate(): 激活工作簿窗口。
方法
app.books.active()
app.books.add(): 创建一个新的工作表,并返回 Sheet 对象
close(saving=None): 关闭工作簿。saving 参数可以是xlwings.constants.WorkbookSave.SAVE 或xlwings.constants.WorkbookSave.DONTSAVE,用于指定是否保存更改
connect(): 连接到一个已经打开的工作簿。
app.books.open('路径')
打开已有文件
save(): 保存工作簿。如果工作簿是新创建的,还可以指定文件路径和格式
save_as(filename, file_format=None): 将工作簿另存为指定的文件名和格式。
disconnect(): 断开与工作簿的连接,释放资源。
get_address(start_row=1, start_column=1, absolute=False): 获取当前工作簿的文件路径和名称的链接地址
set_tab_color(color): 设置工作簿中当前激活工作表的标签颜色。
事件
on_change: 可以注册一个函数,当工作簿中的单元格被更改时触发。
on_selection_change: 可以注册一个函数,当工作簿中的选定区域更改时触发
工作表对象
获取对象:
属性
方法
获取默认活动工作表:sheet=wb.sheets.active
按索引需要获取工作表:sheet=wb.sheets[0]
按工作表名称获取工作表:sheet=wb.sheets['sheetname']
新建工作表,默认激活,默认位置为第一张:sheet = wb.sheets.add()
新建工作表,激活,并指定插入位置(相对指定工作表对象之后):sheet=wb.sheet.add('新建表名', after=sheet_ori)
单元格对象
读取单元格数据
str_a = sheet.range("A1").value
str_b = sheet.range(1, 1).value
# 读取二维区域的数据 str_a1_c4 = sheet.range("A1:C4").options(ndim=2).value
str_a1_c4 = sheet.range((1, 1),(4, 3)).options(ndim=2).value
写入单元格数据
赋单一值:sheet.range("A1").value = 'str_a'
赋单一值:sheet.range(1, 1).value = 'str_a'
赋连续值,这个写法是纵向(列方向)写入数据:sheet.range("A1").value =[1, 2, 3]
#将A1,B1,C1单元格的值存入list1列表中 list1=shtee.range('A1:c1').value # 在A1、B1、C1单元格内写入数据1、2、3 sheet.range('A1').options(transpose=True).value=[1,2,3]
range
指定区域的基础方式
xw.Range('A1')、xw.Range('A1:A3')、xw.Range((1,1))
xw.Range((1,1),(3,3))、xw.Range(xw.Range("A1"),xw.Range("C3"))
xw.Range('rangename')
rng = xw.Book().sheets[0].range("A1:D5") rng[0, 0] #相当A1单元格,类似dataframe的loc访问方式
获取一个区域作为对象 sheet.range('A1').value =[[1,2],[3,4]] rng1 =sheet.range('A1').expand('table') rng2 = sheet.range('A1').options(expand='table') print(rng1.value) #[[1.0,2.0],[3.0,4.0]] print(rng2.value) #[[1.0,2.0],[3.0,4.0]] sheet.range('A3').value =[5,6]print(rng1.value) #[[1.0,2.0],[3.0,4.0]] print(rng2.value) #[[1.0,2.0],[3.0,4.0],[5.0,6.0]] 直接调用expand获取延伸区域对象的,是固定(按赋值时的区域限定),用options(expand='table')赋值的话,视作在原区域上动态拓展的对象
rng.add_hyperlink(r\'www.baidu.com\',\'百度\',提示:点击即链接到百度\')
获取当前区域地址:rng.address或rng.get address()
清除内容:rng.clear contents()
清除格式和内容:rng.clear()rng.clear()
取得range的背景色,以元组形式返回RGB值:rng.color
设置range的颜色:rng.color=(255,255,255)
清除range的背景色:rng.color=None
获取公式或者输入公式:rng.formula='=SUM(B1:B5)'
数组公式:rng.formula_array
获得单元格的绝对地址: rng.get_address(row_absolute=True, column_absolute=True,include_sheetname=false, external=false)
获得列宽:rng.column_width
返回range的总宽度:rng.width
获得range的超链接:rng.hyperlink
获得range中右下角最后一个单元格:rng.last_cell
range平移:rng.offset(row_offset=0,column_offset=0)
range进行resize改变range的大小:rng.resize(row_size=None,column_size=None)
range的第一行行标:rng.row
行的高度,所有行一样高返回行高,不一样返回None:rng.row_height
返回range的总高度:rng.height
返回range的行数和列数:rng.shape
返回range所在的sheet:rng.sheet
返回range的所有行:rng.rows
range的第一行:rng.rows[0]
range的总行数:rng.rows.count
返回range的所有列:rng.columns
返回range的第一列:rng.columns[0]
返回range的列数:rng.columns.count
所有range的大小自适应:rng.autofit()
所有列宽度自适应:rng.columns.autofit()
所有行宽度自适应:rng.rows.autofit()
给单元格增加注释:rng.api.AddComment('text')
调整单元格格式
rng.api.NumberFormat=“@” #设置为文本格式
rng.api.NumberFormat=“0.” #设置为小数格式
rng.api.NumberFormat=“yyyy-mm-dd" #设置为""连接的日期格式
rng.api.NumberFormat ="8%" #设置为百分比
设置单元格大小
sheet.autofit() #自动调整单元格大小。注:此方法是在单元格写入内容后,再使用,才有效。
sheet.range(1,4).column width=5 # 设置第4列 列宽。(1,4)为第1行第4列的单元格
sheet.range(1,4).row height =20 #设置第1行 行高
设置单元格字体格式
设置单元格的填充颜色:cell.color=255,200,255
设置字体的颜色:cell.api.Font.ColorIndex=3
设置字体的大小:cell.api.Font.size =24
设置为粗体cell.api.Font.Bold = True
cell.api.HorizOntalAlignment= -4108 #-4108水平居中。-4131靠左,-4152 右。
cell.api.VerticalAlignment=-4130 #-4108 垂直居中(默认)-4160靠上,-4107下,-4130自动换行对齐。
cell.api.NumberFormat='0.00'#设置单元格的数字格式
单元格边框
cell.api.Borders(num).LineStyle = num_line # num,7表示左边框、8表示上边框、9表示下边框、10表示右边框;11表示内部垂直线,12表示内部水平线 # num_line,1表示直线、2表示虚线、5表示双点划线、4表示点划线 # num=5、num_line=1,表示左上至右下的直斜线;num=6、num_line=1,表示左下至右上的直斜线
cell.api.Borders(num).Weight,表示线条粗细程度
单元格合并与拆分
rng.api.merge() 合并单元格
rng.api.unmerge()拆分单元格
插入行与删除行
rng.api.EntireRow.Delete()删除rng对应数据行
rng.api.Rows(num).Insert() 在指定行之前插入行,原行下移
插入列与删除列
rng.api.EntireColumn.Delete() 删除rng单元格的所在列
rng.api.Columns(num).Insert() 在rng指定列之前插入列,原列右移
最大数据行列(非连续)
cell = sheet.used_range.last_cell cell.row # 最大行,不考虑连续数据 cell.column # 最大列,不考虑连续数据
cell = sheet.range("a1").expand("down") max_rows = cell.rows.count
数据排序
sheet.range('a2',(rows,columns)).api.Sort(Key1=sheet.range("C2").api, Order1=1) # Order1的参数,1表示升序、2表示降序,排序关键字段为“C列”,因为第一行为标题行,所以从“A2"开始排序
删除重复数据
# RemoveDuplicates(3)为按第3列内容进行删除重复项。 sheet.range('a2',(rows,columns)).api.RemoveDuplicates(3)
插入公式
# 插入公式 sheet.range('d1').formula='=sum(e1+f1)'
复制数据
#复制 a2 到 a6 之间单元格的值,粘贴到'a15'中 sheet.range('a2','a6').api.copy(sheet.range('a15').api)
跨表格复制、黏贴 my_values = sheet.range('a2: d4').options(ndim=2).value sheet.range('a1').value = my_values
关闭文件
wb.save()、wb.close()、app.quit()
清除单元格内容和格式 sheet.range('A1').clear() 单元格的列标 sheet.range('A1').column 单元格的行标 sheet.range('A1').row 单元格的行高 sheet.range('A1').row height 单元格的列宽 sheet.range('A1').column width 列宽自适应 sheet.range('A1').columns.autofit() 行高自适应 sheet.range('A1').rows.autofit() 单元格背景色(RGB)sheet.range('A1').color=(34,139,34) 清除单元格颜色 sheet.range('A1').color=None 输入公式,相应单元格会出现计算结果sheet.range('A1').formula='=SUM(A1:E1)' 获取单元格公式 sheet.range('A1')formula array
图表
示例
chart = sheet.charts.add() chart.set_source_data(sheet.range("A1:B6")) chart.chart_type="line" chart_name="Sample" chart.x_axis.title = "X_axis" chart.y_axis.tile = "Y_axis" chart.top = sheet.range("D1").top chart.left = sheet.range("D1").left chart.width = 400 chart.height = 300
requests
访问网址 url = 'http://……' rq = requests.get(url)
各种请求类型
#GET请求 requests.get("http://httpbin.org/get")
#POST请求 requests.post("http://httpbin.org/post")
#PUT请求 requests.put("http://httpbin.org/put")
#DELETE请头 requests.delete("http://httpbin.org/delete")
#HEAD请求 requests.head("http://httpbin.org/get")
#OPTIONS请求 requests.options("http://httpbin.org/get")
encoding
查看编码,rq.encodiing
headers
查看响应头,rq.headers
# 伪装User-Agent headers ={"user-agent":'Mozilla/5.0 (windows NT 10.0;Win64;x64)Applewebkit1537.36(KHTML,like Gecko)chrome/86.0.4240.198 Safari/537.36'} response = requests.get('https://www.zhihu.com/explore’, headers=headers)
headers ={"user-Agent": "Mozilla/5.0 (windows NT 10.0; win64;x64)Applewebkit/537.36(KHTML,like Gecko)chrome/54.0.2840.99 Safari/537.36"} # 这是目标url #url =https://www.baidu.com/s?wd=python #最后有没有问号结果都一样 url =https://www.baidu.com/s? # 请求参数是一个字典 wd=python kw ={'wd': 'python'} #带上请求参数发起请求,获取响应(自动搜索传入参数) response =requests.get(url,headers=headers, params=kw)
proxies
proxies ={"http": "http://124.236.111.11:80","https": "https:183.220.145.3:8080"} req =requests.get(http://www.baidu.com’,proxies =proxies)
status_code
查看状态码,rq.status_code
text
查看网页内容,rq.text
type
查看结果类型,,type(rq)
beautifulsoup4
pandas
read_excel()
pd.read_excel(r"……\XXX.xlsx",sheet_name='XXX',head=3) head参数指明了列名所在位置,head上的名称数据自动删除,head行的数据作为数据列名 sheet_name:可以用工作表名(字符串),也可以用阿拉伯数字表示第几个工作表;还可以是list对象读取多张表数据,如sheetname=[0,3,'Test5']表示第1、第4张表和表名为'Test5'的工作表(共三张) index_col:用于指定索引列,默认为None即第0列作为索引列 names:用列表(或数组)对象指定读取对象的列标题 header:通过指定具体的行索引作为数据的标题行(表列名),如传入的对象是整数的列表,则将多行作为多级列索引 usecols:默认为None(读取所有列),可以通过指定list对象读取指定列,指定列的顺序与表内数据列顺序无关,最后呈现数据仍按原相对顺序展现 skiprows:指定要跳过(不读取)的行号或文件开头要跳过的行数,=lambda x: x in [0,1,2] skipfooter:默认为0,int类型,指定从尾部起计算的要跳过(不读取)的行数 dtype:指定列的数据类型,逐一指定{'A': np.int64, 'B': str} nrows:int类型,只解析指定行数的数据
数据写入:
# 在已有数据文件中“增量写入数据: wirter = pd.ExcelWriter(r"……\XXX.xlsx", mode='a', ifsheet_exists='overlay') dataframe df.to_excel(writer, index=False, sheet_name='XXX', startrow=writer.sheet['XXX'].max_row) writer.close() #已经升级在关闭时自动保存 mode='w'方法,支持在文件不存在的情况下,新建
数据修改
将两列数据求和,计算方式可以指定(sum等)、计算方向也可以指定(axis=1表示按列求和) df['在册人数'] = df[['在岗人数','离岗人数']].sum(axis=1)
Dataframe对象
aggregate()
简称agg(),统计学词汇,是指对一组数据进行某种形式的汇总和计算,python支持的聚合统计方法有:min、max、sum、mean均值、median中位数、std标准差、var方差、count计数
append:df1.append(df2) 注意两个df对象的数据结构(列结构)
apply:
df2 = df.apply(lambda x: x.max() - x.min()) 新建一个DataFrame对象,计算各列的最大值-最小值
df2 = df.apply(lambda x: x.max() - x.min(), axis= 1) 新建一个DataFram对象,计算各行的最大值-最小值,
df_sum["日期"] = df_sum["费款所属期起"].apply(lambda x: next_month(str(x).replace("-", ""))) 可以实施较为复杂的公式计算,str(x).replace("-", "")首先剔除了指定列“费款所属期起”中的字符"-",进而运用自定义函数更新数据(含插入数据)
df['父节点'] = 's' + df['dd_id'].apply(lambda x:str(x)[1:]) 将“父节点数据列”数据替换为当前记录的‘dd_id’数据列按指定规则运算后的结果,即:字母s开头,加上dd_id列数据第2个开始至结尾的字符,组成的新字符【即将dd_id列数据首字母替换成s】
def print_row(row): print(f"Index: {row.name}, Name: {row['Name']}, Age: {row['Age']}, City: {row['City']}") df.apply(print_row, axis=1) 通过逐行应用自定义方法,达到遍历全表的效果
df['gender'] = df['gender'].apply(lambda x: 0 if x == 'female' else x) 将表内gender字段为female的数据行gender列全部修改为0
df1['省市'] = df1.loc[:, ['省市', '日期']].apply(lambda x: x["省市"] + str("-市-") + x['日期'] if x['省市'] == '北京' else x['省市'] + str("-省-") + x['日期'], axis=1) 在指定参数axis=1的前提下,可以将x视作行对象,用x['列名']代替每行数据的指定列
astype()
转换数据格式(由于数据规范性原因,不能转换的会报错)df['price'].astype('int')将数据列格式转化为int类型
df.astype({'Q1': 'int32','Q2':'int32'}).dtypes
at:df.at[5,"列名"] 返回索引号为5对应数据行的指定列名的数据值
attrs
axes
concat():
pd.concat(objects,axis=0,join='outer',ignore_index=False,keys=None,levels=None,names=None,verify_integrity=False,copy=True) 参数 objects:DataFrame或者Series axis:0或者1,默认为0,纵向合并数据 join:inner(交集)、outer(联合),默认outer ignore_index:boolean,默认为False,如果为True,不使用索引,不指定为True时会将索引一并添加,可能出现索引值重复的情况 keys:序列,默认无,使用传递的键作为最外层构建层次索引,如果是多索引,应该使用元组,会强制取消索引,在原索引前增加一列(keys传入的list对象),类似pivot,只会在首行展示下“标识”,后续同一“标识”下的其他行数据为None levels:序列列表,默认无,用于构建MultiIndex的特定级别(唯一值),否则会将从键截断 names:list,结果层次索引中的级别名称,传入keys对象后,通过该参数指定“层次索引”的列名,便于后续引用 verify_integrity:boolean,默认False,如果True将会检验连接轴是否包含重复项 copy:boolean,默认True,如果为False将不会复制数据
columns()
df.columns()查看列名
df.columns.values[10]='XXX' 修改第11列的列名为XXX df.columns.value["ori_name'] = 'des_name' 通过列名锁定并更新数据列名称
df.columns=['x','y','z'] 通过一个与列数相等的list对象,更新全部列的名称
copy():
通过copy()方法可以建立一个与原dataframe“数据隔离”的副本,df2=df1,新建的df2实际引用了df1的内存空间,会随着df1的变动而自然更新,如果不希望更新可以df2=df1.copy(),这样在另外一个内存空间建立了一个数据副本
cumsum()
计算数据的累计和
cut
df['分类标记列'] = pd.cut( x = df['销售额'],bins = [0,100,1000,10000,100000], right = false, labels = ['较差','一般','合格','优秀']) # 在分类标记列中根据销售额设置5个节点,按照right为false的划分标准,分成了4个区间档次,按照“左闭合、右开放”的原则 #(right = True的,对应左开放,右闭合原则)将四个档次分别用制定的标签赋值描述
del:del df['待删除列名']
describe():对数据列给出摘要或描述性统计信息
不带任何参数下运行结果
遇到文本型数据:返回4个统计结果“数据条目数,唯一值数量,top,出现次数”
exclude
df.describe(exclude='number') 统计所有非数字列(如字符串)的数据,number和all必须要用括号前后围起来,其他数据类型不用加符号
include参数
df.describe(include=int)) 统计所有int型的数据 df.describe(include=[object, bool]) 统计指定类型的数据列
at
df.describe().at['std', 列名],可以读取统计维度下,指定列的数值
loc
df.describe().loc['std'] 对于数值型数据的统计结果,可以通过loc[索引名称]读取series对象,索引名称有:count、mean、std、min、25%、50%、75%、max
diff():对比对象内部的相互变化
# 通过两个list对象用合并成一个集合对象,以二维数据形式创建DataFrame对象。典型用途是日期时间为索引的数据集,调用该方法可快速计算环比变动值 df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [5, 4, 3, 2, 1]}) diff_df = df.diff(periods=1,axis=0) 效果:按照行(axis=0)方向,向后相邻1单元(periods=1)做“减发”变动计算,即本行数据减去上一行同一列数据的结果,存入新的DataFrame,由于第一行(index=0)没有“上一行”,因此新生成的DataFrame对象首行为空(NaN)
drop
依据index列的不同取值条件,删除数据行 df.drop(index=range(0,7), inplace=True)
删除行
通过loc+条件的方式,锁定series对象,调用锁定对象的index属性,依据index属性删除数据行 df.drop(index=df.loc[df['指定列']=='XXX'].index, inplace=True)
通过指定数据列名、列序号的方式删除数据 df.drop(df.columns==['ID','销量']) df.drop(df.columns==[[4,5]], axis=1) # 指定列名并明确axis参数值为1,表示按列删除数据,删除列 df.drop(columns=['医保单位附加', '医保单位'], axis=1, inplace=True)
删除列
dropna
df.dropna(axis=0, how="any", thresh=None, subset=None, inplace=True) 默认删除一行中只要有一个字段为空就会被删除 axis=0或"index"表示按行删除,1或"columns"表示按列删除 how:any表示只要有1个NaN,就删除整行(或列),all表示全部都是NaN才删除行(或列) thresh:int型数据,非空数据个数小于指定值时,删除行(或列) subset参数:制定删除数据方向中指定的行或列有空值时,予以删除。 inplace参数默认为false表示不替换源数据,如果设置inplace参数为True就会将数据操作更新到源数据中
df.dropna(axis=0, subset=['姓名'], inplace=True) 表示只有当姓名字段为空的数据行,才会被删除
dtypes:了解数据的性质和每列数据类型,便于数据整理
drop_duplicates
删除重复数据
df.drop_duplicates(inplace=True) 默认删除两行完全一致的重复记录,删除后会保留其中一个 inplace参数默认为false表示不替换源数据,如果设置inplace参数为True就会将数据操作更新到源数据中
df.drop_duplicates( subset('姓名') , keep = 'last') 删除姓名列重复的记录,默认删除后只保留第一次出现重复姓名的行,之后重复行均被删除,不论重复行其他字段情况。 通过给keep赋值为last也可以选择保留重复记录中的最后一行,keep参数默认值为first,所以默认保留重复记录的第一行
df_dup = df.loc[df.duplicated('姓名') == False , :] 快速定位非重复数据
duplicated()
df.duplicated().any()查看是否存在重复数据
empty
expanding
数据累计计算
explode()
将一行数据拆分成多行 result = df.explode('Names')
ffill():根据前一行或列的数值,向空白值位置填充数据
df_cftc["发薪机构"].ffill(axis=0, inplace=True)
fillna()
fillna(value=None,method=None,axis=None,inplace=False,limit=None,downcast=None,**kwargs) value:用于填充空值的新数据 method:默认None,backfill或bfill表示用空白值后面的数据(是后面一行还是后面一列,看axis参数)填充,pad或ffill表示用空白值前面的数据(是前面一行还是前面一列,看axis参数) axis:0表示按行维度配合method选定方式填充空白值,1表示按列维度 inplace:原地替换 limit:int型参数,未指定method方式下,控制填充数量;指定method,控制每段连续空白值的填充数量
用指定值填充全部空白数据 df.fillna(value=0, inplace=True)
filter():针对数据列名称和索引字段开展应用数据筛选
参数中regex通过正则表达式约束筛选条件,like视作包含特定字符的通配符约束对象,axis确定是在列还是行对象中应用以上约束 df.filter[items=['工号', '姓名']) 相当于筛选了工号、姓名两列数据 df.filter(regex='收入', axis=1) 按列筛选对象,列名中包含'收入'两个字的数据列被选中 df.filter(regex='收入$', axis=1) 以'收入'两字结尾的数据列名称,被筛选中 df.filter(like='2', axis=0) 索引含有'2'的行被筛选中 筛选‘索引中以字符2开头'且'列名有字符Q'的数据对象(单列,可能多行) df.filter(regex='^2', axis=0).filter(like='Q', axis=1)
flags
groupby
db.groupby('客户分类').count() 按客户分类分组后计算数量,count的位置可以用其他统计函数代替,如sum、mean等
db.groupby('客户分类').aggregate({'销量':'sum','ID':'count'}) 按照客户分类后,按销量求和、按ID计数
df2 = df1.groupby(['发薪机构','月份']).aggregate({'在岗员工(人)':'sum','离岗员工(人)':'sum','工资总额':'sum'}) df2.reset_index("工号") 单一字段分组可能还有用,2个及以上字段分组后索引列必然无效了,需要重新设置索引
df_sum_4.loc[df_sum_4['养老保险个人额度'] != 0, :].groupby(by='月份')['工号'].count() 分组计算后的对象,数据类型变为Series,分类字段进入index,单一计数结果作为数据存储
“查找df表单中,员工最后一月出现的记录”,查询员工最后在职发薪状态,获取岗位类型、薪级、岗位名称等字段【前提是明细数据按照月份升序排列,这样的最后一行数据才是最后一个月的数据】 df.groupby('工号').tail(1)
# 分组筛选数据 # 按品种汇总,筛选指定字段均值大于15的数据结果 result_filter = df.groupby('Category').filter(lambda x:x['value'].mean() > 15)
head():df.head(5) 视作调取行索引0-4的前5行数据
iat:与loc和iloc的关系类似,iat与at是一组同样的读取对象数值的方法,df.iat[0,5]通过数值的方式,返回索引列数值为0的第5列对象数值
idxmin
查找最小值所在列的列名和序号
idxmax
iloc
df.iloc[行索引, 列索引],依靠数字的位置索引调取元素,从0起算含首不含尾。
df.iloc[0:13,:] 表示第1行到第12行,冒号指代所有列
df.iloc[:,[0,4]] 表示所有行,第1列和第5列
对于每列设置规范表头的数据表,可以用iloc快速锁定对象 print(df[df.iloc[:,1]=='2022年10月']) 列索引为1数据列中取值为'2022年10月'的数据行 print(df[df.iloc[:, 1]=='2022年10月'].iloc[:, 1:5]) 可以通过iloc不断缩小表格范围,聚焦目标数据
index
info():用于快速查看表格的列数、列标签、列数据类型、内存使用情况、范围索引以及每列单元格数(非空),为后续数据处理做准备
insert()
在指定位置(第0列)插入一列(列名为日期,数据全部用date填充),再用append、extend等方法增加数据 df.insert(loc=0, column='日期', value=date)
isnull():db.isnull().sum() 返回表格各列中空值数量
iterrows():
# 方法返回一个迭代器,按行遍历表格,返回索引及本行内各列数据 for index, row in df.iterrows(): print(f"Index: {index}, Name: {row['列名1']}, Age: {row['列名2']}, City: {row['列名3']}")
itertuples()
for row in df.itertuples(): print(f"Index: {row.Index}, Name: {row.Name}, Age: {row.Age}, City: {row.City}") 比apply、iterrows方法效率更高,通过元组对象提供访问接口
lambda
df.工号[lambda s:max(s.index)] dataframe对象中索引列数值最大的那行数据中,工号字段的数值
# 将工号列强制转换为6位字符并对长度不足的字符自动在前方补0 df_pending['工号'] = df_pending['工号'].apply(lambda x: "0"*(6-len(x)) + x)
# 更新 付款月份 数据列 df_sum["实际付款月份\n例:202301"] = df_sum["费款所属期起"].apply(lambda x: next_month(str(x).replace("-", "")))
# 通过lambda简化数据多条件筛选条件 fruit2 = fruit.loc[fruit.价格.apply(lambda a:10<=a<=20)].loc[fruit.数量.apply(lambda s:70<=s<=100)]
loc
df.loc[:,'工号'] 依靠列表对象枚举的方式调取数据,第一个参数用冒号代替,相当筛选指定列 df.工号 能达到同样的效果,返回一个Series对象,dataframe.列名的方式可以选取单一列,多用于多条件筛选中简化代码 df.loc[:,:'工号'] 选取所有行,只选择工号列及之前的数据列,“冒号”实际用于表示一个范围,如两侧全部缺失则表示“全选”行或者列
dataframe = df.loc[df["级别"]=='一级',:] 将表内“级别”列的数据中等于“一级”的行全部选中
df.loc[:,['销售渠道','平均销售单价'] 将表内标售渠道和平均销售单价两列选中
df.loc[df["销售渠道"].isin(["淘宝","天猫"]),['销售渠道','销售数量','销售单价','销售额'] 将表内“销售渠道”是“淘宝、天猫”数据,对应的'销售渠道','销售数量','销售单价','销售额'予以选中,isin为判断时候在参数内的逻辑语句
df[~df["销售渠道"].isin(["京东","拼多多"])],相当选取“销售渠道不是京东、拼多多”的数据行
df.loc[len(df)]= [……] 在df对象的最后一行追加数据
将指定列中的空白数据填充为单一值
df_detail_lastmonth.loc[df_detail_lastmonth['岗位名称'].isnull(), '岗位名称'] = '无'
df.loc[index, 'column'],通过索引和列名的方式也可以定位数据元素了
多条件筛选数据时,可用的逻辑运算符:&:与,|:或,~:非
map():将对象中所有元素按照指定的方法处理一遍
利用str.strip可以清除字符串内的特殊字符(如前后方空格,字符串内转义字符),清除数据列中的无效空格 df['city']=df['city'].map(str.strip)
替换表格数据,df['Status'] = df['Status'].map({'Active': 1, 'Inactive': 0})
双表数据更新,根据最后一月的字段值更新全部月份 df1 = pd.read_excel("test.xlsx", header=0) # 先排序(升序),这样获取的最后一行(tail)才是最后一个月 df2 = df1.sort_values(by='日期', ascending=True).groupby('工号').tail(1) # 将获取的最后一个月数据转换为“字典对象”支撑dataframe.map()更新数据,字典对象就一个索引(工号)、一个数值(薪级) mapping_dic = df2[['工号', '薪级']].set_index('工号')['薪级'].to_dict() df1['薪级'] = df1['工号'].map(mapping_dic) print(df1.sort_values(by=['工号', '日期'], ascending=True))
min
返回各行最后一个数值型数据 df_tax_detail_2.loc[:, ['不使用优惠税率', '全部计入优惠税率', '方案36000', '方案144000', '方案300000', '方案420000', '方案660000', '方案960000']].min(numeric_only=True, axis=1)
mask
根据“Salary”列的条件进行替换 df['Bonus'] = df['Salary'].mask(df['Salary'] > 60000, 'HighBonus')
merge
pd.merge(left = df1 ,right = df2 ,on=['工号','姓名'], left_index = true ,right_index = true, how = 'inner') on:表示表格链接的数据列,也可以是left_on = '姓名',right_on = '姓名',若链接数据列是索引列(不是公共列),需要用left_index、right_index描述 how:表示连接方式inner表示两个表里同时存在的数据行作为匹配对象,参数除了inner以外,还有outer、left、right,其中:left和right分别表示以两表之一为主表匹配数据,不在主表内的数据忽略不计,主表内有但次表无的,返回NaN数据表示空白,outer表示只要两张表里有的就全部对接合并 left_on和right_on:确定连接两表的关键字段,相比“on=list,left_index,right_index”更加直观,因为链接字段很有可能不是索引字段 suffixes:重复列名的重命名,合并时预计在输出结果中按“原表列名”会重现重复列名,增加suffixes('_left','_right')参数后,会自动调整列名以区别显示 indicator:标识列,在结果数据集中的最后一列增加一列“标识”,indicator=True(列名为_merge)或者indicator='指定列名',填入“both”(标识该数据在两张表里都存在)、”left_only"(仅存在于左表)、“right_only"(仅存在于右表)
df_result = pd.merge(df_node_dd, df_node_sd, how='inner', left_on='sd_id', right_on='sd_id') 将两个表格合并,合并双方共有数据,共有的判定通过left_on和right_on的对应情况
nlargest
df.nlargest(6,'年龄') 年龄列最大的6行,这6行数据自上而下年龄逐步递减,索引仍为原df对象中的索引号,对非数值字段应用时会报错
df['A'].nlargest(2) 数据表中A列中最大的2个值,返回Series对象
nsmallest
df.smallest(6,'年龄') 年龄列最小的6行,这6行数据自上而下年龄逐步递增,索引仍为原df对象中的索引号,对非数值字段应用时会报错
df.loc[:, ['工号', '员工姓名', '应发额']].nsmallest(10, "应发额") 可以用这种方式筛选指定列最小n行数据
df['A'].nsmallest(2) 数据表中A列最小的2个值,返回Series对象
pct_change():类似diff,比较表内数据的比例变动
df = pd.DataFrame({'A': [10, 15, 20, 25], 'B': [5, 7, 10, 15]}, index=pd.date_range('2023-01-01', periods=4)) pct_change_df = df.pct_change(periods=1, fill_method='bfill', axis=0) 解读:按行(axis=0),每行向上做“减法”。 periods:指定计算百分比变化的周期数,默认为1。 fill_method:指定如何填充缺失值,可选参数包括backfill、bfill、pad、ffill、nearest等。默认为pad。 limit:指定连续缺失值的最大填充数量。默认为None。 freq:指定时间频率,用于计算时间序列数据的百分比变化。默认为None。 axis:指定计算的轴,0表示按列计算,1表示按行计算。默认为0。
pivot_table():数据透视表
pd.pivot_table(df,values=['ID','销量'], index='客户分类', columns='区域', aggfunc={'ID':'count','销量':'sum'}, fill_value=0,margins=True,dropna=None,margins_name='总计') values:需要聚合运算的列名集合 index:聚合运算的分类字段 columns:列方向的分类(列索引)集合 aggfunc:通过字典指定values对象中各项目的聚合运算方法(sum、mean、max等) fill_value:指定用于替换“透视表”中聚合运算后为空的数据(如:补0) margin:默认是False,用于控制是否添加行和列的小计数 dropna:是否删除所有条目都是NA的列,默认是True margin_name:与margin搭配使用,当margin为True时,本字段用于明确合计数的列名,如:总计 该方法返回对象是个DataFrame对象,可继续用loc等方法筛选数据
df_sum_2_pivot = pd.pivot_table(df_sum_2, index=['月份', '单位'], values=['养老保险缴费基数', '养老个人额度', '医疗个人额度', '失业个人额度'], aggfunc={'养老保险缴费基数': 'sum', '养老个人额度': 'sum', '医疗个人额度': 'sum', '失业个人额度': 'sum'}) df_sum_2_pivot.reset_index(drop=False, inplace=True) 通过给index传入list对象,透视表生成多级汇总数据,此时的索引列已经是两列的组合了,通过reset_index函数,不删除原索引的方式,可以达到拆分索引列效果
df_sum_pivot = pd.pivot_table(df_sum, index=['实际付款月份\n例:202301', '主体名称'], values=['缴费人数', '缴费基数(元)', '应缴费额(元)'], columns='征收品目', aggfunc={'缴费人数': 'mean', '缴费基数(元)': 'sum', '应缴费额(元)': 'sum'}, margins=False) index:相当Excel的行索引,当需要的索引字段是一个list对象时,在这里标识出。当索引维度为两个及以上时,透视表的行做引会被自动覆盖,有必要在实施完毕后重置索引(df.reset_index(Drop=false, inplace='True') values:相当数据透视表中待统计汇总的字段
plot()
import matplotlib.pyplot as plt # 通过DataFrame对象生成图表 fruit.plot.bar(x="水果名", y="数量", color="orange", title="水果数量显示图") plt.tight_layout() plt.show()
import matplotlib.pyplot as plt import pandas as pd
pop():
df.pop(3)删除索引为3的行数据
# 调整顺序,将指定列通过pop方法从原表格中剔除存入一个Series对象,再将该对象插入到表格中指定列位置,最终达成变更列顺序的需求 series_dw = df_sum_2_pivot.pop("主体名称") df_sum_2_pivot.insert(loc=1, column='主体名称', value=series_dw)
quality()
DataFrame.quantile(q=0.5, axis=0, numeric_only=True, interpolation='linear') 参数: q:分位值,在0至1之间取值,表示在一组从小到大排列的数据集合中“1+(数据条目数-1)×q(分位值)” axis:在{0,1,'index', 'columns'}之一取值,其中0和index相当,表示按行取数 interpolation:表示“取值方法”,可以在{'linear','lower','higher','midpoint','nearest'}之一,默认是linear 取值规则:linear:i+(j-1)×fraction,fraction采用计算分位值【“1+(数据条目数-1)×q(分位值)”】的小数部分 lower:i,较小的一个 higher:j,较大的一个 nearest:i和j中更接近的一个数值,“更接近”的定义不清楚 midpoint:(i+j)/2,相邻位置数据均值
query():调用SQL查询进行数据筛选
df.query('工号==\'550012\'') 查询表内工号为550012的数据,由于sql查询语句本身需要单引号,传入查询条件时需要转义字符参与,同时“等于”需要用Python的双等号
sample():db.sample(frac=0.25) 从数据集中抽取一个小的样本,如25%
rank()
df['销量'].rank(method='first') 排名,与排序有差异 参数: method参数有first(排名值相等的,原始位置靠前的排名在前)、min(排名值小的,位置靠前,相当升序排名)、max(与min相反)、average(当排名值有重复的,按排名值÷个数,如同一数字占据了2、3两个位置,则两个数字的排名均为2.5)、dense(排名值相等的,并列排名,后续的排名顺延,不会因为有两个2造成没人第3) axis:设置沿着哪个轴计算排名(0或者1) numeric_only:是否仅仅计算数字型的columns,布尔值 na_option:NaN值是否参与排序及如何排序(‘keep’,‘top',’bottom') ascending:设定升序排还是降序排 pct:是否以排名的百分比显示排名(所有排名与最大排名的百分比)
df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [5, 4, 3, 2], 'C': ['a', 'b', 'c', 'd'], 'D': [np.nan, 2, 3, 4]}) ranked_df = df.rank(axis=0, method='min', ascending=False, numeric_only=True, na_option='bottom', pct=False) 参数解读: method:指定排名的方式,可选参数包括average、min、max、first、dense。默认值为average。 ascending:指定排名的顺序,True表示升序排名,False表示降序排名。默认值为True。 axis:指定排名的轴,0表示按列排名,1表示按行排名。默认值为0。 numeric_only:指定是否只对数值类型的数据进行排名。默认值为True。 na_option:指定如何对NaN值进行排名,可选参数包括keep、top、bottom。默认值为keep。 pct:是否以百分位形式显示返回的排名。默认为False。 ranked_df内容:只处理数字型数据(numeric_only=True),比较同一列的各行数据(axis=0),本行数据的排序顺序为降序(method='min',最大值排1、最小值排最后),无论何种排序方式空值(NaN)都排在最后(na_option='bottom') A B D 0 4.0 1.0 4.0 1 3.0 2.0 3.0 2 2.0 3.0 2.0 3 1.0 4.0 1.0
rename()
修改索引的方式 db.rename(index={'0':'X','1':'Y'}) 如果不指明index参数,输入一个字典对象并附加axis='index'有同样效果
修改数据的列名 db.rename(index=None,columns={'原列1':'原列1新列名','原列2':'原列2新列名'}) 对列索引进行重命名 # 简化列名,即刻更新 df_ori.rename(columns={'在岗员工(人)': '在岗人数', '离岗员工(人)': '离岗人数'}, inplace=True)
用df的第5行作为列名 df.rename(columns=df.loc[5,:], inplace=True)
replace():
df['年龄'].replace(30,31) 将年龄字段中值为30的数值,替换成31
resample()
重采样方法,多用于时间序列的处理
reset_index()
# reset_index('列名') :指定列作为索引列 df3 = df2.groupby('工号')['合计'].sum() 这个写法的分组结果是“工号转入索引列、数据列仅有合计列数据” df3 = df3.reset_index('工号') 不增加这个方法,写入excel文件时会将工号列视作系统序号而删掉 df3.to_excel(writer, index=False, sheet_name='汇总', header=['工号','2022工资总额'])
df.reset_index() 将全部index转化为column
df.reset_index(level=0) 将第0行索引转化为column列名
db.reset_index(drop=True) 删除原有索引
db.reset_index("列名") 将制定列作为索引列
#对于groupby、pivo等方法生成的dataframe,因为采用多维索引,因此输出表单的索引不能继续使用,需要重置,但有保留的价值(转化成2列) df_sum_pivot.reset_index(drop=False, inplace=True)
select_dtypes()
通过数据类型筛选数据列(int型数据列) df.select_dtypes(include='int')
shape
以“(行数,列数)”格式返回datafram对象的行数、列数,通过“行×列”快速评估数据数量(规模),shape函数本身不是pandas库的方法,是numpy库的函数
shape[0]存储了dataframe对象的行数,shape[1]存储了dataframe对象的列数,多用于for循环中控制遍历上限
set_index():df.set_index('工号') 用指定列作为行索引
shift()
result = df['A'].shift(-1),位移数据,A列数据内各行数据向上移动一行,原本最后一行的数据因无下行,用NaN填充
size
sort_index
df.sort_index() 按索引升序(默认)排序 df.sort_index(ascending=False, inplace=True) 按降序排序并替换现有索引 df['工号'].sort_index(inplace=True) 这个只会将指定列(工号)的数据进行升序排列,不会对其他列产生联动效应,相当于对一列Series对象排序 df.sort_index(inplace=True) 通过对索引列的排序,才能正确的对整表数据开展排序 df.sort_index(na_position='first') 空白字段排在前方,当first用last代替时,空白数据将排在末位 df.sort_index(axis=1) 会对列名开展排序
sort_values
df.sort_values(by=['工号'], ascending=False) 按工号降序排序 na_position参数:first或者last,制定缺失值的排序位置
df.sort_values(by=['部门','工号'], ascending=[False,True],inplace=True) 多列排序,按照部门降序、工号升序排列
split()
将一列拆分成多列数据 df['Names'].str.split('_',expand = True)
style
sum:df.sum(axis=1) 每列/行的求和结果,axis默认为0表示对列求和,指定1表示对行求和
T:转置,原索引(按行)转换后将作为“第一行”,需要删除,原横向的列名转化为纵向的索引号,df.T.to_excel('test.xlsx', index=False)会删除转置后的第一列
tail():df.tail(n) 查看对象最后n行
transform()
通常与groupby连用,避免索引更改 df.groupby(col1).col2.transform("sum") 按col1分组聚合,在结果中统计col2字段的“合计”,生成新列
to_excel
df.to_excel(r'文件名', index=False, header=None, sheet_name='明细') 采取覆盖写入的方式生成文件
writer = pd.ExcelWriter('工资总额明细报表-筛选.xlsx', mode='a') 指定文件必须已经存在 df.to_excel(writer, index=False, header=None, sheet_name='明细')
to_dict
df.to_dict(orient='',into=),orient的参数决定了处理后的对象类型 orient='dict':可以通过df.to_dict(orient='dict')['月份'][4] 的形式访问二维表df对象中“月份”列的第5个元素 orient='list':可以通过df.to_dict(orient='list')['月份'][4]的形式访问二维表df对象中“月份”列,索引为4的元素 orient='series':可以通过df.to_dict(orient='series')['员工姓名'].iloc[4]的形式访问数据
unique():返回指定列的唯一值存入array对象,为便于调用可以结合tolist()方法。df['city'].unique().tolist()将数据列唯一值存入list对象
update()
用一个df1更新另一个df2中与df1相同列的数据,df2中数据为nan的,则不更新df1中对应数据,否则用df2的值替换df1的值 df = pd.DataFrame({'A': [1, 2, 3], 'B': [400, 500, 600]}) new_df = pd.DataFrame({'B': [4, np.nan, 6]}) df.update(new_df) df ''' A B 0 1 4 1 2 500 2 3 6
value_counts():df['ID'].value_counts() 统计指定列出现非空数据的次数
values
where
df.where(df['应发额']>30000).dropna() 将参数中的条件作为筛选条件,逐一匹配dataframe中的每行数据,符合条件的保留,不符合的用NaN空值代替,fillna清空空白行整理格式
统计方法
count:df.count() 统计每列非空数据个数,df.count(axis=1) 统计每行非空数据个数
max:求最大值
mean:求平均值
min:求最小值
median:求中间值(中位数)
mode:求出现次数最多的值
var:求方差
std:求标准差
quantile(0.25):求25分位数,可以用0.5、0.75等分位数
# 发薪机构与岗位类型与当前统计表“指定行”相关字段取值一致的,计算“大于80%数据值的,前20%的分位值” df_result_sum.iloc[row, 3] = salary_detail.loc[(salary_detail['发薪机构'] == df_result_sum.iloc[row, 0]) & (salary_detail['岗位类型'] == df_result_sum.iloc[row, 1]), '年初至本月累计应发'].quantile(0.8, interpolation='midpoint')
corr():求整个DataFram表中的相关性
部分实践方法
数据列文本替换:df2["姓名"].str.replace(' ',''),删除姓名列中的空格
新增数据列(由现有数据列计算生成)
# 依据“在岗人数、离岗人数”两列数据生成“在册人数”数据列,数据计算发放为sum,计算方向axis=1表示按列计算 df_ori['在册人数'] = df_ori[['在岗人数', '离岗人数']].sum(axis=1)
通过公式添加列
展示计算后的数据: print('平均销售单价',df2.['销售单价'].mean()),打印所有商品的平均单价,直接调用mean方法,类似的方法还有std标准差、median中位数、max最大值、min最小值 df2.loc[ (df2['销售量']>df2['销售量'].mean() ) & (df2['销售单价']>df2['销售单价'].mean() ) ,:] 选中了表格内销售量大于销量平均值 并且 销售单价大于平均单价的所有行
数据分列存储: pd.DataFrame((x.split('-') for x in df_inner['category']),index=df_inner.index,columns=['category','size'] 将一列有明显录入规则的数据,通过指定分隔符调用split方法拆分成两列数据并存入新的数据表
拆分合并单元格至每个分解单元格 df['单位'].fillna(axis=0, inplace=True) 已读取数据的datafram对象,先填充,本方法按上而下填充空值,形成一个中间文件 将中间文件数据写入原文件 for row in worksheet.iter_rows(): row_list[] for cell in row: row_list.append(cell.value) 通过逐一添加元素的方式,形成一个series对象 worksheet.apppend(row_list) 将新添加完成的series对象合并进入dataframe对象
df[df.工号.eq('550012')] 返回一个Series对象,里面以True/False存储了每个行数据与指定值的逻辑运算结果
比对两个从Excel读取出来的DataFrame对象的字段是否有差异,由于待比对数据为“数值型数据”因此在判断条件中除了判定“存在”还判断数据类型dtype if (df1.dtypes.index[num] in df2.dtypes.index.values) and (not df1.iloc[:, num].dtype is np.dtype(dtype='object')): check_list.append(df1.dtypes.index[num])
模糊匹配:选择“Name”列包含字母“A”的行,df[df['Name'].str.contains('A', case=False, na=False)]
新增一列数值条件判定结果
新增一列表示年龄是否大于30 df['IsAbove30'] = df['Age'] > 30
Series对象
可以理解为“附带索引的列表” S1 = pd.Series(['a','b','c']) S1 = pd.Series(['a','b','c'],index=(1,3,4)) 指定行索引编号 S1 = pd.Series({1:'a',2:'b',3:'c'})
value_count():可以统计各元素出现的次数
index():
isin()
# 可以通过比较两个Series对象来识别一个Series存在或不存在另外一个Series对象的数据,isin 的结果是一组布尔型数值的集合 ser1 = pd.Series([1, 2, 3, 4, 5]) ser2 = pd.Series([4, 5, 6, 7, 8]) # 返回ser1【不】包含ser2的布尔型series ser3=~ser1.isin(ser2) # 利用布尔型集合作为索引,获取ser1不包含ser2的元素 print(ser1[ser3])
# 比较两个Series中
将Series对象转化为DataFrame对象,当Series对象index列有名称(比如从dataFrame.groupby()运算而来的),不能指定列名,只能忽略columns参数,用其已有默认名称 df = pd.DataFrame(s, columns=['Number'])
Panel对象
to_datetime()
接受一个字符串或者一个字符串的序列(如列表,数组,或者Series),并返回一个日期时间格式的对象(如Timestamp,DatetimeIndex,或者Series)
pd.to_datetime(s, infer_datetime_format=True) infer_datetime_format=True可以让Pandas自动识别不同格式的日期数据,避免误读日和月
转换单一字符串 import pandas as pd s = "2020-01-01" dt = pd.to_datetime(s) print(dt) print(type(dt)) --->2020-01-01 00:00:00 ---><class 'pandas._libs.tslibs.timestamps.Timestamp'> 还可以进一步调用dt(timestamp对象)的属性 print(dt.year) # 年份 print(dt.month) # 月份 print(dt.day) # 日期 print(dt.hour) # 小时 print(dt.minute) # 分钟 print(dt.second) # 秒 print(dt.dayofweek) # 星期几 print(dt.dayofyear) # 一年中的第几天 print(dt.weekofyear) # 一年中的第几周 print(dt.tz) # 时区 print(dt.freq) # 频率
转换字符串序列 import pandas as pd s = ["2020-01-01", "2020-02-01", "2020-03-01"] dt = pd.to_datetime(s) print(dt) print(type(dt)) --->DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01'], dtype='datetime64[ns]', freq=None) ---><class 'pandas.core.indexes.datetimes.DatetimeIndex'> 进一步调用属性时,返回DatetimeIndex对象 print(dt.year) # 年份 print(dt.month) # 月份 print(dt.day) # 日期 print(dt.hour) # 小时 print(dt.minute) # 分钟 print(dt.second) # 秒 print(dt.dayofweek) # 星期几 print(dt.dayofyear) # 一年中的第几天 print(dt.weekofyear) # 一年中的第几周 print(dt.tz) # 时区 print(dt.freq) # 频率 --->输出结果 Int64Index([2020, 2020, 2020], dtype='int64') Int64Index([1, 2, 3], dtype='int64') Int64Index([1, 1, 1], dtype='int64') Int64Index([0, 0, 0], dtype='int64') Int64Index([0, 0, 0], dtype='int64') Int64Index([0, 0, 0], dtype='int64') Int64Index([2, 5, 6], dtype='int64') Int64Index([1, 32, 61], dtype='int64') Int64Index([1, 5, 9], dtype='int64') None None
crosstab()
交叉表
pyautogui
全局操作
pyautogui.FAILSAFE =False 当鼠标移到左上角的时候,强制报错并终止程序,便于程序运行时人工终止
pyautogui.PAUSE= 1 所有pyautogui的指令都要暂停一秒;其他指令不会停顿;这样做,可以防止键盘鼠标操作太快
position():pyautogui.position()[0]返回当前光标的横坐标,pyautogui.position()[1]返回当前光标的纵坐标
size():pyautogui.size()[0]返回横向分辨率像素数,pyautogui.size()[1]返回纵向分辨率像素数
displayMousePosition(),运行后坐标会实时显示
移动鼠标
moveTo():moveTo(横坐标, 纵坐标, 操作时间),按指定时间移动到指定光标位置
moveRel():moveRel(200, 300, 1),以当前光标位置为基准【相对移动】,向右移动200像素,向下移动300像素,以上操作在1秒钟内完成
单击鼠标
click():
pyautogui.click(x=none,y=none,click=1,interval=0.0,duration=0.0,button='primary') x、y表示点击位置的坐标像素 click:表示点击次数 interval:表示相邻两次点击的间隔时间 duration:设定本次动作完成的累计时间,注意与interval、click的逻辑合理性 button:left、middle、right、primary、secondary
单击左键:pyautogui.leftclick(x=none,y=none,interval=0.0,duration=0.0)
单击右键:pyautogui.rightclick(x=none,y=none,interval=0.0,duration=0.0)
单击中键:pyautogui.middleclick(x=none,y=none,interval=0.0,duration=0.0)
左键双击:pyautogui.doubleclick(x=none,y=none,interval=0.0,button='left',duration=0.0)
左键三连击:pyautogui.tripleclick(x=none,y=none,interval=0.0,button='left',duration=0.0)
pyautogui.mouseDown(x=none,y=none,button='primary',duration=0.0) pyautogui.mouseUp(x=none,y=none,button='primary',duration=0.0) 将鼠标移动到指定坐标,“按下/松开”鼠标
单击页面元素拖动
用途:拖动滚动条展示未显示页面元素,拖动窗口,拖动网页元素到指定位置
pyautogui.dragTo(x=None,y=None,duration=0.0,button='primary',mouseDownUp=True) 把鼠标拖动到指定位置,松开【视作拖动行为】。mouseDownUp设为False,相当单纯移动光标;duration=0或不设置,也不能正常拖动。
pyautogui.dragRel(xOffset=None,yOffset=None,duration=0.0,button='primary',mouseDownUp=True) 与dragTo函数类似,属于【相对位置拖动】
鼠标滚轮
pyautogui.scroll(clicks, x=None, y=None)【代码实操时发现执行无效果】 clicks:int数值指明滚动量 xy坐标指明了事件发生位置,未指定的按当前坐标。
模拟键盘输入
pyautogui.KEY_NAMES,可以查询支持的模拟按键
pyautogui.press(keys, presses=1, interval=0.0) key:模拟按下的按键,可以是单个的str,也可以是list列表 press:重复按下的次数,默认为1 interval:间隔,默认为零表示无间隔连续按键
pyautogui.write(message,interval=0.0) message可以传入“hello message”形式的内容,而不是像press方法只能传入单个按键【但是不支持中文】
pyautogui.hotkey('ctrl','shift','C') 表示执行同时按下三个按键激活的热键
调出一个弹出窗口
pyautogui.alert(text="", title="", botton="OK")
pyautogui.confirm(text="", title="", buttons=['OK','Cancel'])
pyautogui.confirm(text="", title="", buttons=range(10)),激活一个窗口,有10个按键,按键文字描述从0到9
pyautogui.prompt(text="", title="", default=""),打开一个可以输入信息的窗口,有OK和Cancel两个按钮,任意点击其中一个都会关闭窗口,点OK关闭窗口时会返回输入值,点Cancel则取消
pyautogui.password(text="", title="", default="", mask="*") 用于输入密码,输入内容用指定mask掩码遮蔽,点击OK返回输入文字
pyperclip
copy():将参数内容复制到剪贴板,可以在后续通过pyautogui.hotkey('ctrl','shift','V'),将副职内容黏贴到指定位置,该方法支持中文字符
pyecharts
render():渲染表格函数,默认生成html文件,生成图片格式的文件需要按照其他插件库
charts
Bar
import pyecharts.options as opts # 柱状图,创建时制定图表主题 bar = Bar({"theme": ThemeType.MACARONS}) # 在横坐标分类 bar.add_xaxis(["吃喝", "杂物", "交通", "书费", "游玩", "花呗", "网购"]) # 在纵坐标方向增加数据,数值数目与和总表分类数保持一致 bar.add_yaxis("旁友A", [600, 20,30, 50, 100, 125, 200]) bar.add_yaxis("旁友B", [650,25,25, 80, 150, 145, 100]) # title_opts标题,text表示主标题描述、subtext表示副标题描述 bar.set_global_opts( title_opts={"text": "同学们的生活开支", "subtext": "通过 dict进行配置"}) bar.render()
# 堆积柱状图,基于Bar的基础数据,在纵坐标(yaxis)方向上,增加参数stack,具有相同stack参数至的纵坐标数据会“堆积” bar.add_yaxis("旁友A", [600, 20,30, 50, 100, 125, 200], stack='stack1') bar.add_yaxis("旁友B", [650,25,25, 80, 150, 145, 100], stack='stack1')
# 纵坐标数据参数,category_gap=0表示两列柱状图间隔为0 bar.add_yaxis("旁友B", [650,25,25, 80, 150, 145, 100], category_gap=0) # 纵向柱状图转换为横向的条状图,正常添加坐标数据,然后翻转reversal_axis() bar.reversal_axis()
Bar3D
3D柱形图
BMap
百度地图
Boxplot
筒形图
Calendar
日历图
EffectScatter
涟漪特效散点图
Funnel
漏斗图
Gauge
仪表盘
Geo
# 存储含有地理位置的底层数据,通过Map函数搭配使用,构建地图
geo.add(name, attr, value, type="scatter", maptype='china', coordinate_region='中国', symbol_size=12, border_color="#111", geo_normal_color="#323c48", geo_emphasis_color="#2a333d", geo_cities_coords=None, is_roam=True, **kwargs) 参数: name:str 图例名称 attr:list 属性名称 value: list 属性所对应的值 type:str 图例类型,有'scatter','effectScatter','heatmap'可选。默认为'scatter' maptype: str 地图类型,据此确定了地图形状 coordinate_region: str 城市坐标所属国家 symbol_size: int 标记图形大小。默认为12 border_color: str 地图边界颜色。默认为'#111' geo_normal_color: str 正常状态下地图区域的颜色。默认为'#323c48' geo_emphasis_color: str 高亮状态下地图区域的颜色。默认为'#2a333d' geo_cities_coords: dict 用户自定义地区经纬度,类似如{'阿城':[126.58,45.32],}这样的字典。 is_roam: bool 是否开启鼠标缩放和平移漫游。'scale'缩放、'move'平移、'True'都开启;默认为True。
Graph
关系图
Grid
1.并行显示多张图表,第一张图必须是能区分出二维坐标(x/y轴)的图,不能是Pie 2.当数据系列过多的时候,图例跟绘图区会重叠,可以将图表对象加入Grid对象,进而通过grid_top属性,将绘图区向空白地区偏移(压缩)
Grid.add(chart, grid_width=None, grid_height=None, grid_top=None, grid_bottom=None, grid_left=None, grid_right=None) grid_width:grid组件宽度, 默认自适应窗口 grid_height:grid组件高度, 默认自适应窗口 grid_top:grid组件离容器顶部的距离,默认为None,有'top','center','middle'可选,也可以为百分比或整数 grid_bottom:离容器底部的距离,其他同top grid_left:离容器左侧的距离,其他同top grid_right:离容器右侧的距离,其他同top
HeatMap
热力图
KLine
K线图
Line
# 折线图 import pyecharts.options as opts from pyecharts.charts import Line c = ( Line() .add_xaxis(["10.13", "10.14", "10.15", "10.16" , "10.17" , "10.18"]) .add_yaxis("成都fly北京", [1650, 1700, 1461, 1350, 1100, 1500]) .add_yaxis("成都fly昆明", [1020, 575, 400, 350, 330, 480]) .set_global_opts(title_opts=opts.TitleOpts(title="航班价格折线图")) ) c.render()
# 折线样式,平滑曲线(is_smooth属性) line.add(……, linestyle_opts=opts.LineStyleOpts(width=2, type_='dotted', is_smooth=True))
# 折线标签点的颜色、折线图例的颜色 line_rjlr.add_yaxis("2023年", round((df_detail.loc[(df_detail["日期"] > 202212) & (df_detail["单位名称"] == company_name), '当月人均利润总额']), 2), linestyle_opts=opts.LineStyleOpts(width=5, type_='solid', color='rgba(7, 20, 170,0.5)'), markline_opts=opts.MarkLineOpts(label_opts=opts.LabelOpts(color='rgba(7, 20, 170,0.5)'), linestyle_opts=opts.LineStyleOpts(color='rgba(7, 20, 170,0.5)')), itemstyle_opts=opts.ItemStyleOpts(color='rgba(7, 20, 170,0.5)'))
Line3D
3D折线图
Liquid
Map
InitOpts:初始化参数 map = Map(init_opts=Opts.InitOpts(width='', height=,chart_id='',renderer='',page_title='',theme,bg_color='',js_host='', animation_opts=)
add:添加数据系列 series_name:系列名称,用于tooltip的显示,Legend的图例筛选 data_pair:[list1[], list2[]],可以用zip函数+2个list对象构建 maptype:str对象,china(对应省级),china-cities(对应城市级) is_selected:bool对象,默认True,表示默认状态下是否选中该序列 is_roam:bool对象,是否开启鼠标缩放和平移漫游,默认True center:中心视角,用经纬度表示 zoom:缩放比例 name_map:自定义地区的名称映射 symbol:标记图形形状 is_map_symbol_show:bool类型,是否显示标记图形(在图上各省内,不再出现圆点标记),默认True label_opts:配置标签项, tooltip_opts:配置提示框组件 itemstyle_opts:图元样式配置项 emphasis_label_opts:高亮标签配置项 emphasis_itemstyle_opts:高亮图元样式配置项
visualmap_opts视觉映射配置表 is_show: type_:映射过渡类型,可算'color','size' min_:指定visualMapPiecewise组件的最小值 max_:指定visualMapPiecewise组建的最大值 range_text:visualMap图示两端的文字,如'High','Low'或者'最大','最小' range_color:组件过渡颜色 range_size:组件过渡size大小 range_opacity:图元及其附属标签文字的透明度 orient:组建的放置方向,'horizontal','vertical' pos_left、pos_right、pos_top、pos_bottom: split_number:对于连续数据,按照max和min的取值,分成多少段,默认为5段 series_index:取哪列数据,默认取所有列 dimension:组建的映射维度 is_caculable:是否显示可以拖拽用的手柄 is_piecewise:是否为分段性,默认为False,在“图例”处能显著识别是否分段 is_inverse:是否反转组建 precision:数据展示的小数精度,默认为0 pieces:自定义每一段的范围、文字及样式,如{"min":10, "max":100, “label":"10到100"} out_of_range:定义在选中范围外的视觉元素,包括:symbol图元的图形类别,symbolSize图元的大小,color图元的颜色,colorAlpha图元的颜色的透明度,opacity图元及其附属标签的透明度,colorLightness颜色的敏感度,colorSaturation颜色的饱和度,colorHue颜色的色调 item_width:图形的宽度 item_height:图形的高度 background_color: border_color:组件边框的颜色 border_width:边框线宽 textstyle_opts:文字样式配置项
# 自主控制分段的上下限以及对应的颜色,注意“颜色默认从下限往上限匹配,与分段顺序无关” pieces=[{"max": 200, "min": 20, "label": "超过20家"}, {"max": 19, "min": 10, "label": "超过10家"}, {"max": 9, "min": 5, "label": "超过5家"}, {"max": 4, "min": 1, "label": "已覆盖暂不足5家"}, {"max": 0, "min": 0, "label": "尚未覆盖"}], range_color=['rgba(25,50,150,0)', 'rgba(25,50,150,0.4)', 'rgba(25,50,150,0.6)', 'rgba(25,50,150,0.8)', 'rgba(25,50,150,1)']
Map3D
3D地图
Overlap
# 多张图表叠加显示在一张图标上 # C1表示一个柱状图对象,C2表示一个饼图(圆环图)对象 C1.overlap(C2)
Page
# 顺序排列 page = Page(layout=Page.SimplePageLayout) page.add(图表1, 图表2, 表格1,……) page.render()
# 可拖动编辑位置、大小模式 page_board = Page(layout=Page.DraggablePageLayout) page_board.add(chart1, chart2, ……) page_board.render("预排版-待拖动.html") # 在“预排版-待拖动.html”打开后“拖动、缩放”,save_config按钮保存chart_config.json,将json文件下载并保存到程序目录下 # chart_config.json以“字典”模式,通过 cid、width、height、left、top的参数设置,逐一明确各个“chart”对象的位置、大小 # cid属性对应chart_id属性,是明确“chart”对象的唯一标记 page_board.save_resize_html("预排版-待拖动.html", cfg_file="./chart_config.json", dest='最终文件.html')
Parallel
平行坐标系
PictorialBar
象形柱状图
Pie
# 饼图,链式调用的写法 from pyecharts import options as opts from pyecharts.charts import Pie from pyecharts.faker import Collector, Faker c = ( Pie() .add("", [list(z) for z in zip(['上课','睡眠','餐饮','娱乐','聊天学习','健身'], [4,8,3,3,2,1])]) .set_colors(["blue", "green", "yellow", "red", "pink","orange"]) .set_global_opts(title_opts=opts.TitleOpts(title="这一天天的")) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}")) ) c.render()
Polar
极坐标系
Radar
雷达图
Sankey
桑基图
Scatter
散点图
Scatter3D
3D散点图
Sunburst
旭日图
ThemeRiver
主题河流图
Timeline
Tree
树图
TreeMap
矩形树图
WordCloud
词云图
commons
utils
components
Table
table= Table() table.add(header,rows) table.set_globals_opts(title_opts=opts.ComponentTitleOpts(title="表格名称"))
options
set_global_opts
# 图表的主副标题文字 bar.set_global_opts( title_opts={"text": "同学们的生活开支", "subtext": "通过 dict进行配置"}) bar.set_global_opts(title_opts=opts.TitleOpts(title="一级标题",subtitle="二级标题",title_link="链接网址" title:主标题文本,支持"\n" title_link: subtitle:副标题文本,支持"\n" subtitle_link: pos_left:title组件离容器左侧的距离,可以是20这样的像素值,也可以是'20%'的相对容器宽度的百分比,也可以是'left','center','right'自动对齐 pos_right:title组件离容器右侧的距离 pos_top:title组件离容器顶部的距离,可以是'top','middle','bottom' pos_bottom:title组件离容器底部的距离 padding:标题内边距,单位px,接收单一值(表示上下左右4个方向均等值缩进),也接受数组,分别指定4个方向的内边距 item_gap:主副标题的间距 title_textstyle_opts:主标题字体样式,参考series_options.TextStyleOpts subtitle_textstyle_opts:副标题字体样式,参考series_options.TextStyleOpts
# 坐标轴控制 # 调整横坐标显示方位,原坐标系最左侧视作0,-2相当在左侧多出2列的空间,数值8将与现有数据条目比较,现有条目不足8的,补足,否则截断显示到第8个数据 bar.set_global_opts(xaxis_opts=opts.AxisOpts(is_show=True, min_=-2, max_=8) # 调整纵坐标显示方位,控制纵坐标最大值为40 bar.set_global_opts(yaxis_opts=opts.AxisOpts(max_=40))
AxisOpts轴坐标配置
type_:坐标轴类型,value表示数值轴,用于连续数据;category表示类目轴,必须同步给予data参数设置类目数;time表示时间轴;log表示对数轴
name:坐标轴名称
is_show:是否显示
is_scale:只能在数值轴中有效,在双轴的散点图中比较有用,当坐标轴设置min和max之后配置无效
is_inverse:是否反向坐标轴
name_location:坐标轴显示位置,start、middle、center、end
name_gap:坐标轴名称与轴线之间的距离
name_rotate:坐标轴名称旋转角度
interval:坐标轴数值间隔,不能在类目轴上使用
grid_index:x轴在Grid的索引
position:X轴的位置,top、bottom
offset:Y轴相对默认位置的便宜
split_num:坐标轴的分隔段数
boundary_gap:
min:坐标轴最小值
max:坐标值最大值
min_interval:
max_interval:
axisline_opts:坐标轴刻度线配置项,参考global_options.AxisLineOpts
axistick_opts:坐标轴刻度配置项,参考global_options.AxisTickOpts
axislabel_opts:坐标轴标签配置项,参考series_options.LabelOpts
axispointer_opts:坐标轴指示器配置项,参考global_options.AxisPointerOpts
name_textstyle_opts:坐标轴名称的文字样式,参考series_options.TextStyleOpts
splitarea_opts:分割区域配置项,参考series_options.SplitAreaOpts
splitline_opts:分割线配置项,参考series_options.SplitLineOpts
minor_tick_opts:坐标轴次刻度线相关设置,参考坐标轴次刻度线相关设置&
minor_split_line_opts:坐标轴在 grid 区域中的次分隔线。次分割线会对齐次刻度线,参考series_options.MinorSplitLineOpts
AxisLineOpts坐标轴轴线配置
is_show:是否显示坐标轴轴线
is_on_zero:X 轴或者 Y 轴的轴线是否在另一个轴的 0 刻度上,只有在另一个轴为数值轴且包含 0 刻度时有效
on_zero_axis_index:当有双轴时,用这个属性手动指定在哪个轴的0刻度上
symbol:末端箭头显示方式,none、arrow、[none,arrow]相当左侧无箭头,[arrow,none]相当右侧无箭头
linestyle_opts:坐标轴线风格配置项,参考series_optionsLineStyleOpts
AxisTickOpts坐标轴刻度配置
is_show:是否显示坐标轴刻度
is_align_with_label:类目轴中在 boundaryGap 为 true 的时候有效,可以保证刻度线和标签对齐
is_inside:坐标轴刻度是否朝内,默认朝外
length:坐标轴刻度的长度
linestyle_opts:坐标轴线风格配置项,series_optionsLineStyleOpts
AxisPointerOpts坐标轴显示器配置
is_show
link
type_:默认line,还可以shadow、none
label
linestyle_opts
InitOpts初始化配置顶
width
height
chart_id
renderer
page_title
theme
bg_color
js_host:远程js服务器,默认https://assets.pyecharts.org/assets/
animation_opts:画图动画初始化配置,参考global_options.AnimationOpts
AnimationOpts画图动画配置
animation:是否开启动画,默认为True
animation_threshold:是否开启动画的阈值,当单个系列显示的图形数量大于这个阈值时会关闭动画。默认 2000
animation_duration:初始动画的时长,默认值为 1000
animation_easing:初始动画的缓动效果
animation_delay:初始动画的延迟,默认为0
animation_duration_update:数据更新动画的时长,默认300
TooltipOpts提示框配置顶
is_show
trigger:触发类型
item(数据项图形,主要是散点图、饼图等无类目轴的图表
axis:坐标轴触发,主要在柱状图、折线图等使用类目轴的图表
none
trigger_on:触发条件
mousemove:鼠标移动时触发
click:鼠标点击时触发
mouse|click:同时鼠标移动和点击时触发
none:不在mousemove或click时触发
axis_pointer_type:指示器类型
line:指示器类型
shadow:指示器类型
none:无指示器
cross:十字准星指示器
is_show_content:是否显示提示框浮层
is_always_show_content:是否永远显示提示框内容
show_delay:浮层显示的延迟,单位ms
hide_delay:hide_delay,单位ms
position:提示框浮层的位置,相对位置[10,10],百分比[50%,50%],固定参数inside、top、left、right、bottom
formatter
background_color:提示框浮层的背景颜色
border_color:提示框浮层的边框颜色
border_width:提示框浮层的边框宽
textstyle_opts:文字样式配置项,参考series_options.TextStyleOpts
# 图例配置项LegendOpts
# 工具配置项ToolboxOpts
toolbox_opts=opts.ToolboxOpts(is_show=True, orient='horizontal', item_size=10, pos_left='70%' 展示Toolbox框,默认有“下载、刷新、展示数据表、区域放大、放大还原、转为折线图、转为柱形图、转为堆积图”;样例还指定了排列方向、大小、相对位置
# 视觉映射配置项,VisualMapOpts
# 提示框配置项,TooltipOpts
# 区域缩放配置项,DataZoomOpts
set_series_opts
import pyecharts.options as opts # 数据序列标签在序列“右侧”,用于横向的条状图 bar.set_series_opts(label_opt=opt.LabelOpts(position="right"))
import pyecharts.options as opts # 自定义标记线,在纵坐标数值为10的位置,增加一条横向的标记线,标记线对象命名为“yAxis=10" bar.set_series_opts(label_opt=opt.LabelOpts(is_show=False), markline_opts= opts.MarkLineOpts.(data=[opts.MarkLineItem(y=10, name='yAxis=10')])) # 可以指定多条标记线 markline_opts=opts.MarkLineOpts(data=[ opts.MarkLineItem(type_='min', name='最小值'), opts.MarkLineItem(type_='max', name='最大值'), opts.MarkLineItem(type_='average', name='平均值'), ])
import pyecharts.options as opts # 自定义标记点 bar.set_series_opts(label_opt=opt.LabelOpts(is_show=False), markpoint_opts=opts.MarkPointOpts(data=[ opts.MarkPointItem(type_='min', name='最小值'), opts.MarkPointItem(type_='max', name='最大值'), opts.MarkPointItem(type_='average', name='平均值'), ])
ItemStyleOpts
color:图例的颜色
用rgb(128,128,128)、rgba(128,128,128,0.5),a表示alpha通道(代表透明度),也可以用十六进制字符串“#ccc”代替
渐变色
纹理填充
border_color:边框颜色
color0:阴影线颜色
border_color0:
border_witdth:描边线宽度,默认不描边
border_type:支持dashed、dotted
opacity:从0到1的数值
area_color:序列对应图表区域颜色,如map下的各省地图颜色
LabelOpts
# 通过以下语句设置标签格式 bar.set_series_opts(label_opt=opt.LabelOpts(……))
is_show:False、True,表示是否显示数据标签
position:top、bottom、left、right、inside,、insideleft,、insideright、6个值,标记数据标签的相对位置
color:数据标签的颜色,可以设为'auto'
distance:当position为“字符描述值”如Top、insideright下有效,表示标签距离数据系列的偏移位置
font_size:int数值,表示文字大小
font_style:str对象,字体风格,如''normal,'italic','oblique'
font_weight:normal、bold、bolder、lighter
font_family:str对象,表示字体,如'Microsoft YaHei','Arial'
rotate:从-90到90选,正值表示顺时针旋转
margin:
interval:
horizontal_align:水平对齐方式,left、right、center
vertical_align:垂直对齐方式,top、middle、bottom
formatter:回调函数
rich:自定义富文本样式
LineStyleOpts
is_show:
width:线宽
opacity:0至1,透明度
curve:线条弯曲度
type_:solid、dashed、dotted
color:纯色、渐进式、纹理填充
MarklineOpts
is_silent:默认false表示不响应和触发鼠标事件
data:标记线数据
# 通过以下语句设置标记线格式 markline_opts= opts.MarkLineOpts.(data=[opts.MarkLineItem(y=10, name='yAxis=10')])
# 可以指定多条标记线 markline_opts=opts.MarkLineOpts(data=[ opts.MarkLineItem(type_='min', name='最小值'), opts.MarkLineItem(type_='max', name='最大值'), opts.MarkLineItem(type_='average', name='平均值'), ])
symbol:具体格式见data.symbol,指明标记线两端类型
symbol_size:标线两端的标记大小
precision:标记线显示数值的精度
label_opts:
linestyle_opts:
MarkLineItem
name:
type_:
x:
y:
xcoord:
ycoord:
value_index:
value_dim
coord
symbol
symbol_size
MarkPointOpts
data:
symbol:
symbol_size:
label_opts:
MarkPointItem
name:
type_:min、max、average
value_index:0或者1,与type_属性搭配使用,0表示横坐标方向、1表示纵坐标方向
value_dim
coord:
x:相对容器的横坐标像素
y:相对容器的纵坐标像素
value:
symbol:可以在'circle','rect','roundRect','triangel','diamond','pin','arrow','none'中选择合适的图例
symbol_size:[20,10]表示图例宽20、高10
TextStyleOpts
color
font_style
font_weight
font_family
font_size
align
vertical_align
line_height
backgroud_color
border_color
border_width
border_radius
padding:内边距
shadow_color
shadow_blur
witdth:文字块宽度
height
rich:自定义富文本
AreaStyleOpts
opacity
color
SplitAreaOpts
is_show
areastyle_opts
MinorTickOpts
次级刻度线
MinorSplitLineOpts
is_show
width
type_
opacity
lineStyle_opts
faker
globals
# 模块预设多个配色主题:有 LIGHT、DARK、CHALK、ESSOS、INFOGRAPHIC、MACARONS、PURPLE_PASSION、ROMA、ROMANTIC、SHINE、VINTAGE、WALDEN、WESTEROS、WONDERLAND # 通过创建图表对象时初始化设置主题 from pyecharts.globals import ThemeType bar = Bar(init_opts= opts.InitOpts(theme=ThemeType.Dart))
# 区域缩放,默认缩放横坐标,通过type_属性,默认为“slider”,还有“inside”可选 bar.set_global_opts(title_opts=……,datazoom_opts=[opt.DataZoomOpts(), opt.DataZoomOpts(type_='inside')]) # 缩放纵坐标 bar.set_global_opts(title_opts=……,datazoom_opts=opts.DataZoomOpts(orient='Vertical'))
导出报表到图片
# 使用 snapshot-selenium 渲染图片 from snapshot_selenium import snapshot make_snapshot(snapshot, bar.render(), "bar.png")
selenium
from selenium import webdriver # 指定要打开的URL url = r'https://cas.baogang.info/cas/...' # 用指定浏览器打开网址,driver相当于浏览器对象 driver.get(url) # 关闭浏览器 driver.quit()
webdriver对象
初始化
# 通过指定浏览器构建对象 driver = webdriver.Chrome(options=, service=,keep_alive=True)
driver.set_page_load_timeout(20) # 设置连接超时20秒
用get方法打开网页
url = r'https://cas.baogang.info/cas/...' driver.get(url)
back():浏览器“回退”到上一页面
close():关闭当前浏览器标签,多用于新建标签的关闭
ChromeOptions对象
# 首先创建配置对象 options = webdriver.ChromeOptions()
options.add_argument('lang=zh_CN.UTF-8') # 设置中文 options.add_argument('--headless') # 无头参数,浏览器隐藏在后台运行 options.add_argument('--disable-gpu') # 禁用GPU加速 options.add_argument('--start-maximized') # 浏览器最大化 options.add_argument('--window-size=1920x1024') # 设置浏览器分辨率(窗口大小) options.add_argument('--user-agent=""') # 设置请求头的User-Agent options.add_argument('--incognito') # 隐身模式(无痕模式)
# 增加启动配置参数,达到特定效果 option = ChromeOptions() # 可以使得启动的Chrome浏览器左上角窗口不再显示“被自动化软件控制” option.add_argument("--disable-blink-features=AutomationControlled") driver = webdriver.Chrome(options=option)
#另一种通过增加启动参数,“伪装”访问网站,进而下载数据的配置方式 option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) option.add_experimental_option('useAutomationExtension', False) option.add_argument("--disable-blink-features=AutomationControlled") #禁用图片加载 options.add_experimental_option('prefs', {'profile.managed_default_content_settings.images': 2}) driver = webdriver.Chrome(options=option)
current_url:当前页面网址
execute_script():执行JavaScript
# 当前浏览器标签缩放比例指定为100% driver.execute_script("document.body.style.zoom='100%'")
# 滚动到指定元素可见 “元素.scrollIntoView()“ title = driver.find_element(by=By.CLASS_NAME, value='searchDiv') driver.execute_script("arguments[0].scrollIntoView();", title) from selenium.webdriver.common.action_chains import ActionChains action = ActionChains(driver) element = driver.find_element(By.ID, "kw") action.scroll_to_element(element).perform()
# 部分元素因遮挡等原因,无法在页面上直接点击或直接调用元素的click方法时报错,表示元素不可见或不可点击,可以用JavaScript方法避免元素在页面上被遮挡而无法点击 driver.execute_script("arguments[0].click();", xczxqk)
#上下滑动窗口 driver.execute_script("window.scrollTo(0,1000)") # 向下滚动窗口500个像素 driver.execute_script("window.scrollBy(0, 500)") # 滚动到窗口底部 driver.execute_script("window.scrollTo(0, document.body.scrollHeight)") # 滚动到窗口顶部 driver.execute_script("window.scrollTo(0, 0)") # 修改网页元素属性 driver.execute_script("arguments[0].setAttribute(arguments[1],arguments[2]);",'网页元素id名','元素属性形成','修改后的属性值') #打开新标签 driver.execute_script("window.open("https://www.baidu.com")")
# 常用脚本文件 window.scrollto(20,1000) window.open('https://www/baidu/com')
forward():浏览器“前进”
get_window_size():获取浏览器窗口大小
maximize_window():当前窗口最大化
page_source():获取当前页面的完整html代码
refresh():刷新页面
quit():关闭当前浏览器标签,如果是Chrome实例中最后一个标签,关闭后将结束Chrome进程
save_screenshot():截屏并保存到参数指定的文件名位置(含路径及后缀名的完整字符串)
send_keys():通过find_element定位元素,调用元素的send_keys()方法,传入字符串
set_window_size(宽, 高):修改浏览器窗口的大小
set_window_position():设定浏览器窗口位置
title:当前页面标签的“标题”
switch_to大类
switch_to.default_content():退出当前页面的多层iFrame嵌套,到最外层
# 在页面中多个frame结构中切换,可能存在父子frame切换的逻辑顺序 driver.switch_to.frame(driver.find_element(by=By.ID, value='pageFrame'))
# 切换浏览器标签,获取浏览器的窗口句柄,默认窗口的句柄索引号为0 handles = driver.window_handles driver.switch_to.window(handles[1])
启动参数配置ChromeOptions
Select对象
# 定位网页中的下拉列表对象 from selenium.webdriver.support.select import Select
定位
select_by_index() select_by_value() #通过对象option中value属性的值来定位 select_by_visible_text() # 通过下拉框内的文本值定位
# 先获取下拉列表对象,依据显示值选定对象 gs = Select(driver.find_element(by=By.XPATH, value='//*[@id="export_formatList"]')) gs.select_by_visible_text("Excel (match exact layout)")
信息
voptions:返回所有options all_selected_options:返回已选中的options first_selected_options:返回所有选中的options中的第一个 deselect_all():取消已选中的options deselect_by_index():根据index属性取消选择 deselect_by_value():根据value属性取消选择 deselect_by_visible_text():根据已选中options中等于指定值,取消选择
find_element():通过不同的定位方式找指定元素
返回对象是网页的dom对象
# id标签方便且唯一,但是有可能不存在,或者是动态生成的 browser.find_element(by=By.ID, "XXX") # name属性、tag属性不一定是唯一值
# link对象 find_element(By.LINK_TEXT, 'XX') 表示根据链接文本全字匹配进行精确查找 find_element(By.PARTIAL_LINK_TEXT,'XX')根据链接文本模糊匹配进行定位
# xpath # 绝对路径,根据html代码结构,从最外侧到当前对象。由于路径描述完整,任意html代码的调整【部分网站内的元素id是随机生成的】都会造成查找不成功,通过xpath层次隶属关系可以不用通过“id”属性定位元素 /html/body/div[2]/form/input[3] 其中[]表示本级对象存在分支,括号内的数字表示第几个分支 # 相对路径,通过多种方式“混合定位”, //input[@id='kw'] 表示任意目录下的input元素,id值为kw的对象(@后的代码为对象属性) //input[@id='kw' and @name='kw'] 表示任意目录下,id属性和name属性都是kw的input元素 //input[@id='aa']/p 当要查找的对象,没有设置任何属性,可以通过找到它的上级属性,再向下(/p)锁定 element = driver.find_element(by=By.XPATH, value="'kw'] " nodename:选取此节点的所有子节点 /:从当前节点选取直接子节点 //:从当前节点选取孙节点 .:选取当前节点 ..:选取当前节点的父节点 @:选取指定名称的属性 *:选取对象所有属性
# CSS选择器,理论上可以准确定位任何元素 browser.find_element(By.CSS_SELECTOR, '#toolbar-search-input') .xxx:类选择器,选择class属性为XXX的元素 #xxx:id选择器,选择id属性为xxx的元素 xxx:元素选择器,选择标签名为xxx的元素 AA>XX或AA xx:派生选择器,选择父标签AA标签下的XX子元素,视作XXX方法的延伸 AA+XX:选择同一级标签AA后的所有XX元素,视作XXX方法另一种的延伸 [yyy='bbb']:属性选择器,选择yyy属性取值为bbb的元素 *:选择所有元素 xpath与CSS选择器的合用 div#xx1>input.yy2 在css里标识层级关系的字符是 > 或者 空格,(xpath里使用的/)
find_elements()::通过不同的定位方式找符合指定条件的元素集合
# 查找具有“共性”的元素,多为同一个父对象的子节点,用list对象存储易于后续调用
# 业务需求:查找引用指定图标对象的元素集合,选定如列表后逐一点击 # 查找对象“//*[@id="dd7"]”所有下属元素的src属性,是否包含有plus.gif或plusbottom.gif字符的“子元素集合”。 list2 = driver.find_elements(by=By.XPATH, value='//*[@id="dd7"]//*[contains(@src,"plus.gif") or contains(@src,"plusbottom.gif")]')
# 同样结构下,选择dd7节点下,src属性以coption开头的元素 list3= driver.find_elements(by=By.XPATH, value='//*[@id="dd7"]//*[starts-with(@src,"coption")]')
# 同样结构下,选择dd7节点下【用CSS选择方式】,src属性以coption开头的元素 list3= driver.find_elements(by=By.CSS_selector, value="[id^='coption']") # 同样结构下,选择dd7节点下【用CSS选择方式】,src属性包含有coption的元素 list3= driver.find_elements(by=By.CSS_selector, value="[id*='coption']")
len(list2)
网页元素的属性及事件处理方法
click():向对象传入单击鼠标左键的动作
clear():清除可输入文本(多用于文本框对象)
current_url:页面连接
get_attribute("XX"):获取对象XX属性数值,如找到了
is_displayed():bool值,标记元素是否可见
page_source:页面源码
send_keys("XXX") 向对象传入指定字符串(需要自行研判对象类型,是否能接受数据传入)
size():返回元素的尺寸
submit():提交按钮,只能用于包含属性type='submit'的对象,并同时存在于form表单中。一般的按钮点击,用click
text:标签内文本
title:页面标题
等待页面加载的方法
sleep(N):导入time包后,强制休眠N秒
WebDriverWait(Browser,n,h)
显示等待,针对特定对象(id='kw')的加载,等n秒、每h秒查验一次(这种查验并不刷新页面,实操中在页面等待阶段刷新页面会更快的完成页面加载)。 WebDriverWait(browser,n,h).until(expected_conditions.presence_of_element_located((By.ID,'kw')))
对于元素的加载状态有多种方法可以匹配,同时不同的对象(如iFrame框架)有专属方法,如:页面标签是否包含指定字符、指定元素是否已加载(且可见可点击)、指定元素是否已加载且在页面上的长宽均大于0、指定元素是否已经不可见、判断元素的text属性是否包含字符、判断iFrame是否可用、判断元素是否被选中
implicitly_wait(N)
隐式等待,等待页面加载N秒,期间对象加载完毕了自动终止等待,超过N秒仍未加载完毕,会抛出异常
browser.get('http://www.csdn.net') browser.implicitly_wait(5)
调整窗口尺寸
# 获取当前窗口大小,像素尺寸 driver.get_window_size() --->width:1050,height:710
set_window_size(width, height) 调整窗口到指定尺寸
driver.maximize_window() 窗口最大化
driver.minimize_window() 窗口最小化
窗口切换
switch_to.window('XX') 切换到指定页面,XX为指定页面窗口的句柄
switch_to_frame('XX') 切换到内敛框架
switch_to.parent_frame() 切换到当前框架的上一级框架
switch_to.alert 切换到页面弹窗
item = browser.switch_to_alert item.dismiss() 执行弹窗取消按钮 item.text 获取弹窗提示内容文本 item.accept() 执行弹窗确认按钮
driver.switch_to.default_content():切换当网页最外层,页面内存在多个iFramed对象时,可以快四到达最外层
鼠标操作
from selenium.webdriver import ActionChains action = ActionChains(browser)
move_to_element(X):鼠标移动到对象上方悬停
double_click(X):双击对象
context_click():单击右键
perform():以上方法在perform前都存储在内存,并不实际执行,调用perform方法后执行鼠标操作
模拟键盘操作
复杂的, 相当于ctrl+x,执行剪切动作,借此可以模拟各种“快捷键”操作 from selenium.webdriver import Keys webdriver.send_keys(Keys.CONTROL,'x')
简单的,模拟字符输入 username_input = driver.find_element(by=By.ID, value="username") username_input.send_keys("550012")
execute_script():执行“脚本文件”
get_screenshot_as_file(X):浏览器全屏截图,X代表保存的位置及文件名(含后缀),若不写完整路径则保存在主程序目录下
python-docx
引用库及基础对象定义 from docx import Document from docx.shared import Pt,RGBColor
paragraph对象
paragraph_format属性:段落样式
P1 = document.add_paragraph('早睡早起!') format_P1 = P1.paragraph_format
左右缩进 format_P1.left_indent = Pt(20) format_P1.right_indent = Pt(20)
首行缩进 format_P1.first_line_indent = Pt(20)
行间距 format_P1.line_spacing = 1 段前间距,0磅 format_P1.space_before = Pt(0) 段后间距,0磅 format_P1.space_after = Pt(0)
paragraph.style属性
除了在创建paragraph对象时设置样式,还可以在新增完之后,修改属性,属性描述时关注空格 paragraph.style = 'List Bullet'
text属性:段落文本内容
run对象
# 单一连续样式文本对象的内容 run = P1.add_run("测试连续文字内容")
字号:run.font.size = Pt(12)
字体:run.font.name = "微软雅黑"
字体颜色:run.font.color.rgb = RGBColor(235,123,10)
字体加粗:run.font.bold = True
字体增加下划线:run.font.underline = True
字体增加斜体:run.font.italic = True
字体删除线:double_strike
文本下划线:strike
双删除线:double_strike
首字母大写:all_caps
字体带阴影:shadow
runs对象
paragraph.runs罗列了段落中所有run对象的集合
table对象
添加新行 row = table.add_row()
添加新列 col = table.add_col()
cell对象
定位:cell = table.cell(0, 1)
内容:cell.text = “任意字符”
rows对象
获取表格第一行,逐列处理数据 for row in table.rows: for cell in row.cells: ……
row_count = len(table.rows)
cols对象
类似rows对象
paragraphs对象
document.paragraphs,罗列了document对象中所有paragraph对象的集合
sections对象
插入页眉 from docx.shared import Cm section = document.sections[0] header = section.header paragraph = header.paragraphs[0] run = paragraph.add_run() run.add_picture("logo.ico", height=Cm(0.91))
add_heading()
document.add_heading("标题", level=2),level参数有1-9可选项
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT # 先添加一个2级标题的空白对象 head = document.add_heading(level=2) # 设置格式,居中CENTER、左对齐LEFT、右对齐RIGHT、两端对齐JUSTIFY # 段落字符分布以填充段落的整个宽度,JUSTFY_MED以中等字符压缩率对齐、JUSTFY_HI合理的高字符压缩比率对齐、JUSTIFY_LOW以较低的字符压缩率对齐 head.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 添加标题内容,因为是先添加的格式,内容自动继承之前的格式 run = head.add_run('绿水青山') # 设置字体 run.font.name = '微软雅黑'
add_page_break()
加入分页符,新增加编辑的段落样式属性与之前页面分为2个不同对象
add_paragraph()
p1 = document.add_paragraph("早睡早起!")
在新增段落时就增加段落样式, p1 = document.add_paragraph("早睡早起!", style="ListBullet")
style的类型:
Normal、caption、Footer、Intense Quote、
Body Text、Body Text 2、Body Text 3、List Paragraph、macro、Nospacing、Quote、Subtitle、TOc Heading、Title
Header、Heading 1、Heading 2、Heading 3、Heading 4、Heading 5、Heading 6、Heading 7、Heading 8、Heading 9
List、 List 2、List 3
List Bullet、List Bullet 2、List Bullet 3
List continue、List continue 2、List continue3、List Paragraph
add_picture()
添加图片并指定大小 document.add_picture('文件名', width=Inches(1.0))
add_tabel()
table = document.add_table(rows=2, cols=2)增加了2×2的表格
Document()
创建新的空白文档:document = Document()
加载已有文档:document = Document(含完整路径及文件名的字符串)
insert_paragraph_before()
p1 = document.add_paragraph("早睡早起!") p1.insert_paragraph_before("Power!!!")
save()
保存对象:document.save(含完整路径及文件名的字符串),无路径则存在当前目录
常见用途
使用中文字体
系统默认使用英文字符,需要以下代码切换为东亚字符 from docx.oxml.ns import qn run.font.name = '宋体' run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
使用其定义文本样式
from docx.enum.style import WD STYLE_TYPE style = document.styles.add style('my_style', WD_STYLE_TYPE.CHARACTER) style.font.color.rgb = RGBColor(255,0,0) style.font.name =’黑体’ style. _element.rPr.rFonts.set(qn('w:eastAsia'),’黑体’) style.font.size = Pt(20) style.font.bold = True run1 = p.add_run(‘社会主义核心价值观是社会主义核心价值体系的内核’) run2 = p.add run('比心') # 将自定义的样式应用在run2上 run2.style = ‘my_style’ run3 = p.add run(‘体现社会主义核心价值体系的根本性质和基本特征’)
替换文件中指定段落(占位代码)
for p in document.paragraphs : if p.text ==占位1': # 清除原有内容,也可以直接令p.text = 新的内容 p._element.clear() run = p.add_run('新的内容) run.font.size = Pt(18)
pyinstall
在Pycharm的终端对话框输入指令,将代码功能打包成一个exe文件 pyinstaller -F --onefile --version-file version.txt -n 共享中心薪酬台账处理专用程序 main.py
版权信息
借用固定格式(参数)的txt(version.txt)文件,添加版权信息 pyinstaller -w --version-file version.txt --onefile main.py
StringStruct(u'CompanyName',u'共享中心人事服务室'),在Explorer中鼠标悬停显示的文件说明“公司”条目的内容
StringStruct(u'FileDescription', u'薪酬台账数据辅助统计专用'),在右键展开文件属性后,文件说明条目的内容
StringStruct(u'LegalCopyright', u'Copyright(C) 2023 BaoWu ShuKe'),在右键展开文件属性后,版权信息条目的内容
StringStruct(u'OriginalFilename',u'Salary Aggregate'),在右键展开文件属性后,原始文件条目的内容
StringStruct(u'ProductName',u'薪酬台账辅助统计数据'),在右键展开文件属性后,产品名称条目内容
StringStruct(u'ProductVersion', u'1.1.1')]),在右键展开文件属性后,文件版本条目内容
参数--add-data,可将资源文件一起打包进去 pyinstaller --add-data assets;assets angry_it_man.py
参数-w 如果不想要每次打开都会伴随着一个黑屏窗口打开 pyinstaller -w angry_it_man.py
参数-F,把所有的东西都打包进单个的exe文件中 pyinstaller -w -F angry_it_man.py
参数-n,自定义打包生成的exe文件名 pyinstaller -w -F angry_it_man.py -n 愤怒的it男
参数-i,将exe文件图标指定为ico文件 pyinstaller --add-data assets;assets -i assets\favicon.ico -w -F angry_it_man.py
爬虫与反爬虫
User-Agent限制
通过检测请求头中的User-Agent来识别爬虫
{“User-Agent”: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"}
Referrer限制
通过检测请求头中Referrer字段来识别爬虫
Cookies限制
网站通过在响应中发送Cookies来识别爬虫
频率限制
通过判断访问频率,防止爬虫对网站造成负担
JavaScript混淆
防止爬虫识别页面内容
HTTPS加密
使用HTTPS加密协议防止爬虫抓取数据
根据用途整理
ZIP压缩包
将指定目录下所有ZIP文件解压缩到当前位置 import os import zipfile # 指定文件夹路径 folder_path = "/path/to/your/folder" # 获取文件夹下所有的zip文件 zip_files = [os.path.join(folder_path, file) for file in os.listdir(folder_path) if file.endswith('.zip')] # 解压zip文件到当前位置 for zip_file in zip_files: with zipfile.ZipFile(zip_file, 'r') as zip_ref: zip_ref.extractall(folder_path) print("解压完成。")