接上一篇案例:Python_批量下载1000个apk,我们只讲了如何下载,
其实市场部提供的表格,不仅仅包含了apk的下载地址,还有apk的版本号,还有MD5信息等,
如何确保你下载的这1000个apk,是下载过程中未出错,版本号对的上,MD5信息也对上?
附:市场部提供的包含apk版本号,md5信息的表。
本案例主要介绍:如何快速地实现对已经下载好的app进行批量地验证。
准备阶段
- 本篇只讲验证apk的版本号与md5信息,不讲下载。
- 需要确保aapt已经成功地加入到了环境变量中去
- “aapt dump bagding XXX.apk | findstr version”命令可以解析某个apk的versionName信息。
- Windows操作系统可以用“certutil -hashfile XXX.apk MD5”命令可以计算某apk的MD5哈希值,
MD5是用于验证文件下载过程完整性的常用的一套计算方法,确保被下载的文件,在网络传输过程中,未被篡改或者损坏。 - Linux操作系统可以用“md5sum XXX.apk”命令来计算某个apk的MD5哈希值。
- 其实Python的hashlib模块,也可以进行MD5哈希值的计算,可不受操作系统影响。
- 上一篇案例,我们已经下载好了的apk是放在“downloaded_apk”文件下,os.listdir()函数可以列出文件夹下的所有apk文件。
- 涉及Excel读写操作,依旧推荐openpyxl, 需要考虑与原始Excel上的版本号及MD5值自动做对比,
所以我们增加了2列用于做验证对比, 如果值相同,我们回填Ok,如果值不相同,我们回填差异值并标记红底色。
Python批处理脚本形式
记住批处理脚本的精髓:批量顺序执行语句
# coding=utf-8 import os import re import openpyxl from openpyxl.styles import PatternFill # 第一步:再生成整个excel表格的字典,key是apk中文名称,value是一个列表[所在行数, 版本号,MD5] print("正在生成apk信息索引字典...") apkinfo_dict = {} apkname_col = 2 apkversion_col = 4 apkmd5_col = 6 apkversion_col_newadd = 5 # 新加的版本验证列 apkmd5_col_newadd = 7 # 新加的MD5验证列 error_fill = PatternFill(fill_type='solid', fgColor="FF3300") # 标记红色底色 excel = openpyxl.load_workbook('Top_1000_apks.xlsx') # 读取excel里边的内容 table = excel.active rows = table.max_row for r in range(2, rows + 1): # 跟excel的第一行标题行无关,从第二行文字内容开始做替换工作 apk_name = table.cell(row=r, column=apkname_col).value # 获取apk名称 apk_version = table.cell(row=r, column=apkversion_col).value # 获取apk名称 apk_md5 = table.cell(row=r, column=apkmd5_col).value # 获取apk名称 apkinfo_dict[apk_name] = [r, apk_version, apk_md5] print(apkinfo_dict) # 第二步:再读取downloaded_apk文件夹下的所有文件,并进行对比及回填操作 curpath = os.getcwd() apk_dir = os.path.join(curpath, "downloaded_apk") apk_list = os.listdir(apk_dir) for apk in apk_list: print("正在进行%s的版本和MD5值对比与回填操作..." % apk) apk_path = os.path.join(apk_dir, apk) file_name = apk.replace(".apk", "") # 获取apk文件名,去掉后缀 s1 = os.popen("aapt.exe dump badging %s | findstr version" % apk_path).read() version_name = re.findall(r"versionName=\'(.*)\'", s1)[0] print(version_name) s2 = os.popen("certutil -hashfile %s MD5" % apk_path).read() md5_value = s2.splitlines()[1] md5_value = md5_value.replace(" ", "") print(md5_value) r = apkinfo_dict[file_name][0] # 获得该apk所在行号 # 假如版本号匹配的上,回填Ok,假如匹配不上,回填新的版本号 if version_name == apkinfo_dict[file_name][1]: table.cell(row=r, column=apkversion_col_newadd).value = "OK" else: table.cell(row=r, column=apkversion_col_newadd).value = version_name table.cell(row=r, column=apkversion_col_newadd).fill = error_fill # 标记红色底色 # 假如MD5匹配的上,回填Ok,假如匹配不上,回填新的MD5 if md5_value == apkinfo_dict[file_name][2]: table.cell(row=r, column=apkmd5_col_newadd).value = "OK" else: table.cell(row=r, column=apkmd5_col_newadd).value = md5_value table.cell(row=r, column=apkmd5_col_newadd).fill = error_fill # 标记红色底色 print("对比及回填结束,并保存到了New_Top_1000_apks.xlsx,请查阅...") excel.save("New_Top_1000_apks.xlsx") os.system("pause")
Python面向过程函数形式
面向过程函数的编程思维应该是这样的:
你需要多少个功能(函数),才能做成这个事,
最好把功能(函数)都尽量封装好,只暴露一些的参数接口即可。
在命令行工具熟练运用后,就可以考虑尽量用Python模块来实现命令行工具的功能,
比如certutil或md5sum就尽量不用了,而考虑用hashlib模块来代替,
减少对某个命令行工具的依赖,这样可移植性更强些(减少了对操作系统的限制)。
# coding=utf-8 import os import re import openpyxl from openpyxl.styles import PatternFill import hashlib # 定义一些本模块(当前.py文件)可能都需要调用的“全局变量” apkname_col = 2 apkversion_col = 4 apkmd5_col = 6 apkversion_col_newadd = 5 # 新加的版本验证列 apkmd5_col_newadd = 7 # 新加的MD5验证列 error_fill = PatternFill(fill_type='solid', fgColor="FF3300") # 标记红色底色 def parse_apk_excel(excel_file): '''用于生成apk信息索引字典''' print("正在生成apk信息索引字典...") apk_info_dict = {} excel = openpyxl.load_workbook(excel_file) # 读取excel里边的内容 table = excel.active rows = table.max_row for r in range(2, rows + 1): # 跟excel的第一行标题行无关,从第二行文字内容开始做替换工作 apk_name = table.cell(row=r, column=apkname_col).value # 获取apk名称 apk_version = table.cell(row=r, column=apkversion_col).value # 获取apk名称 apk_md5 = table.cell(row=r, column=apkmd5_col).value # 获取apk名称 apk_info_dict[apk_name] = [r, apk_version, apk_md5] return apk_info_dict, excel, table def get_apk_version(apk_path): s = os.popen("aapt.exe dump badging %s | findstr version" % apk_path).read() version_name = re.findall(r"versionName=\'(.*)\'", s)[0] print(version_name) return version_name def get_apk_md5(apk_path): with open(apk_path, "rb") as hf: apk_md5 = hashlib.md5(hf.read()).hexdigest() print(apk_md5) return apk_md5 def compare_rewrite(apk_info_dict, excel, table): curpath = os.getcwd() apk_dir = os.path.join(curpath, "downloaded_apk") apk_list = os.listdir(apk_dir) for apk in apk_list: print("正在进行%s的版本和MD5值对比与回填操作..." % apk) file_name = apk.replace(".apk", "") # 获取apk文件名,去掉后缀 apk_path = os.path.join(apk_dir, apk) version_name = get_apk_version(apk_path) md5_value = get_apk_md5(apk_path) r = apk_info_dict[file_name][0] # 获得该apk所在行号 # 假如版本号匹配的上,回填Ok,假如匹配不上,回填新的版本号 if version_name == apk_info_dict[file_name][1]: table.cell(row=r, column=apkversion_col_newadd).value = "OK" else: table.cell(row=r, column=apkversion_col_newadd).value = version_name table.cell(row=r, column=apkversion_col_newadd).fill = error_fill # 标记红色底色 # 假如MD5匹配的上,回填Ok,假如匹配不上,回填新的MD5 if md5_value == apk_info_dict[file_name][2]: table.cell(row=r, column=apkmd5_col_newadd).value = "OK" else: table.cell(row=r, column=apkmd5_col_newadd).value = md5_value table.cell(row=r, column=apkmd5_col_newadd).fill = error_fill # 标记红色底色 print("对比及回填结束,并保存到了New_Top_1000_apks.xlsx,请查阅...") excel.save("New_Top_1000_apks.xlsx") apk_info_dict, excel, table = parse_apk_excel("Top_1000_apks.xlsx") # 获取索引字典 compare_rewrite(apk_info_dict, excel, table) # 开始对比及回填 os.system("pause")
Python面向对象类形式
面向对象类的编程思维应该是这样的:
如果给你一个空白的世界,在这个世界里你需要哪些种类的事物,
这些种类的事物都具备哪些共有的属性与方法,
这些种类(类)的事物(对象),和其他种类(其他类)的事物(其他对象)有什么关系。
尽量把这些类封装好,只暴露对外的属性(变量)和方法(函数)即可。
# coding=utf-8 import os import re import openpyxl from openpyxl.styles import PatternFill import hashlib # 定义一些本模块(当前.py文件)可能都需要调用的“全局变量” apkname_col = 2 apkversion_col = 4 apkmd5_col = 6 apkversion_col_newadd = 5 # 新加的版本验证列 apkmd5_col_newadd = 7 # 新加的MD5验证列 error_fill = PatternFill(fill_type='solid', fgColor="FF3300") # 标记红色底色 class ExcelParser(): def __init__(self, excel_file): self._excel_file = excel_file # 没必要暴露到外界,加_ def parse_apk_excel(self): # 这是需要暴露的方法(函数),不能加_ '''用于生成apk信息索引字典''' print("正在生成apk信息索引字典...") apk_info_dict = {} excel = openpyxl.load_workbook(self._excel_file) # 读取excel里边的内容 table = excel.active rows = table.max_row for r in range(2, rows + 1): # 跟excel的第一行标题行无关,从第二行文字内容开始做替换工作 apk_name = table.cell(row=r, column=apkname_col).value # 获取apk名称 apk_version = table.cell(row=r, column=apkversion_col).value # 获取apk名称 apk_md5 = table.cell(row=r, column=apkmd5_col).value # 获取apk名称 apk_info_dict[apk_name] = [r, apk_version, apk_md5] return apk_info_dict, excel, table def get_apk_version(apk_path): s = os.popen("aapt.exe dump badging %s | findstr version" % apk_path).read() version_name = re.findall(r"versionName=\'(.*)\'", s)[0] print(version_name) return version_name def get_apk_md5(apk_path): with open(apk_path, "rb") as hf: apk_md5 = hashlib.md5(hf.read()).hexdigest() print(apk_md5) return apk_md5 def compare_rewrite(apk_info_dict, excel, table): curpath = os.getcwd() apk_dir = os.path.join(curpath, "downloaded_apk") apk_list = os.listdir(apk_dir) for apk in apk_list: print("正在进行%s的版本和MD5值对比与回填操作..." % apk) file_name = apk.replace(".apk", "") # 获取apk文件名,去掉后缀 apk_path = os.path.join(apk_dir, apk) version_name = get_apk_version(apk_path) md5_value = get_apk_md5(apk_path) r = apk_info_dict[file_name][0] # 获得该apk所在行号 # 假如版本号匹配的上,回填Ok,假如匹配不上,回填新的版本号 if version_name == apk_info_dict[file_name][1]: table.cell(row=r, column=apkversion_col_newadd).value = "OK" else: table.cell(row=r, column=apkversion_col_newadd).value = version_name table.cell(row=r, column=apkversion_col_newadd).fill = error_fill # 标记红色底色 # 假如MD5匹配的上,回填Ok,假如匹配不上,回填新的MD5 if md5_value == apk_info_dict[file_name][2]: table.cell(row=r, column=apkmd5_col_newadd).value = "OK" else: table.cell(row=r, column=apkmd5_col_newadd).value = md5_value table.cell(row=r, column=apkmd5_col_newadd).fill = error_fill # 标记红色底色 print("对比及回填结束,并保存到了New_Top_1000_apks.xlsx,请查阅...") excel.save("New_Top_1000_apks.xlsx") if __name__ == '__main__': e_obj = ExcelParser("Top_1000_apks.xlsx") apk_info_dict, excel, table = e_obj.parse_apk_excel() # 获取索引字典 compare_rewrite(apk_info_dict, excel, table) # 开始对比及回填 os.system("pause")
本案例练手素材下载
跳转到自拍教程官网下载素材
武散人出品,请放心下载并使用!
运行方式与效果
确保Android设备通过USB线与电脑连接了,adb设备有效连接,
以上代码的3种实现形式都可以直接运行,比如保存为verify_apks.py并和downloaded_apk文件夹还有Top_1000_apks.xlsx放在同一个文件夹下,
建议python verify_apks.py运行,当然也可以双击运行。
运行效果如下:
最终会新生成一个New_Top_1000_apks.xlsx, 其验证及回填效果如下,
红色的是代表实际下载下来的apk与市场部提供的Excel上的版本信息及Md5不一样的标注。
更多更好的原创文章,请访问官方网站:www.zipython.com
自拍教程(自动化测试Python教程,武散人编著)
原文链接:https://www.zipython.com/#/detail?id=f13a1efe25424b679e663a63fb64a10c
也可关注“武散人”微信订阅号,随时接受文章推送。
来源:https://www.cnblogs.com/zipython/p/12655033.html