Python 常用笔记
记录
http://blog.sina.com.cn/s/blog_73b339390102yoio.html PE:市盈率 = 股价 / 每股盈利
PEG:(市盈率相对盈利增长比率/市盈增长比率) PEG=PE/(企业年盈利增长率*100)
PB:市净率=股价 / 每股净资产
PS:市销率=股价 / 每股收入=总市值 / 销售收入
ROE:净资产收益率=报告期净利润/报告期末净资产
EPS:每股盈余=盈余 / 流通在外股数
beta值:每股收益=期末净利润 / 期末总股本 # 投资收益率计算器
import math
年均投资收益率 = (pow(终值/本金, 1/年限) -1)*100
投资收益本息 = pow((1+预期年收益率),年限)*本金
投资目标年限 = math.log(终值/本金)/math.log(1+预期年收益率) 年化收益率 = ((终值-本金)/本金)/年限 或 利息*365/(本金*天数)
利息收益 = 本金*年化收益率*天数/365 单利终值 = 本金*(1+年利率*年限) 单利现值 = 终值/(1+年利率*年限)
复利终值 = 本金*((1+年利率)**年限) 复利现值 = 终值/(1+年利率)**年限 等额本金月供 = 每期本金+每期利息
每期利息 = (贷款本金-已归还本金累计额)*月利率
每期本金 = 贷款本金÷还款月数
月供递减 = 每月应还本金×月利率
总利息 = 还款月数×(总贷款额×月利率-月利率×(总贷款额÷还款月数)*(还款月数-1)÷2+总贷款额÷还款月数) 等额本息月供 = 本金*月利率*[(1+月利率)**(年限*12)]/[(1+月利率)**(年限*12)-1]
每期利息 = 剩余本金*月利率
每期本金 = 月供-每月利息
总利息 = 还款月数×每月月供额-贷款本金
正则
小括号,大作用
一般用于获取 () 中的正则内容进行下一步操作使用,如果想要关闭这种获取能力,可以在左括号 ( 后面加上 ?: 就可以了。
另一个作用就是让括号内正则表达式进行组合,方便使用之前介绍的 ?* + 等,还有或操作符 |。
当获取了小括号里的内容后,我们也可以反向引用 () 里的内容,每一个小括号里的内容,只要没有使用 ?: ,就会被分配一个组号,从左到右从1开始递增。
在使用中,可以使用 \i 引用前面 () 里获取的内容。
除了上面使用索引的方式反向引用外,还可以使用组名的方式引用。
也就是通过左括号 ( 后面跟一个字串 ?P<组名> 的方式,来为这个组起一个别名,后面就可以通过 (?P=组名) 来引用这个组获取的内容了。例如想要匹配重复数字,可以使用 (?P<key>\d+)\s+(?P=key)。 断言
在实际使用中,我们需要对正则表达式使用断言,来对文本进行部分约束,但断言不会匹配任何文本。
\b 匹配单词的边界
\B 匹配非单词边界,会受到ASCII标记影响
\A/^ 从开始位置匹配, 如有MULTILINE标志,则^会在每个换行符后匹配
\Z/$ 在结束位置匹配,如有MULTILINE标志,则$在每个换行符前匹配
另外还有些特殊的,如正前瞻、负前瞻、正回顾、负回顾:
正前瞻(?=e):如 表达式1(?=表达式2) 表达式3 ,则表式后面的内容需要匹配表达式2;
负前瞻(?!e):如 表达式1(?!表达式2) 表达式3 ,则表式后面的内容不能匹配表达式2;
正回顾(?<=e):如 (?<=表达式2)表达式1 表达式3 ,则表式前面的内容需要匹配表达式2;
负回顾(?<!e):如 (?<!表达式2)表达式1 表达式3 ,则表式前面的内容不能匹配表达式2。
例如我们想查找一个字串 python,而这个字串后面必须要跟着 data 字串,那我们就可以使用 (python)\s+(?=data)。
这样即使字串中有 python,但我们限定了只匹配这种情况,可以大大提高了准确率。 条件表达
相信大家在平时开发过程中会经常用到三目运算符,比如 data == 1 ? 'Y' : 'N',在正则里也有类似的运算操作。
表达式:(?(判断表达式) 为真时执行表达式| 为假时执行表达式),当判断表达式匹配到内容的时候,则这里就会匹配为真时的表达式,否则就会匹配为假时的表达式。
例如:(?(\d+) [\s\d,]| [\s,]) 正则的四大功能
在我们平时用正则表达式处理字符串的时候,主要会使用到它的四大功能:
匹配:这个之前已经详细讲过了,就是看这个字符串是否符合正则表达式的语法。
提取:这个功能就是用来通过正则表达式提取指定字符串中符合要求的文本,如果有符合表达式的内容会返回一个或多个。
替换:这个功能可能用的会少一些,主要是用来将查找到的符合要求的文本,替换成我们指定的字符串。
拆分:这个功能用的更少了,其实就是用正则表达式对符合要求的文本字串进行分割。 正则的其他方法
上次已经说了四个比较常用的方法,主要用来做匹配和提取,另外还有一些方法用来做替换和拆分,在这里我们也说一下:
sub(str, t, n):这个方法用来替换操作。即将每个匹配到的文本用 str 进行替换,并返回替换后的字符串。当指定了 n 时,则最多替换 n 次。对于 str 可以是组名或者编号来引用捕获到的内容。
subn(str, t, n):这个方法和 sub() 方法基本相同,只是这个会返回一个二元组,其中除了包括结果字串,还有替换的数量。
split(str, n):这个方法是用来拆分字串操作。即将匹配到的文本对字符串进行分割,并返回一个结果列表。如果正则存在分组,则把分组匹配文本放列表中,并且每两个分割的中间作为列表的一部分。 正则匹配对象:
一般正则表达式可以匹配的对象不同,需要调用不同的方法获取。
group() 返回编号或组名匹配到的内容。默认(0)是表示匹配整个表达式内容,当然也可以指定多个,则会返回一个元组数据。
groupdict() 这个方法会返回一个字典,其中字典的 KEY 是命名的组名,VALUE 为组名对应获取的内容。
groups() 该方法会返回一个包含所有捕获内容的子分组的元组,如果指定了默认值,则这个值就会作为没有获取到的内容的值。
lastgroup() 该方法用于获取最后一个匹配到内容的组名。
lastindex() 该方法会返回最后一个匹配到内容的组编号。
start() 该方法用于指定匹配内容子分组是从字串的哪个位置开始匹配的,如果没有匹配则返回 -1。
end() 该方法用于返回当前匹配对象子分组是从哪个位置匹配结束的,如果没有匹配则返回 -1.
span() 该方法会返回一个二元组,内容为 (start(), end()) 的返回值。
pos() 该方法用于搜索字符串的开头起始位置。
endpos() 该方法用于搜索字符串的结束末尾位置。 常用正则表达式:
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
身份证号码:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
空白行:\n\s*\r
日期格式:^\d{4}-\d{1,2}-\d{1,2}
复杂密码:^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.? 总结
好了,今天就算是把 Python 正则表达式相关的都介绍完了,为了方便大家理解,讲的比较基础,但真正用在项目中的时候,可以举一反三灵活运用。OK,今天就聊这些,如果你喜欢记得点 在看。
时间转换
import time
a = '2020-03-06 19:18:00'
a1 = time.strptime(a,'%Y-%m-%d %H:%M:%S') #格式化str为time格式
print(time.strftime('%Y%m%d',a1)) #格式化time格式为str
print(time.asctime(time.localtime(time.time()))) #格式化当前时间为 Thu Apr 7 10:29:13 2016
print (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) # 格式化成2016-03-20 11:45:39形式
print (time.strftime("%a %b %d %H:%M:%S %Y", time.localtime())) # 格式化成Sat Mar 28 22:24:24 2016形式 a = "Sat Mar 28 22:24:24 2016"
print (time.mktime(time.strptime(a,"%a %b %d %H:%M:%S %Y"))) # 将格式字符串转换为时间戳
def times(ti):
strti = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ti))
point = (ti - int(ti)) * 1000
times = "%s.%03d" % (strti, point)
return times
from datetime import datetime,timedelta
import calendar
calendar.month(2016, 1) #输出2016年1月份的日历 import pandas as pd
pd.to_datetime('20160320', format='%Y%m%d').strftime('%Y%m%d') #pandas 格式化str输出
.weekday()+1 计算对应星期 from datetime import datetime,timedelta
print(datetime.now().strftime("%H:%M:%S.%f")) datetime.today() # 返回当前时间时分秒都为0
now.isoweekday() # 返回的1-7代表周一--周日
now.weekday() # 返回的0-6代表周一--到周日
datetime.strptime('20150101', "%Y%m%d") # 格式化字符串成datetime格式 (pd.to_datetime('20200130')+timedelta(days=3)).strftime('%Y%m%d') #格式化后三天的日期 now = datetime.now()+timedelta(days=3)
print(now.strftime('%Y-%m-%d')) #格式化当天后三天的日期
列表排序
import operator,json aa = [{"key": "780", "A": ["01", "03", "05", "07", "09"], "T": "1"},
{"key": "781", "A": ["01", "03", "05", "07", "09"], "T": "3"},
{"key": "782", "A": ["01", "03", "05", "07", "09"], "T": "9"}]
print(json.dumps(aa,indent=2, ensure_ascii=False))
b = sorted(aa,key=operator.itemgetter('key')) # 列表或json数据排序 #虽说loads是转回json 但是像这样key是单引号不能直接转 需要先dumps
data ="[{'a':1,'b':2,'c':3,'d':4,'e':5}]"
json1 = json.dumps(data)
print(json.loads(json1))
print(type(json1),json1) with open('222.txt','r') as f2: a = json.load(f2)
json.dump(aa,open('111.txt','w'),indent=4) json.loads() #str转json json.load() #读取文本str格式转json
json.dumps() #输出成字符串 json.dump() #将json写入文本
a = json.load(f2)
print(json.dumps(a[0],indent=4,ensure_ascii=False)) #显示中文编码 n=3
a1 = [aa[i:i + n] for i in range(0,len(aa),n)] #每三个元素一组输出一行
aa = pd.Series(range(1,9))
a1 = aa.groupby(aa.index//3).agg(list).apply(pd.Series) re常用
print(re.sub(r'[\u4e00-\u9fa5]+', ':', '1小时21分2秒')) # 替换所有汉字为:
print(re.findall('<li code="(.*)" class="ui-', i)) #截取字符 a = ''.join(str(i)+',' for i in df1['cod'].tolist())[:-1] #list转换str
[i,v for i,v in enumerate(list)] a = ['e', 'a', 'u', 'o', 'i']
a.sort() #升序 正序
a.sort(reverse=True) # 降序 逆序 不能存变量
a.sort(key= lambda x : x[1]) # 根据第二个字母排序 默认根据第一个字母排序 sorted(a) # 可存变量 保留原list 可传参数 reverse = True 降序 , reverse = False 升序(默认) sorted([[6,7,8],[2,3,4],[1,2,3]], key=lambda x: x[2]) #多维列表 根据元素排序 sorted(lis,key=lambda x:cod.index(x[0])) #多维列表 根据单维列表进行指定排序 lis为多维 cod是单列表 [[k,v] for k,v in dict(new).items() if k not in dict(B1).keys()] #二维列表转化成dict,比较两个列表i[0]的差集 ['别墅' if '别墅' in i else '车位' if '车位' in i else '高层' for i in a] #列表推导示例
[[i[0],i[2]] for i in old for v in new if i[0] == v[0] and i[2] != '0'] d = {'lily':25, 'wangjun':22, 'John':25, 'Mary':19}
sorted_keys = sorted(d) # 对字典而言,默认是对keys进行排序
print(sorted_keys)
sorted_keys1 = sorted(d, key=lambda x : x[1])
print(d_new2) d_new = sorted(d.items(), key=lambda x: x[1], reverse=True) # 根据年龄排序,返回列表形式
print(d_new)
d_new = dict(d_new) # 使用内置函数把嵌套列表转换成字典
print(d_new) sorted_values = sorted(d.values(), key=lambda x:x, reverse=False) # 排序值
print(sorted_values) 输出:
['John', 'Mary', 'lily', 'wangjun']
['wangjun', 'Mary', 'lily', 'John']
[('lily', 25), ('John', 25), ('wangjun', 22), ('Mary', 19)]
{'lily': 25, 'John': 25, 'wangjun': 22, 'Mary': 19}
[19, 22, 25, 25] #互换dick的key和value
d = {'lily':25, 'wangjun':22, 'John':25, 'Mary':19}
d_new = {v:key for key,v in d.items()}
print(d_new)
输出:{25: 'John', 22: 'wangjun', 19: 'Mary'} f.readlines()
a1 = pd.Series(list(set(df.code).union(set(df1.code)))) # 求并集 A + B
a2 = pd.Series(list(set(df.code).intersection(set(df1.code)))) #求交集 A and B
a3 = pd.Series(list(set(df.code).difference(set(a2)))) #求差集 A - B
编码转换
df.to_csv('abdata.csv', mode='a', encoding='utf_8_sig') # pandas导出csv 要指定编码 #python2 指定utf8
#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8") f.write(unicode('%s-日期 成交:%s万 成交额:%s亿'%(i[0],i[1],i[2]),"utf-8")+ '\n') #py2写入中文也有毛病要加unicode
pandas例子
from sqlalchemy import create_engine
from datetime import datetime,timedelta
import numpy as np
import pandas as pd
import tushare as ts
import matplotlib.pyplot as plt
from matplotlib import colors
from pylab import mpl #正常显示画图时出现的中文和符号
import time ts.set_token("123")
pro = ts.pro_api() pd.set_option('display.unicode.ambiguous_as_wide', True) #设置中文列名对齐
pd.set_option('display.unicode.east_asian_width', True) #设置列名对齐
pd.set_option('display.max_rows',None) #显示所有行
pd.set_option('display.max_columns',None) #显示所有列
pd.set_option('expand_frame_repr', False) #设置不换行
pd.set_option('max_colwidth',100) #设置显示最大字符
np.set_printoptions(suppress=True) # 非科学计数法 mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False pd.options.mode.chained_assignment = None %matplotlib inline #jupyter画图用
# bz.iloc[bz.groupby(['ts_code']).apply(lambda x: x['bz_sales'].idxmax())] # 分组取最大值的第一行
# bz.groupby('ts_code').apply(lambda t: t[t.bz_sales==t.bz_sales.max()])# 分组取最大值
df = query_1m.dropna(axis=0,how='any')
df[['date','time']] = df['index'].str.split(' ').apply(pd.Series)
df = df[['date','time','code','open','close','high','low']]
df.round(3).to_sql('his1m1',mysq,if_exists='append',index=False)
df.replace(regex={r'[(\')]':'',',':'+'})
df_copy.groupby("姓名")["分数"].transform(np.mean) #简易聚合
.query("代码.str.startswith('io')",engine='python') str.contains #模糊查询
df2.ts_code.value_counts() #计数重复值
df.applymap(lambda x:f'{x:.3f}'.rstrip('.0').replace('nan','0')) #取消小数尾部0
df.assign(ss=df.aa.str.findall('|'.join(df1)).str[0]) # 模糊匹配数据 长短series填充
df['aa'].astype('float') #转换整列格式
df.reset_index(drop=True) #重置index索引 并删除原索引
dfs.drop_duplicates() #去除完全相同的行保留第一行
.loc['a1']#根据index获取行 .iloc[0].name #根据行号获取行的某个值 aa.loc[:,'比_1':]获取所有行和指定列
# loc和iloc 可以更换单行、单列、多行、多列的值
df1.loc[0,'age']=25 # 思路:先用loc找到要更改的值,再用赋值(=)的方法实现更换值
df1.iloc[0,2]=25 # iloc:用索引位置来查找
.drop_duplicates().sort_values(by=['trade_date']) #删除重复值并排序 # at 、iat只能更换单个值
df1.at[0,'age']=25 # iat 用来取某个单值,参数只能用数字索引
df1.iat[0,2]=25 # at 用来取某个单值,参数只能用index和columns索引名称 df.columns = ['c','b'] #修改索引名
df.rename(columns={'a':'c'},inplace=True) #修改索引名 #pivot()和unstack()实现行转列
dfcod = counts[['cod','key','日期1','日期2']].set_index(['key','日期1','日期2','cod']).unstack()
df1 , df2 = df[['日期1','日期2','key']] , df.pivot('日期2','cod',v) #行转列 列转行参考
https://www.cnblogs.com/leohahah/p/9778304.html #新增一行 用append 但必须要得先创建DataFrame才行
df1=df1.append(new,ignore_index=True) # ignore_index=True,表示不按原来的索引,从0开始自动递增 #新增一列
tabsdetail['SH'] = sh.append([sh,sh,sh]).tolist() #sh是Series
tabs.insert(0, '总金额', [m,m*2,m*3,m*4],allow_duplicates=True) #指定位置添加一列 np.array(df0[['name','key']]).tolist() #dataframe转化list dfdata = pd.DataFrame()
dfdata = dfdata.append(df1,ignore_index=True) #pandas append必须存入变量 否则不生效 pd.DataFrame([[1,2,3],[1,2,3]],columns=['a','b','c'],index=df0.index) #创建dataframe
df0 = pd.DataFrame({'id':[3,4,5,6,7,3,4,5],
'name':[10.54,11.11,12.80,10.05,11.21,10.98,11.12,10.55]},
index=('a1','a2','a3','a4','a5','a6','a7','a8')) df0.loc[df0['id'] == 3 ,'key'] = 1
df0.loc[df0['id'] == 5 ,'key'] = 0 # 进行布尔值判断 输出符合条件
df0['key'] = np.where(df0['id'] == 3 ,1,0) pd.concat([df0, df1], axis=1) #合并两个dataframe
df.index=pd.to_datetime(df.date) # 将index 改为时间
df=df.sort_index() #排序index
df['ret']=df.close/df.close.shift(1)-1 # .shift(1) 获取下一个 .shift(-1) 获取上一个 data.sort_values(by=['标记','时间'],ascending=[False,True]) #多列排序指定升降序 df['当天'].fillna(method='ffill',inplace=True) #根据一列nan值填充上一个不为nan的值 df['a'] = (df_new.ret+1.0).cumprod() #计算当前值并累计连乘 .cumsum()累积连加 df1['ret'].diff() # 比较上一值与当前值的差
[i for i in df["close"].rolling(k).mean()] # 移动窗口list的均值
df['c'].rolling(window=10, min_periods=1, center=False).mean() #Series中计算均值 #dataframe行转列 - 只能根据相同列名不同行名数据转置 适合matplotlib用 单index日期画图 比如多个日期 每个日期中需要转置的行名不得重复
df1 = df[['cod','盈亏','日期2']].pivot('日期2','cod','盈亏').rename_axis([None], axis=1) # pivot 指定列名 行名 数据 只能固定这三个参数
df1 = df1.rename_axis(None, axis=1).reset_index() # 取消第一个columns 将其拍平
df1.index=pd.to_datetime(df1.日期2) #dataframe行转列 - 整合统计用 可以根据多个指定的index 但是set_index必须是前面列表-1的列 不然会乱 前面列表剩下的一个元素就是数据其他为index
dfcod = counts[['cod','key','盈亏','日期2','日期1']].set_index(['key','日期1','日期2','cod']).unstack()
dfcod.columns = [s1 +'_'+ str(s2) for (s1,s2) in dfcod.columns.tolist()] # 将其拍平
# dfcod.reset_index(inplace=True) # 重置index 转成正常的dataframe
dfcod.loc[['前10']] # 根据key分组显示index和数据
dfcod a1.index = a1.index.droplevel() #删除一个多索引的index-names # series 根据list 判断是否存在
df0[df0['id'].isin([3,4])] #根据list获取列表信息
df0[~df0['id'].isin([3,4])] #根据list获取列表信息 取反 # series 根据list 排序
df['words'] = df['words'].astype('category') #必须转换成这个格式
df['words'].cat.reorder_categories([1,2,3], inplace=True) # list长度相等用这个
df['words'].cat.set_categories([1,2,3], inplace=True) # list多 用这个
df['words'].cat.set_categories([1,2,3], inplace=True) # list少 用这个
df.sort_values('words', inplace=True) #df.fillna(method='bfill', inplace=True) 处理填充缺失值 inplace 是原列修改 ffill 前一个 bfill 下一个 limit=2 填充两个 #pandas 读写mysql from sqlalchemy
import create_engine
mysq = create_engine('mysql+pymysql://root:mysql.123@localhost/abdata?charset=utf8')
df.to_sql('coun',mysq,if_exists='append',index=False) # 追加数据
df.to_sql('counts',mysq,if_exists='replace',index=False) #删除并写入表
df = pd.read_sql_query('select * from cod1',mysq) # 查询mysql表 #pymysql读写mysql import pymysql
conn = pymysql.connect('127.0.0.1', 'root', 'mysql.123', 'data',charset='utf8')
cur = conn.cursor()
sql1 = "SELECT * from (SELECT * from data1 ORDER BY id DESC LIMIT %s ) aa order by id" %sum cur.execute(sql1)
c1 = cur.fetchall() #读取mysql
conn.commit() #写入mysql cur.close()
conn.close()
DataFrame样式设置
def show(v):
col = 'black' if v > 0 else 'green'
return 'color:%s'%col def background_gradient(s, m, M, cmap='PuBu', low=0, high=0.8):
rng = M - m
norm = colors.Normalize(m - (rng * low),M + (rng * high))
normed = norm(s.values)
c = [colors.rgb2hex(x) for x in plt.cm.get_cmap(cmap)(normed)]
return ['" style="color: rgb(128, 0, 0);">' % color for color in c] def highlight_max(s,m):
is_max = s == m
return ['" style="color: rgb(128, 0, 0);">' if v else '' for v in is_max] tabs.style.applymap(show).background_gradient(cmap='Reds',axis = 1,low = 0,high = 1,subset = set1).\
apply(background_gradient,cmap='Purples',m=tabs[set2].min().min(),M=tabs[set2].max().max(),low=0,high=1,subset = set2).\
apply(highlight_max,m=tabs[set2].max().max()).background_gradient(cmap='Wistia',axis = 1,subset=['总金额']) accdeteil.style.applymap(show).background_gradient(cmap='Reds',axis = 1,low = 0,high = 1).\
background_gradient(cmap='Reds',axis = 1,low = 0,high = 1 ,subset=set2).\
background_gradient(cmap='Purples',axis = 1,low = 0,high = 1,subset = pd.IndexSlice['前10',:'9']).\
background_gradient(cmap='Purples',axis = 1,low = 0,high = 1,subset = pd.IndexSlice['前20',:'9']).\
background_gradient(cmap='Purples',axis = 1,low = 0,high = 1,subset = pd.IndexSlice['前05','1_':]).\
background_gradient(cmap='Purples',axis = 1,low = 0,high = 1,subset = pd.IndexSlice['前15','1_':]).\
background_gradient(cmap='GnBu',axis = 0,low = 0,high = 1 ,subset=['SH_']).\
apply(highlight_max,m=tabs[set2].max().max()) #可参考
https://blog.csdn.net/xiaodongxiexie/article/details/71202279 #颜色样式
https://matplotlib.org/tutorials/colors/colormaps.html
https://www.sioe.cn/yingyong/yanse-rgb-16/
#css 颜色大全
https://www.cnblogs.com/ifeiyun/p/15925282.html
pandas作图
import matplotlib.pyplot as plt ax1 = df1[['策略净值','指数净值']].astype(float).plot(figsize=(15,8)) #dataframe折线图
ax1 = ax1.axhline(y=1,ls=":",c="r"),ax1.legend(loc = 'upper right') #标记0线和指定图例位置
plt.title('策略简单回测%s'%x,size=15)
plt.xlabel('') for i in range(len(df1)):
if df1['当天仓位'][i]==0 and df1['当天仓位'].shift(-1)[i]==1:
plt.annotate('买',xy=(df1.index[i],df1.策略净值[i]),arrowprops=dict(facecolor='r',shrink=0.05)) #标记买卖点
if df1['当天仓位'][i]==0 and df1['当天仓位'].shift(1)[i]==1:
plt.annotate('卖',xy=(df1.index[i],df1.策略净值[i]),arrowprops=dict(facecolor='g',shrink=0.1)) bbox = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9) #指定文字边框样式
t = f'累计收益率:策略{TA1}%,指数{TA2}%;\n年化收益率:策略{AR1}%,指数{AR2}%;'+\
f'\n最大回撤: 策略{MD1}%,指数{MD2}%;\n策略alpha: {round(alpha,2)},策略beta:{round(beta,2)}; \n夏普比率: {S}'
plt.text(df1.index[0], df1['指数净值'].min(),text,size=13,bbox=bbox) #指定位置加文字框
ax=plt.gca() #设置图形样式
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
plt.show()
爬虫例子
from bs4 import BeautifulSoup
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
} htm = requests.get(url=url,headers=headers,timeout=30,stream=False).text
soup = BeautifulSoup(htm, 'html.parser')
txt = soup.find_all('div', class_='lax-s')
#txt = soup.find('div', class_='qi').children #etree方式获取 原文 https://mp.weixin.qq.com/s/c2Sg_LVTjOokePY2lxCGSA
import requests
import pandas as pd
from pprint import pprint
from lxml import etree
import time
import warnings
warnings.filterwarnings("ignore") for i in range(1,15):
print("正在爬取第" + str(i) + "页的数据")
url = "https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,"+str(i)+'.html?'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
}
web = requests.get(url, headers=headers)
web.encoding = "gbk"
dom = etree.HTML(web.text)
#print(etree.tostring(dom, encoding="utf-8", pretty_print=True).decode("utf-8")) #打印整个html 不能直接print
# 1、岗位名称
job_name = dom.xpath('//div[@class="dw_table"]/div[@class="el"]//p/span/a[@target="_blank"]/@title')
# 2、公司名称
company_name = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t2"]/a[@target="_blank"]/@title')
# 3、工作地点
address = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t3"]/text()')
# 4、工资:工资这一列有空值,为了保证数据框的一致性。采取以下方式进行数据的获取
salary_mid = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t4"]')
salary = [i.text for i in salary_mid] #这里None也占一个元素 保持长度一致
# 5、发布日期
release_time = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t5"]/text()')
#----------------------------------------------------------------------------------------------#
# 下面获取二级网址的信息。为了获取二级网址的信息,首先需要获取二级网址的url
# 6、获取二级网址url
deep_url = dom.xpath('//div[@class="dw_table"]/div[@class="el"]//p/span/a[@target="_blank"]/@href')
RandomAll = []
JobDescribe = []
CompanyType = []
CompanySize = []
Industry = []
for i in range(len(deep_url)):
web_test = requests.get(deep_url[i], headers=headers)
web_test.encoding = "gbk"
dom_test = etree.HTML(web_test.text)
# 7、爬取经验、学历信息,先合在一个字段里面,以后再做数据清洗。命名为random_all
random_all = dom_test.xpath('//div[@class="tHeader tHjob"]//div[@class="cn"]/p[@class="msg ltype"]/text()')
# 8、岗位描述性息
job_describe = dom_test.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]/p/text()')
# 9、公司类型
company_type = dom_test.xpath('//div[@class="tCompany_sidebar"]//div[@class="com_tag"]/p[1]/@title')
# 10、公司规模(人数)
company_size = dom_test.xpath('//div[@class="tCompany_sidebar"]//div[@class="com_tag"]/p[2]/@title')
# 11、所属行业(公司)
industry = dom_test.xpath('//div[@class="tCompany_sidebar"]//div[@class="com_tag"]/p[3]/@title')
# 将上述信息保存到各自的列表中
RandomAll.append(random_all)
JobDescribe.append(job_describe)
CompanyType.append(company_type)
CompanySize.append(company_size)
Industry.append(industry)
# 为了反爬,设置睡眠时间
time.sleep(1)
# 由于我们需要爬取很多页,为了防止最后一次性保存所有数据出现的错误,因此,我们每获取一夜的数据,就进行一次数据存取。
df = pd.DataFrame()
df["岗位名称"] = job_name
df["公司名称"] = company_name
df["工作地点"] = address
df["工资"] = salary
df["发布日期"] = release_time
df["经验、学历"] = RandomAll
df["公司类型"] = CompanyType
df["公司规模"] = CompanySize
df["所属行业"] = Industry
df["岗位描述"] = JobDescribe
# 这里在写出过程中,有可能会写入失败,为了解决这个问题,我们使用异常处理。
try:
df.to_csv("job_info.csv", mode="a+", header=None, index=None, encoding="gbk")
except:
print("当页数据写入失败")
time.sleep(1)
print("完毕")
OCR图片识别
#需要安装 tesseract-ocr(需要环境变量) 、chi_sim.traineddata 、 pytesseract-0.2.4 from PIL import Image
import pytesseract,os,re png = r'D:\123\111.png'
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files (x86)\Tesseract-OCR\tesseract.exe'
img = Image.open(png)
tim = os.stat(png).st_mtime
img1 = img.size
aa = pytesseract.image_to_string(img, lang='chi_sim')
print(img1,tim)
print(aa)
webdriver自动化测试
#需要安装 chromedriver-v69 、ChromeSetup_64_69.exe from selenium import webdriver
from selenium.webdriver.common.keys import Keys try:
driver = webdriver.Chrome()
driver.get("http://user/login")
time.sleep(1) driver.find_element_by_id('username').send_keys('123123')
driver.find_element_by_id('password').send_keys('123123')
driver.find_element_by_id('login').click()
time.sleep(2) driver.find_element_by_xpath('//*[@id="header"]/div[7]/div/div[1]/ul/li[4]/a').click()
time.sleep(2)
driver.find_elements_by_class_name('content')[2].click()
time.sleep(2) s1 = driver.find_element_by_class_name('i1').text
s2 = s1[3:6]
s3 = driver.find_element_by_id('pre-kanjiang').text
s4 = driver.find_element_by_xpath('//*[@id="money"]/strong').text
s5 = driver.find_element_by_xpath('//*[@id="money"]/em').text
print('key=', s2, 'time=', s3, s5 + '=', s4)
fs.write('key=' + s2 + '\n' + 'time=' + s3 + '\n' + s5 + '=' + s4 + '\n')
time.sleep(2) if int(s2) == int(s.get('key')):
elements = driver.find_elements_by_class_name('code') if 'A' in s.keys():
data_values = s.get('A')
for i in data_values:
a_button_index = int(i) - 1
elements[a_button_index].click()
print('a_button_index = ', a_button_index)
fs.write('a_button_index = ' + str(a_button_index) + '\n')
if 'B' in s.keys():
data_values = s.get('B')
for j in data_values:
b_button_index = int(j) + 9
elements[b_button_index].click()
print('b_button_index = ', b_button_index)
fs.write('b_button_index = ' + str(b_button_index) + '\n')
if 'C' in s.keys():
data_values = s.get('C')
for k in data_values:
c_button_index = int(k) + 19
elements[c_button_index].click()
print('c_button_index = ', c_button_index)
fs.write('c_button_index = ' + str(c_button_index) + '\n') time.sleep(1)
driver.find_elements_by_name('danwei')[1].click()
driver.find_element_by_class_name('txt').clear()
driver.find_element_by_class_name('txt').send_keys(int(s.get('T')) * 1)
driver.find_element_by_class_name('tztj-hover').click()
time.sleep(2)
driver.find_element_by_class_name('tz-true-hover').click() time.sleep(2)
driver.find_element_by_xpath("/html/body/div[2]/div[3]/div/button[1]").send_keys(Keys.ENTER)
time.sleep(2)
driver.quit() except Exception as e:
print(e) 自动点击 url = "https://1111" chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('User-Agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36"')
chromeOptions.add_argument('lang=zh_CN.UTF-8')
driver = webdriver.Chrome(chrome_options=chromeOptions)
driver.get(url)
driver.delete_all_cookies() #清空cookie
driver.add_cookie({'name':'JSESSIONID','value':'D11197B'})
time.sleep(1)
driver.refresh() #刷新页面
time.sleep(1) driver.switch_to_frame(0) #进入第一个frame
# driver.switch_to.default_content() #回退frame drilis = driver.find_elements_by_class_name('ui-question-options-order') #获取所有选项的元素
oplis = [drilis[i:i + 4] for i in range(0,len(drilis),4)] # 每个ABCD一组
print(oplis) for i,v in zip(oplis,idlis):
if v == 'A':i[0].click()
elif v == 'B':i[1].click()
elif v == 'C':i[2].click()
elif v == 'D':i[3].click()
time.sleep(0.1)
selenium 获取网页源代码
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
from time import ctime
import requests, json, os, time,pymysql,re
from collections import deque
from shutil import copyfile chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('User-Agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36"')
chromeOptions.add_argument('lang=zh_CN.UTF-8')
driver = webdriver.Chrome(chrome_options=chromeOptions) for i in aa['schedules']:
url = i['pcUrl']
name = i['title'] driver.get(url)
#driver.page_source #打印页面信息
time.sleep(1) vi = driver.find_element_by_id("playback-video-wrapper")
vi1 = vi.get_attribute("innerHTML").split('src=')[1].split('"')[1] #打印部分页面信息
print([name,vi1])
time.sleep(1) time.sleep(1)
driver.quit()
json递归
import json,time,re class FindKey(object):
def __init__(self, obj):
self.json_object = None
if isinstance(obj, str):
self.json_object = json.loads(obj)
elif obj != None:
self.json_object = obj
else:
raise TypeError("Unexpected object type.Can not read from NoneType") def get_obj_contain_key(self, key):
result_list = []
self.__search_obj_contain_key(
json_object=self.json_object,
old_path="",
key=key,
result_list=result_list)
return result_list def __search_obj_contain_key(self, json_object, old_path:str, key, result_list):
if isinstance(json_object, dict):
for k,v in json_object.items():
if k == key:
result_list.append(
{
"path": old_path,
"obj": json_object
}
)
if isinstance(v, dict) or isinstance(v, list):
self.__search_obj_contain_key(
json_object=v,
old_path= old_path + "[\"{}\"]".format(k),
key=key,
result_list=result_list
)
elif isinstance(json_object, list):
tmp_index = 0
for item in json_object:
if item == key:
result_list.append(
{
"path": old_path,
"obj": json_object
}
)
if isinstance(item, dict) or isinstance(item, list):
self.__search_obj_contain_key(
json_object=item,
old_path= old_path + "[{}]".format(tmp_index),
key=key,
result_list=result_list
)
tmp_index += 1
return None json_str = "{\"a_dict\":{\"a_list\":[\"item1\", \"ip\", \"item2\"]}, "+\
"\"ip\":\"8.8.8.8\", \"b_dict\":{\"ip\":\"192.168.1.1\", "+\
"\"c_dict\":{\"ips\":[{\"ip\":\"192.168.1.2\"},"+\
"{\"ip\":\"192.168.1.3\"},{\"ip\":\"192.168.1.4\"}]} } }" json_obj = json.loads(json_str)
print(json.dumps(json_obj,indent=2, ensure_ascii=False)) tool = FindKey(json_obj)
res = tool.get_obj_contain_key("ip")
for item in res:
print("path=",item["path"])
print("obj=",item["obj"]) # with open('123.txt','r',encoding='utf-8') as f2:
# a = json.load(f2)
# tool = FindKey(a)
# res = tool.get_obj_contain_key("material")
# for item in res:
# sy = item["path"].replace('[','').split(']')
# # print(item["path"],len(sy))
# if len(sy) == 6:
# lj = a[int(sy[0])]["list"][int(sy[2])]["title"]
# else:
# lj = ''.join(i for i in [a[int(sy[0])]["title"],' - ',
# a[int(sy[0])]["list"][int(sy[2])]["title"],' - ',
# a[int(sy[0])]["list"][int(sy[2])]["list"][int(sy[4])]["title"]])
# print(len(sy),lj,"'"+item["obj"]['title']+".pdf',")
# # print("'"+item["obj"]['material']+"',") # with open('a.txt','r',encoding='utf-8') as f:
# data = json.loads(f.readline())
# json_obj = data
# # print(json.dumps(json_obj,indent=2, ensure_ascii=False)) # tool = FindKey(json_obj)
# res = tool.get_obj_contain_key("pcUrl")
# aa = []
# for item in res:
# # print("path=",item["path"])
# # print("obj=",item["obj"],'\n')
# if item["obj"]['title'][1] == '2':
# aa.append(item["obj"])
# # print([item["obj"]['title']+'.mp4',item["obj"]['pcUrl']],',') '''
from selenium import webdriver
from bs4 import BeautifulSoup chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('User-Agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36"')
chromeOptions.add_argument('lang=zh_CN.UTF-8')
driver = webdriver.Chrome(chrome_options=chromeOptions) for i in aa:
url = i['pcUrl']
name = i['title'] driver.get(url)
#driver.page_source #打印页面信息
time.sleep(1) vi = driver.find_element_by_id("playback-video-wrapper")
vi1 = vi.get_attribute("innerHTML").split('src=')[1].split('"')[1] #打印部分页面信息
print([name+'.mp4',vi1],',')
time.sleep(1) time.sleep(1)
driver.quit()
'''
下载器
import json,requests,os,time def yddown(lis):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3626.96 Safari/537.36',
'Accept' : '*/*',
'Origin' : 'https://live.youdao.com',
'Sec-Fetch-Site' : 'cross-site',
'Sec-Fetch-Mode' : 'cors',
'Sec-Fetch-Dest' : 'empty',
'Referer' : 'https://live.youdao.com/',
'Accept-Encoding' : 'gzip, deflate, br',
'Accept-Language' : 'zh-CN,zh;q:0.9'
} for i in lis:
time.sleep(3)
startTime = time.time()
names = i[0]
u = i[1]
r = requests.get(u, timeout=600, headers=headers)
# names = '经析.mp4'
# u = 'https://stream2.mp4'
# r = requests.get(u,timeout=600,headers=headers)
# with open(os.path.join(os.path.dirname(os.path.abspath("D:/")),'aa.pm4'),"wb") as f:f.write(r.content)
downsize = 0
with(open('D:/0yd/'+names, 'wb')) as f:
for chunk in r.iter_content(chunk_size=10000):
if chunk:
f.write(chunk)
downsize += len(chunk)
line = '%s 耗时 %ds, 共 %.2f MB' % (names,time.time()-startTime, downsize / 1024 / 1024)
print(line)
return lis = [
['aaa.mp4','https://staa.mp4']
] yddown(lis)
cs客户端自动化测试
import os,sys,time
import pywinauto
import pywinauto.clipboard
import pywinauto.application
import win32clipboard as wincb
import win32con def winmax(): #窗口最大化
if main_window.get_show_state() != 3:
main_window.maximize()
main_window.set_focus() def winmin(): #窗口最小化
if main_window.GetShowState() != 2:
main_window.Minimize() def closepopup(): #关闭弹窗
popup_hwnd = main_window.PopupWindow()
if popup_hwnd:
popup_window = app.window_(handle=popup_hwnd)
popup_window.SetFocus()
popup_window.Button.Click()
return True
return False def pos(): #获取持仓并刷新复制到剪切板
dialog_window.CCustomTabCtrl.ClickInput(coords=(30, 8)) #点击持仓
dialog_window.Button5.click()
time.sleep(0.5)
dialog_window.Button5.click()
# time.sleep(0.2)
# dialog_window.CVirtualGridCtrl.RightClick(coords=(100, 70)) # 右击持仓
# main_window.TypeKeys('C') #如果能复制了 就把这些打开 def copypos(): #获取剪切板信息
wincb.OpenClipboard()
t = wincb.GetClipboardData(win32con.CF_TEXT)
wincb.CloseClipboard()
return t def copyposition(): #导出持仓并读取
dialog_window.CVirtualGridCtrl.RightClick(coords=(100, 70)) # 右击持仓
main_window.TypeKeys('S')
time.sleep(0.1)
closepopup()
closepopup()
with open('C:/Users/Administrator/Desktop/table.xls','r') as f:
return [[i.split('\t')[1],i.split('\t')[3],i.split('\t')[4]] for i in f.readlines()[1:]] def order(x): #B是买 S是卖 开始下单
dialog_window.TypeKeys("{F6}")
if x == 'B':
for i in Blis:
# dialog_window.window(title_re='重填').click()
time.sleep(0.1)
dialog_window.Edit1.set_focus()
dialog_window.Edit1.set_edit_text(i[0])
dialog_window.Edit3.set_edit_text(i[1])
time.sleep(0.2)
dialog_window.Button1.click()
if x == 'S':
for i in Slis:
time.sleep(0.1)
dialog_window.Edit4.set_focus()
dialog_window.Edit4.set_edit_text(i[0])
dialog_window.Edit6.set_edit_text(i[1])
time.sleep(0.2)
dialog_window.Button2.click() def cancel(x): #撤单 B:撤买 S:撤卖 all:全撤
dialog_window.CCustomTabCtrl.ClickInput(coords=(140, 8)) #点击委托
try:
dialog_window.Button6.Click()
time.sleep(0.1)
dialog_window.Button6.Click()
except Exception as e:
pass
if x == 'B':
dialog_window.Button8.Click()
if x == 'S':
dialog_window.Button9.Click()
if x == 'all':
dialog_window.Button7.Click()
time.sleep(0.1)
closepopup() def BSlist(x): #返回买卖剩余量 B是买 S是卖
global Blis
global Slis
pos() #可以复制了就打开old
# old = [[i.split('\t')[1],i.split('\t')[3],i.split('\t')[4]] for i in copypos().decode("gb2312").split('\r\n')[1:]]
old = copyposition()
new = [[i[0],'0'] for i in Slis if int(i[1]) > 0 ]+Blis
if x == 'B':
B1 = [[v[0],str(int(i[1])-int(v[1]))] for i in [i for i in new if i[1] != '0'] for v in old if i[0] == v[0]]
B2 = [[k,v] for k,v in dict([i for i in new if i[1] != '0']).items() if k not in dict(B1).keys()]
Blis = [i for i in B1 if i[1] != '0']+B2
return Blis
if x == 'S':
Slis = [[i[0],i[2]] for i in old for v in [i for i in new if i[1] == '0'] if i[0] == v[0] and i[2] != '0']
return Slis if __name__ == '__main__':
files = [i for i in os.listdir('D:/abdata/csv/') if 'cod' in i] Blis = []
Slis = []
with open('D:/abdata/csv/'+sorted(files)[-1],'r',encoding='utf-8') as f:
for i in f:
i = i.strip().split(',')
if i[4] == '0' and int(i[2]) >0:Blis.append([i[0],i[2]])
if i[4] == '1' and int(i[2]) >0:Slis.append([i[0],i[2]]) '''
order(x): # 需要传参 B是买 S是卖
cancel(x): # 撤单 B:撤买 S:撤卖 all:全撤
BSlist(x): # 返回买卖剩余量 B是买 S是卖
winmax(): # 窗口最大化 winmin(): # 窗口最小化
pos(): # 获取持仓并刷新复制到剪切板 copypos(): # 获取剪切板信息
closepopup(): #关闭弹窗 copyposition(): #导出持仓并读取
''' title = '网上股票交易系统5.0'
app = pywinauto.application.Application()
app.connect(title=title)
top_hwnd = pywinauto.findwindows.find_window(title=title)
dialog_hwnd = pywinauto.findwindows.find_windows(top_level_only=False, class_name=u'#32770', parent=top_hwnd)[0]
wanted_hwnds = pywinauto.findwindows.find_windows(top_level_only=False, parent=dialog_hwnd)
main_window = app.window(handle=top_hwnd)
dialog_window = app.window(handle=dialog_hwnd)
winmax() #窗口最大
# pos() #获取复制持仓 # old = [[i.split('\t')[1],i.split('\t')[3]] for i in copypos().decode("gb2312").split('\r\n')[1:]]
# new = [[i[0],'0'] for i in Slis if int(i[1]) > 0 ]+Blis B = 1
S = 1 while S > 0 :
closepopup()
time.sleep(0.5)
# pos() #获取复制持仓
Slis = BSlist('S')
S = len(Slis)
if S > 0:
closepopup()
order('S')
closepopup()
time.sleep(2)
cancel('all')
time.sleep(2) while B > 0 :
time.sleep(0.5)
closepopup()
# pos() #获取复制持仓
Blis = BSlist('B')
B = len(Blis)
if B > 0:
closepopup()
order('B')
closepopup()
time.sleep(2)
cancel('all')
time.sleep(2)
vba合并所有工作表sheet为一个 Sub 合并当前工作簿下的所有工作表()
Application.ScreenUpdating = False
For j = 1 To Sheets.Count
If Sheets(j).Name <> ActiveSheet.Name Then
X = Range("A65536").End(xlUp).Row + 1
Sheets(j).UsedRange.Copy Cells(X, 1) '复制内容
End If
Next
Range("B1").Select '表明从B1单元格开始复制合并的内容
Application.ScreenUpdating = True
MsgBox "当前工作簿下的全部工作表已经合并完毕!", vbInformation, "提示"
End Sub
常用pandas技巧
# 常用pandas技巧 #1.计算变量缺失率
df=pd.read_csv('titanic_train.csv')
def missing_cal(df):
"""
df :数据集 return:每个变量的缺失率
"""
missing_series = df.isnull().sum()/df.shape[0]
missing_df = pd.DataFrame(missing_series).reset_index()
missing_df = missing_df.rename(columns={'index':'col',
0:'missing_pct'})
missing_df = missing_df.sort_values('missing_pct',ascending=False).reset_index(drop=True)
return missing_df
missing_cal(df)
#如果需要计算样本的缺失率分布,只要加上参数axis=1. #2.获取分组里最大值所在的行方法
#分为分组中有重复值和无重复值两种。无重复值的情况。
df = pd.DataFrame({'Sp':['a','b','c','d','e','f'], 'Mt':['s1', 's1', 's2','s2','s2','s3'], 'Value':[1,2,3,4,5,6], 'Count':[3,2,5,10,10,6]})
df
df.iloc[df.groupby(['Mt']).apply(lambda x: x['Count'].idxmax())]
#先按Mt列进行分组,然后对分组之后的数据框使用idxmax函数取出Count最大值所在的列,再用iloc位置索引将行取出。有重复值的情况
df["rank"] = df.groupby("ID")["score"].rank(method="min", ascending=False).astype(np.int64)
df[df["rank"] == 1][["ID", "class"]]
#对ID进行分组之后再对分数应用rank函数,分数相同的情况会赋予相同的排名,然后取出排名为1的数据。 #3.多列合并为一行
df = pd.DataFrame({'id_part':['a','b','c','d'],
'pred':[0.1,0.2,0.3,0.4],
'pred_class':['women','man','cat','dog'],
'v_id':['d1','d2','d3','d1']})
df.groupby(['v_id']).agg({'pred_class': [', '.join],'pred': lambda x: list(x),
'id_part': 'first'}).reset_index() #4.删除包含特定字符串所在的行
df = pd.DataFrame({'a':[1,2,3,4], 'b':['s1', 'exp_s2', 's3','exps4'], 'c':[5,6,7,8], 'd':[3,2,5,10]})
df[df['b'].str.contains('exp')] #5.组内排序
df = pd.DataFrame([['A',1],['A',3],['A',2],['B',5],['B',9]], columns = ['name','score'])
#介绍两种高效地组内排序的方法。
df.sort_values(['name','score'], ascending = [True,False])
df.groupby('name').apply(lambda x: x.sort_values('score', ascending=False)).reset_index(drop=True) #6.选择特定类型的列
drinks = pd.read_csv('data/drinks.csv')
# 选择所有数值型的列
drinks.select_dtypes(include=['number']).head()
# 选择所有字符型的列
drinks.select_dtypes(include=['object']).head()
drinks.select_dtypes(include=['number','object','category','datetime']).head()
# 用 exclude 关键字排除指定的数据类型
drinks.select_dtypes(exclude=['number']).head() #7.字符串转换为数值
df = pd.DataFrame({'列1':['1.1','2.2','3.3'],
'列2':['4.4','5.5','6.6'],
'列3':['7.7','8.8','-']})
df
df.astype({'列1':'float','列2':'float'}).dtypes
#用这种方式转换第三列会出错,因为这列里包含一个代表 0 的下划线,
#pandas 无法自动判断这个下划线。为了解决这个问题,可以使用 to_numeric() #函数来处理第三列,让 pandas 把任意无效输入转为 NaN。
df = df.apply(pd.to_numeric, errors='coerce').fillna(0) #8.优化 DataFrame 对内存的占用
#方法一:只读取切实所需的列,使用usecols参数
cols = ['beer_servings','continent']
small_drinks = pd.read_csv('data/drinks.csv', usecols=cols)
#方法二:把包含类别型数据的 object 列转换为 Category 数据类型,通过指定 dtype 参数实现。
dtypes ={'continent':'category'}
smaller_drinks = pd.read_csv('data/drinks.csv',usecols=cols, dtype=dtypes) #9.根据最大的类别筛选 DataFrame
movies = pd.read_csv('data/imdb_1000.csv')
counts = movies.genre.value_counts()
movies[movies.genre.isin(counts.nlargest(3).index)].head() #10.把字符串分割为多列
df = pd.DataFrame({'姓名':['张 三','李 四','王 五'],
'所在地':['北京-东城区','上海-黄浦区','广州-白云区']})
df
df.姓名.str.split(' ', expand=True) #11.把 Series 里的列表转换为 DataFrame
df = pd.DataFrame({'列1':['a','b','c'],'列2':[[10,20], [20,30], [30,40]]})
df
df_new = df.列2.apply(pd.Series)
pd.concat([df,df_new], axis='columns') #12.用多个函数聚合
orders = pd.read_csv('data/chipotle.tsv', sep='\t')
orders.groupby('order_id').item_price.agg(['sum','count']).head() #13.分组聚合
import pandas as pd
df = pd.DataFrame({'key1':['a', 'a', 'b', 'b', 'a'],
'key2':['one', 'two', 'one', 'two', 'one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)})
df for name, group in df.groupby('key1'):
print(name)
print(group) dict(list(df.groupby('key1'))) #通过字典或Series进行分组
people = pd.DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
mapping = {'a':'red', 'b':'red', 'c':'blue',
'd':'blue', 'e':'red', 'f':'orange'}
by_column = people.groupby(mapping, axis=1)
by_column.sum()
Pandas自动爬取Web图表
#Pandas自动爬取Web图表 import pandas as pd
url = "http://fund.eastmoney.com/fund.html"
data = pd.read_html(url,attrs = {'id': 'oTable'})
# 查看表格数量
tablenum = len(data)
print(tablenum) '''
详细用法
pandas.read_html( io, match='.+', flavor=None, header=None, index_col=None, skiprows=None, attrs=None, parse_dates=False, thousands=', ', encoding=None, decimal='.', converters=None, na_values=None, keep_default_na=True, displayed_only=True) 详细参数
「io:」 str, path object 或 file-like objectURL,file-like对象或包含HTML的原始字符串。请注意,lxml仅接受http,ftp和文件url协议。如果您的网址以'https'您可以尝试删除's'。
「match:」 str 或 compiled regular expression, 可选参数将返回包含与该正则表达式或字符串匹配的文本的表集。除非HTML非常简单,否则您可能需要在此处传递非空字符串。默认为“。+”(匹配任何非空字符串)。默认值将返回页面上包含的所有表。此值转换为正则表达式,以便Beautiful Soup和lxml之间具有一致的行为。
「flavor:」 str 或 None要使用的解析引擎。‘bs4’和‘html5lib’彼此同义,它们都是为了向后兼容。默认值None尝试使用lxml解析,如果失败,它会重新出现bs4+html5lib。
「header:」 int 或 list-like 或 None, 可选参数该行(或MultiIndex)用于创建列标题。
「index_col:」 int 或 list-like 或 None, 可选参数用于创建索引的列(或列列表)。
「skiprows:」 int 或 list-like 或 slice 或 None, 可选参数解析列整数后要跳过的行数。从0开始。如果给出整数序列或切片,将跳过该序列索引的行。请注意,单个元素序列的意思是“跳过第n行”,而整数的意思是“跳过n行”。
「attrs:」 dict 或 None, 可选参数这是属性的词典,您可以传递该属性以用于标识HTML中的表。在传递给lxml或Beautiful Soup之前,不会检查它们的有效性。但是,这些属性必须是有效的HTML表属性才能正常工作。例如, attrs = {'id': 'table'} 是有效的属性字典,因为‘id’ HTML标记属性是任何HTML标记的有效HTML属性,这个文件。attrs = {'asdf': 'table'} 不是有效的属性字典,因为‘asdf’即使是有效的XML属性,也不是有效的HTML属性。可以找到有效的HTML 4.01表属性这里。可以找到HTML 5规范的工作草案这里。它包含有关现代Web表属性的最新信息。
「parse_dates:」 bool, 可选参数参考read_csv()更多细节。
「thousands:」 str, 可选参数用来解析成千上万个分隔符。默认为','。
「encoding:」 str 或 None, 可选参数用于解码网页的编码。默认为NoneNone保留先前的编码行为,这取决于基础解析器库(例如,解析器库将尝试使用文档提供的编码)。
「decimal:」 str, 默认为 ‘.’可以识别为小数点的字符(例如,对于欧洲数据,请使用“,”)。
「converters:」 dict, 默认为 None用于在某些列中转换值的函数的字典。键可以是整数或列标签,值是采用一个输入参数,单元格(而非列)内容并返回转换后内容的函数。
「na_values:」 iterable, 默认为 None自定义NA值。
「keep_default_na:」 bool, 默认为 True如果指定了na_values并且keep_default_na为False,则默认的NaN值将被覆盖,否则将附加它们。
「displayed_only:」 bool, 默认为 True是否应解析具有“display:none”的元素。 最后, read_html() 仅支持静态网页解析,你可以通过其他方法获取动态页面加载后response.text 传入 read_html() 再获取表格数据。
'''
67个常用pandas函数
#67个pandas函数 import pandas as pd #导⼊数据
pd.DataFrame() # 自己创建数据框,用于练习
pd.read_csv(filename) # 从CSV⽂件导⼊数据
pd.read_table(filename) # 从限定分隔符的⽂本⽂件导⼊数据
pd.read_excel(filename) # 从Excel⽂件导⼊数据
pd.read_sql(query,connection_object) # 从SQL表/库导⼊数据
pd.read_json(json_string) # 从JSON格式的字符串导⼊数据
pd.read_html(url) # 解析URL、字符串或者HTML⽂件,抽取其中的tables表格 #导出数据
df.to_csv(filename) #导出数据到CSV⽂件
df.to_excel(filename) #导出数据到Excel⽂件
df.to_sql(table_name,connection_object) #导出数据到SQL表
df.to_json(filename) #以Json格式导出数据到⽂本⽂件
writer=pd.ExcelWriter('test.xlsx',index=False)
df1.to_excel(writer,sheet_name='单位') #和writer.save(),将多个数据帧写⼊同⼀个⼯作簿的多个sheet(⼯作表) #查看数据
df.head(n) # 查看DataFrame对象的前n⾏
df.tail(n) # 查看DataFrame对象的最后n⾏
df.shape() # 查看⾏数和列数
df.info() # 查看索引、数据类型和内存信息
df.columns() # 查看字段(⾸⾏)名称
df.describe() # 查看数值型列的汇总统计
s.value_counts(dropna=False) # 查看Series对象的唯⼀值和计数
df.apply(pd.Series.value_counts) # 查看DataFrame对象中每⼀列的唯⼀值和计数
df.isnull().any() # 查看是否有缺失值
df[df[column_name].duplicated()] # 查看column_name字段数据重复的数据信息
df[df[column_name].duplicated()].count() # 查看column_name字段数据重复的个数 #数据选取
df[col] # 根据列名,并以Series的形式返回列
df[[col1,col2]] # 以DataFrame形式返回多列
s.iloc[0] # 按位置选取数据
s.loc['index_one'] # 按索引选取数据
df.iloc[0,:] # 返回第⼀⾏
df.iloc[0,0] # 返回第⼀列的第⼀个元素
df.loc[0,:] # 返回第⼀⾏(索引为默认的数字时,⽤法同df.iloc),但需要注意的是loc是按索引,iloc参数只接受数字参数
df.ix[[:5],["col1","col2"]] # 返回字段为col1和col2的前5条数据,可以理解为loc和iloc的结合体。
df.at[5,"col1"] # 选择索引名称为5,字段名称为col1的数据
df.iat[5,0] # 选择索引排序为5,字段排序为0的数据 #数据处理
df.columns= ['a','b','c'] # 重命名列名(需要将所有列名列出,否则会报错)
pd.isnull() # 检查DataFrame对象中的空值,并返回⼀个Boolean数组
pd.notnull() # 检查DataFrame对象中的⾮空值,并返回⼀个Boolean数组
df.dropna() # 删除所有包含空值的⾏
df.dropna(axis=1) # 删除所有包含空值的列
df.dropna(axis=1,thresh=n) # 删除所有⼩于n个⾮空值的⾏
df.fillna(value=x) # ⽤x替换DataFrame对象中所有的空值,⽀持
df[column_name].fillna(x)
s.astype(float) # 将Series中的数据类型更改为float类型
s.replace(1,'one') # ⽤‘one’代替所有等于1的值
s.replace([1,3],['one','three']) # ⽤'one'代替1,⽤'three'代替3
df.rename(columns=lambdax:x+1) # 批量更改列名
df.rename(columns={'old_name':'new_ name'}) # 选择性更改列名
df.set_index('column_one') # 将某个字段设为索引,可接受列表参数,即设置多个索引
df.reset_index("col1") # 将索引设置为col1字段,并将索引新设置为0,1,2...
df.rename(index=lambdax:x+1) # 批量重命名索引 #数据分组、排序、透视
df.sort_index().loc[:5] # 对前5条数据进⾏索引排序
df.sort_values(col1) # 按照列col1排序数据,默认升序排列
df.sort_values(col2,ascending=False) # 按照列col1降序排列数据
df.sort_values([col1,col2],ascending=[True,False]) # 先按列col1升序排列,后按col2降序排列数据
df.groupby(col) # 返回⼀个按列col进⾏分组的Groupby对象
df.groupby([col1,col2]) # 返回⼀个按多列进⾏分组的Groupby对象
df.groupby(col1)[col2].agg(mean) # 返回按列col1进⾏分组后,列col2的均值,agg可以接受列表参数,agg([len,np.mean])
df.pivot_table(index=col1,values=[col2,col3],aggfunc={col2:max,col3:[ma,min]}) # 创建⼀个按列col1进⾏分组,计算col2的最⼤值和col3的最⼤值、最⼩值的数据透视表
df.groupby(col1).agg(np.mean) # 返回按列col1分组的所有列的均值,⽀持
df.groupby(col1).col2.agg(['min','max'])
data.apply(np.mean) # 对DataFrame中的每⼀列应⽤函数np.mean
data.apply(np.max,axis=1) # 对DataFrame中的每⼀⾏应⽤函数np.max
df.groupby(col1).col2.transform("sum") # 通常与groupby连⽤,避免索引更改 #数据合并
df1.append(df2) # 将df2中的⾏添加到df1的尾部
df.concat([df1,df2],axis=1,join='inner') # 将df2中的列添加到df1的尾部,值为空的对应⾏与对应列都不要
df1.join(df2.set_index(col1),on=col1,how='inner') # 对df1的列和df2的列执⾏SQL形式的join,默认按照索引来进⾏合并,如果df1和df2有共同字段时,会报错,可通过设置lsuffix,rsuffix来进⾏解决,如果需要按照共同列进⾏合并,就要⽤到set_index(col1)
pd.merge(df1,df2,on='col1',how='outer') # 对df1和df2合并,按照col1,⽅式为outer
pd.merge(df1,df2,left_index=True,right_index=True,how='outer') # 与 df1.join(df2, how='outer')效果相同
inner 两表中主键一致的行保留下来 不填充Nan --默认
outer 将不一致的部分填充Nan
left 以左列为准 不填充Nan
right 以右列为准 不填充Nan
修改MP3标题名
import eyed3
import os
import operator prefix=r".mp3"
path = r'D:/0yd/aa/a/' for eachfile in os.listdir(path):
length=len(eachfile)
if operator.eq(prefix,eachfile[length-4:length])==True:
title=u""+eachfile[0:length-4]
print(title)
print(eachfile)
track_num=eachfile[0:eachfile.find('.')]
newname=path+str(track_num)+prefix
print(newname)
# os.rename(os.path.join(path,eachfile), os.path.join(path, newname))
audiofile=eyed3.load(newname)
audiofile.initTag()
# audiofile.tag.album = u"唱片集"
# audiofile.tag.track_num =int(track_num)
audiofile.tag.title =title
# audiofile.tag.album_artist = u"艺术家"
audiofile.tag.save()
# os.rename(os.path.join(path,newname), os.path.join(path, eachfile))
重试三次
import requests
from requests.adapters import HTTPAdapter
import re,time,os
from Crypto.Cipher import AES
from urllib3.util.retry import Retry
import traceback header = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
} def m3u8(url,name):
# requests得到m3u8文件内容
# content = requests.get(url,headers=header).text
if "#EXTM3U" not in content:
print("这不是一个m3u8的视频链接!")
return False
if "EXT-X-KEY" not in content:
print("没有加密")
return False # 使用re正则得到key和视频地址
jiami=re.findall('#EXT-X-KEY:(.*)\n',content)
key=re.findall('URI="(.*)"',jiami[0])
# vi = re.findall('IV=(.*)',jiami[0])[0]
print(key)
#得到每一个ts视频链接
tslist=re.findall('EXTINF:(.*),\n(.*)\n#',content)
newlist=[]
for i in tslist:
# print(i)
newlist.append(i[1]) #得到key的链接并请求得到加密的key值
keyurl=key[0]
keycontent= requests.get(keyurl,headers=header).content
# print(keycontent)
#得到每一个完整视频的链接地址 合并地址
base_url = url.replace(url.split('/')[-1],'')
# print(base_url)
tslisturl=[]
for i in newlist:
tsurl = i
tslisturl.append(tsurl)
print(len(tslisturl),keycontent) #得到解密方法,这里要导入第三方库 pycrypto
#这里有一个问题,安装pycrypto成功后,导入from Crypto.Cipher import AES报错
#找到使用python环境的文件夹,在Lib文件夹下有一个 site-packages 文件夹,里面是我们环境安装的包。
#找到一个crypto文件夹,打开可以看到 Cipher文件夹,此时我们将 crypto文件夹改为 Crypto 即可使用了
# 必须添加b'0000000000000000',防止报错ValueError: IV must be 16 bytes long
cryptor = AES.new(keycontent, AES.MODE_CBC, b'0000000000000000') #for循环获取视频文件
reqs = requests.Session()
reqs.mount('http://', HTTPAdapter(max_retries=5))
reqs.mount('https://', HTTPAdapter(max_retries=5))
n=0
for i in tslisturl:
n+=1
# i = url1+i # 拼接ts
print(n,i)
res = reqs.get(i,headers=header,timeout=30)
# print(res.content[:50])
# print(type(res.content))
#使用解密方法解密得到的视频文件
cont=cryptor.decrypt(res.content)
# print(cont)
with open(name, 'ab+') as f:
f.write(cont)
# break return True def req1(url):
reqs = requests.Session()
retries = Retry(total=3,backoff_factor=0.1,
status_forcelist=[500, 502, 503, 504, 521])
reqs.mount('http://', HTTPAdapter(max_retries=retries))
reqs.mount('https://', HTTPAdapter(max_retries=retries))
count = 0
while True:
if count < 3:
try:
res = reqs.get(url, headers=header, timeout=60)
return res
except:
print('time out')
traceback.print_exc()
count += 1
continue
else:
break def m3u81(url, name):
if "#EXTM3U" not in content:
print("这不是一个m3u8的视频链接!")
return False # 使用re正则得到key和视频地址
jiami = re.findall('#EXT-X-KEY:(.*)\n', content)
# 得到每一个ts视频链接
tslist = re.findall('EXTINF:(.*),\n(.*)\n#', content)
newlist = [] url1 = [i[3][:-10] for i in list1 if i[0] == url.split('\\')[-1][:-5]]
print(url1[0]+'.index.m3u8')
for i in tslist:
print(i[1])
newlist.append(url1[0] + i[1])
print(len(newlist)) # for循环获取视频文件
path1 = path + url.split('\\')[-1][:-5].replace(' ','') + r'\\'
if not os.path.exists(path1):
os.mkdir(path1) n = 0
for i in newlist:
n += 1
print(n, i.split('/')[-1])
res = req1(i)
with open(path1 + i.split('/')[-1], 'wb') as f:
f.write(res.content) with open(path1 + 'file_list.txt', "w+") as f:
for i in newlist:
f.write("file '{}'\n".format(i.split('/')[-1])) # ffmpeg -f concat -i file_list.txt -c copy output.mp4
os.system('ffmpeg -f concat -i %s -c copy %s' % (path1 + 'file_list.txt', path + aa[0]))
return True if __name__ == '__main__': # url1 = 'https://v.baoshiyun.com/resource/media-859816880209920/lud/'
# url2 = '1cbc50f6321d479fb830b4dd5ef62fd0.m3u8?MtsHlsUriToken=ea844a55f1b74e20a6400c5b4a8557aa49be489bfd214f1d967d0fb2f82c6ab8'
# aa = ['Tableau视频.mp4', url1+url2]
# content = requests.get(url,headers=header).text path = r'E:\\0yd\\01\\'
aa = ['流.mp4', r'C:\Users\Administrator\Desktop\index.m3u8']
with open(aa[1],'r') as f: content = f.read() # 改为文件 pd = m3u8(aa[1],r'E:\0yd\01\%s'%aa[0])
if pd:
print('视频下载完成!')
import numpy as npimport pandas as pdimport tushare as tsimport time
Python 常用笔记的更多相关文章
- python常用笔记
A trick when you want to flatten a matrix X of shape (a,b,c,d) to a matrix X_flatten of shape (b*c*d ...
- Python学习笔记之常用函数及说明
Python学习笔记之常用函数及说明 俗话说"好记性不如烂笔头",老祖宗们几千年总结出来的东西还是有些道理的,所以,常用的东西也要记下来,不记不知道,一记吓一跳,乖乖,函数咋这么多 ...
- Python学习笔记-常用模块
1.python模块 如果你退出 Python 解释器并重新进入,你做的任何定义(变量和方法)都会丢失.因此,如果你想要编写一些更大的程序,为准备解释器输入使用一个文本编辑器会更好,并以那个文件替代作 ...
- Python学习笔记(二):条件控制语句与循环语句及常用函数的用法
总结的内容: 1.条件控制语句 2.while循环语句 3.for循环语句 4.函数的用法 一.条件控制语句 1.介绍 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决 ...
- OpenCV之Python学习笔记
OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...
- Python学习笔记基础篇——总览
Python初识与简介[开篇] Python学习笔记——基础篇[第一周]——变量与赋值.用户交互.条件判断.循环控制.数据类型.文本操作 Python学习笔记——基础篇[第二周]——解释器.字符串.列 ...
- Python学习笔记(六)
Python学习笔记(六) Ubuntu重置root密码 Ubuntu 16.4 目录结构 Ubuntu 命令讲解 1. Ubuntu重置root密码 启动系统,显示GRUB选择菜单(如果默认系统启动 ...
- Python学习笔记六
Python课堂笔记六 常用模块已经可以在单位实际项目中使用,可以实现运维自动化.无需手工备份文件,数据库,拷贝,压缩. 常用模块 time模块 time.time time.localtime ti ...
- Python学习笔记,day5
Python学习笔记,day5 一.time & datetime模块 import本质为将要导入的模块,先解释一遍 #_*_coding:utf-8_*_ __author__ = 'Ale ...
- Deep learning with Python 学习笔记(11)
总结 机器学习(machine learning)是人工智能的一个特殊子领域,其目标是仅靠观察训练数据来自动开发程序[即模型(model)].将数据转换为程序的这个过程叫作学习(learning) 深 ...
随机推荐
- python Flask 操作数据库(2)
单表操作 数据准备 from flask import Flask from flask_sqlalchemy import SQLAlchemy class Config: DEBUG = True ...
- 2022NewStarCTF新生赛一些比较有意思的题目wp
Misc_蚁剑流量分析 Pcap的文件可以直接使用工具 编辑器打开目录,一个一个看,可以找到eval危险函数 看到n3wst4r,直接使用linux正则匹配,找出相关内容 Url解码,了解一下蚁剑流量 ...
- 【转载】SQL 2012以上版本分页查询更简单
2012以上版本分页查询更简单 注意:以下都是先执行排序,再取行数据 select* from t_workers order by worker_id desc offset 3 rows -- ...
- 什么是Rabbitmq消息队列? (安装Rabbitmq,通过Rabbitmq实现RPC全面了解,从入门到精通)
目录 Rabbitmq 一: 消息队列介绍 1.介绍 2.MQ解决了什么问题 1.应用的解耦 2.流量削峰 3.消息分发(发布订阅: 观察者模式) 4.异步消息(celery就是对消息队列的封装) 3 ...
- ABC193F Engines
简要题意 给出 \(n\) 个向量,求其子集的和的最大模长. \(1 \leq n \leq 100\) 思路 先说结论:选出的几个向量,一定是极角排序后的某一段(环形)区间. 这个不难感性理解,比如 ...
- ORM执行原生SQL语句、双下划线数据查询、ORM外键字段的创建、外键字段的相关操作、ORM跨表查询、基于对象的跨表查询、基于双下划线的跨表查询、进阶查询操作
今日内容 ORM执行SQL语句 有时候ROM的操作效率可能偏低 我们是可以自己编写sql的 方式1: models.User.objects.raw('select * from app01_user ...
- 模板层之标签、自定义模板语法、母版(模版)的继承与导入、模型层前期准备知识点、ORM常用关键字
今日内容概要 模板层之标签 if判断 {% if 条件1 %} #条件1成立 <p>Hello!</p> #执行 {% elif 条件2 %} #条件1不成立 条件2成立 &l ...
- ChatGPT:让程序开发更轻松
作者:京东科技 赵龙波 "贾维斯,你在吗?" "随时待命,先生." 类似<钢铁侠>里的人工智能助理贾维斯,ChatGPT或许是你的随时待命的助手.C ...
- 计算机网络基础09 TCP/IP
https://www.jianshu.com/p/066d99da7cbd 1 概念 TCP/IP[TCP(传输控制协议)和IP(网际协议)]提供点对点的链接机制,将数据应该如何封装.定址.传输.路 ...
- 解决centos7 yum和wget都不能使用
1.前言 因为卸载了centos 7.9.2009 内置自带的python2.7.5,导致yum无法使用,但是又没有安装wget,两者不能相互安装导致死循环 2.安装wget 找到自己对应的系统版本, ...