Tag Archives: python

Hello World

用python提取Excel内的附件mp4

收到一个Excel文档,里面有两段内嵌的mp4视频,手头mac版的Excel打不开这俩附件。其实以前也发现过,无论是内嵌的doc、还是其他文件,mac版的excel似乎都打不开,但那时身边有用 windows的同事,让他帮忙打开再导出就好了。现在身边人全是mac本,手头唯一windows台式机平时只玩游戏,甚至没装office~~
先到的第一个方法是各种在线文档工具,但是,试了google和腾讯的,上传以后都不行。按说微软自家的在线文档总可以吧,好容易登陆了,TM上传这个Excel文件一直失败…
既然此路不通,那就从头开始:给windows装个office~~记得以前有试用版,装好以后能试用一个月。哪知现在的office365不付钱就找不到下载入口(⊙o⊙)…。有想着下载一个旧版的office,最好是破解版的,找了几个渠道,要么不是正常的下载包、要么到了百度网盘~~然后进网盘提示资源已经没了…(还送,好久不用windows,破解软件这么难找了吗 O(∩_∩)O哈哈~)
最后没办法,搜索引擎也找不到靠边的答案,问chatgpt,在chatgpt的提示下,一步步用python解出了附件,具体大概分下面两步:
1. 将excel备份一份,然后将扩展名改成“.zip”,然后解压,按AI的说法,运气好的话,mp4文件直接就在解压包/xl/embeddings目录底下~~我的运气不好,里面是两个bin文件,按chatgpt的说法,mp4数据就包在这个bin里
2. 调下面python脚本,处理bin文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    import olefile #需要安装olefile库
    ole = olefile.OleFileIO('xx/xl/embeddings/oleObject2.bin')
    print(ole.listdir())
    streams = ole.listdir()
    print(streams) #打印出具体的数据流,mp4可能在\x01Ole10Native中,也可能在其他流中
    #提取mp4数据流
    if ole.exists('\x01Ole10Native'):
        with ole.openstream('\x01Ole10Native') as stream:
            data = stream.read()
        # 保存到缓冲文件
        with open('temp.bin', 'wb') as f:
            f.write(data)
        print("Data from \\x01Ole10Native saved as output.bin")
    else:
        print("\\x01Ole10Native stream not found")
    ole.close()
    # 从 MP4 文件中提取数据
    with open('temp.bin', 'rb') as f:
        data = f.read() 
    # 自动查找 MP4 文件头 ("ftyp")
    data_start = data.find(b'ftyp')
    if data_start == -1:
        print("MP4 header not found. The file may not contain valid MP4 data.")
        exit()
    print(f"MP4 header found at offset: {data_start}")
    # 从 mp4 文件头开始提取数据
    # mp4文件头在"ftyp"之前可能还有四个字节空位,具体的可以使用https://hexed.it之类的工具打开二进制文件查看
    data_start = data_start - 4 
    output_file = 'extracted_video.mp4' #输出mp4文件名
    with open(output_file, 'wb') as out_f:
        out_f.write(data[data_start:])
    print(f"File extracted successfully as {output_file}")

———-
over,转载请注明出处:http://www.jiangkl.com/2024/12/excel_mp4_python

Hello World

pandas日期的高效处理方法

每次碰到dataframe里有datetime字段,都会感觉很麻烦,明明知道pandas里有很多批量处理的方法,但一个datetime改字符串日期,之前试过过很多写法,都不成功,又不甘心用低效的apply,于是动个小聪明,直接前置到提取数据的sql里:SUBSTR(created,1,10) day ^_^
今天又碰到这类问题,数据来源十几张表,而且是之前现成的公共模块,不好随便改sql,无奈找pandas里的处理方法,这次居然轻而易举找到了:
df['day'] = df['created'].dt.strftime(‘%Y-%m-%d’)
嗯,其实就这么简简单单一行代码~~继而好奇进一步研究了这里面的“dt”对象,除了搭配strftime()做日期格式化,还可以直接dt.year/dt.month/dt/time/dt.quarter/dt.weekday,还有dt.dayofyear/dt.weekofyear,哈哈,没错,可以理解成里面藏了一个map
除了这些,还可以类似这么用:(df['日期1'] – df['日期2']).dt.days、(df['日期1'] – df['日期2']).dt.total_seconds()

Hello World

dataframe拆字段

比如,数据源某字段格式:“13/34”,来表示门店每日的新老用户数,现在要把它拆成两个字段,以便下一步分析使用。当然,我们首先肯定想到可以apply,可是如果数据量太大,apply就会变得很慢。那么,有没有更快的办法?
当然有了,毕竟pandas总不会让我们失望
df['new'], df['old'] = df['user_count'].str.split(‘/’, 1).str
简简单单一行代码就完成了

———
over, 参考:https://zhuanlan.zhihu.com/p/343895339

Hello World

pandas之pivot_table的使用

pivot_table是将多行数据转成多列的一个函数,作用类似exce的透视表,这里咱们先看一下它的实际处理效果:

再看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
#构建测试数据
df = pd.DataFrame({
	'品类': ['苹果', '橘子', '香蕉', '橘子', '香蕉', '橘子'],
	'日期': ['2023-10-21', '2023-10-21', '2023-10-21', '2023-10-22', '2023-10-23','2023-10-23'],
	'销量': [13, 24, 25, 27, 19, 21]
	},
	columns=['品类', '日期', '销量']
)
print(df)
#日期列转行 index 行索引,columns 要转为列名的行,values 要转为列值的行
df2 = pd.pivot_table(df, index=['品类'], columns=['日期'], values=['销量'])
df2.fillna(0, inplace=True)
print(df2)

———-
over,转载请注明出处:http://www.jiangkl.com/2023/10/pivot_table

Hello World

闪展腾挪,只为避开apply

apply是pandas一个强大的工具函数,可以逐行对数据进行操作。pandas的优点很多,比如代码简洁、相对直接遍历效率更高;但它的“效率高”是相对的,相对于merge之类的操作,apply的执行时间可能会高出两个数量级。比如下面这行:

1
2
  #为订单数据集增加以后一列:微信支付的金额
  df['pay_wx'] = df.apply(lambda x: (x.pay if x.chan == 'wx' else 0), axis=1)

从上面的代码看,逻辑非常简洁,但是实际测试,50万的数据量,要20秒。下面尝试改造一下

1
2
3
4
  df_wx = df[df['chan'] == 'wx']
  df_wx.rename(columns={'pay': 'pay_wx'}, inplace=True)
  df['pay_wx'] = df_wx['pay_wx']
  df.fillna({'pay_wx': 0}, inplace=True)

代码从一行变成了四行,不过执行效率可以高很多:50万数据,时间大约0.7秒
当然,方法不止一种,对于更见的判断条件,可以直接用merge操作:

1
2
3
4
5
6
7
8
9
10
  #合并某项分类依据
  df['color'] = df.apply(lambda x: ('红' if x.color == '粉红' else x.color), axis=1)
  #使用merge优化
  df_h = df[df['color'] == '粉红'][['id', 'color']]
  df_h['color'] = '红'
  df_nh = df[df['color'] != '粉红'][['id', 'color']]
  df_hs = pd.concat([df_h, df_nh])
  df_hs.rename(columns={'color':'color2'}, inplace=True)
  df = pd.merge(df, df_h, on='id', how='left')
  df['color'] = df['color2']

通过上面这种方法改造,执行时间和第一个方法接近,50万条数据大约0.8秒

———–
转载请注明出处:http://www.jiangkl.com/2022/12/no_apply