当网盘文件超过100G的时候,找文件就有点苦恼了,不记得放在什么文件夹,也不记得名字,就想着从目录着手。
现在百度网盘还未推出目录功能,这里就套用网上推荐的查询目录的方式。后面附有代码。

百度网盘在本地有个数据库文件BaiduYunCacheFileV0.db,里面存放着文件路径和文件名等信息,两者结合提取出目录信息。该文件可以用Navicat Premium 15打开。

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. from tkinter import *
  4. from tkinter.filedialog import askopenfilename
  5. from tkinter.filedialog import asksaveasfilename
  6. from tkinter.ttk import *
  7. import sqlite3

这里用到了用于GUI图形界面开发的库,Tkinter 模块(Tk 接口),其中Tkinter filedialog是文件对话框控件。由于tkinter模块下的组件,整体风格较老较丑,同时也导入了组件更加美观、功能更加强大的ttk 组件。ttk新增了 LabeledScale( 带标签的Scale)、Notebook( 多文档窗口)、Progressbar(进度条)、Treeview(数)等组件。

  1. def select_db_file():
  2. db_file = askopenfilename(title="请选择BaiduYunCacheFileV0.db文件",filetypes=[('db', '*.db')])
  3. db.set(db_file)
  4. def select_save_file():
  5. save_file = asksaveasfilename(filetypes=[('文件', '*.txt')])
  6. f.set(save_file+".txt")

StringVar的作用,我们在使用界面编程的时候,有些时候是需要跟踪变量的值的变化,以保证值的变更随时可以显示在界面上。由于python无法做到这一点,所以使用了tcl的相应的对象,也就是StringVar、BooleanVar、DoubleVar、IntVar

  • StringVar类型需要通过StringVar.set()写入string字符串内容。
  • StringVar类型需要通过StringVar.get()读取内容,返回一个string字符串

askopenfilename返回文件名,是string字符串类型
select_db_file()函数巧妙的是,它把StringVar变量的声明写在了函数的外面且后面出现,而不是函数内部,呀呀,就是不能写在函数内部,在函数外面才是全局变量。
当然也可以理解为回调函数,当按钮被点击时,变量就存在了,不用担心它声明在后面

  1. def write_file(file_dict,f,item,gap=""):
  2. if item=="/":
  3. f.write("━" + "/" + "\n")
  4. for i in file_dict["/"]:
  5. f.write("┣" + "━" + i + "\n")
  6. i = item + i + "/"
  7. if i in file_dict:
  8. write_file(file_dict,f,i, gap="┣━")
  9. else:
  10. gap = "┃ " + gap
  11. for i in file_dict[item]:
  12. f.write(gap + i + "\n")
  13. i = item + i + "/"
  14. if i in file_dict:
  15. write_file(file_dict,f,i,gap)

递归函数write_file(file_dict,f,item,gap=""),参数分别是存放路径和对应文件的字典file_dict,f是待写入内容的txt文件,item是路径,gap是间隙

函数主体分析:如果路径item是最外层的路径,就将最外层路径对应的文件名,写入到f文件中,然后根据文件名重新赋值一个新路径,判断这个新路径是否在字典中,如果在,就递归调用该函数,检查文件名是否是文件夹(也就是文件名包装后的新路径在字典中)

如果路径不是根路径,每次调用函数gap会变化,将新路径对应的文件名,写入到f文件中,然后在文件名前面加上上一级路径后面加上/,赋值一个新路径,在字典中检查,也就是判断该文件名变成路径后,是否还有下一级路径,如果字典中有它
就表示有下一级路径,然后继续调用该函数。

  1. def create_baiduyun_filelist():
  2. file_dict = {}
  3. conn = sqlite3.connect(db.get())
  4. cursor = conn.cursor()
  5. cursor.execute("select * from cache_file")
  6. while True:
  7. value = cursor.fetchone()
  8. if not value:
  9. break
  10. path = value[2]
  11. name = value[3]
  12. size = value[4]
  13. isdir = value[6]
  14. if path not in file_dict:
  15. file_dict[path] = []
  16. file_dict[path].append(name)
  17. else:
  18. file_dict[path].append(name)
  19. with open(f.get(),"w",encoding='utf-8') as fp:
  20. write_file(file_dict,fp,"/")
  21. conn.close()

conn = sqlite3.connect(db.get())连接数据库,db是StringVar类型,需要通过db.get()读取db里的内容,返回string类型的字符串,这里是地址+数据库文件名
cursor = conn.cursor() 使用 cursor() 方法创建一个游标对象,游标对象用于执行查询和获取结果
cursor.execute("select * from cache_file") 使用 execute() 方法执行 SQL 查询,SQL语句和BaiduYunCacheFileV0.db里的表格结构有关系,它里面有张叫cache_file的表
value = cursor.fetchone() fetchone() 获取下一个查询结果集。结果集是一个对象
conn.close()关闭数据库连接

  1. root = Tk()
  2. root.title('百度云文件列表生成工具')
  3. db_select = Button(root, text=' 选择DB文件 ',command=select_db_file)
  4. db_select.grid(row=1,column=1,sticky=W,padx=(2,0),pady=(2,0))
  5. db = StringVar()
  6. db_path = Entry(root,width=80,textvariable = db)
  7. db_path['state'] = 'readonly'
  8. db_path.grid(row=1,column=2,padx=3,pady=3,sticky=W+E)
  9. save_path = Button(root, text='选择保存地址',command=select_save_file)
  10. save_path.grid(row=2,column=1,sticky=W,padx=(2,0),pady=(2,0))
  11. f = StringVar()
  12. file_path = Entry(root,width=80,textvariable = f)
  13. file_path['state'] = 'readonly'
  14. file_path.grid(row=2, column=2,padx=3,pady=3,sticky=W+E)
  15. create_btn = Button(root, text='生成文件列表',command=create_baiduyun_filelist)
  16. create_btn.grid(row=3,column=1,columnspan=2,pady=(0,2))
  17. root.columnconfigure(2, weight=1)
  18. root.mainloop()

root = Tk() 调用窗口函数,实例化一个窗口对象
root.title('百度云文件列表生成工具') 窗口最顶部显示的文字
db_select = Button(root, text=' 选择DB文件 ',command=select_db_file) 在窗口上创建一个button,调用一个按钮,command代表点击按钮发生的事件
padx,pady:与之并列的组件之间的间隔,x方向和y方向,默认单位是像素
db_select.grid(row=1,column=1,sticky=W,padx=(2,0),pady=(2,0)) 设置按钮的位置,在第一行第一列,padx=(2,0) ,与之并列的组件之间的间隔,水平方向上,button与左边的组件,距离是2个像素,与右边的组件,距离是0像素。

如果不调用Button的grid函数,它将不会显示。sticky=W靠左边。
sticky:有点类似于 pack() 方法的 anchor 选项,同样支持 N(北,代表上)、E(东,代表右)、S(南,代表下)、W(西,代表左)、NW(西北,代表左上)、NE(东北,代表右上)、SW(西南,代表左下)、SE(东南,代表右下)、CENTER(中,默认值)这些值。

db = StringVar()StringVar是Tk库内部定义的字符串变量类型,改变StringVar,按钮上的文字也随之改变。
db_path = Entry(root,width=80,textvariable = db) TKinter输入类(TKinter文本框)获取用户输入,TKinter Entry类创建文本框,把变量db绑定到Entry
db_path['state'] = 'readonly' 变量db绑定Entry后,Entry状态变为只读
root.columnconfigure(2, weight=1) 列属性设置
root.mainloop()此函数调用窗口的无限循环,因此窗口将等待任何用户交互,直到我们将其关闭。

选项 说明 取值范围
column 单元格的列号 从0开始的正整数column
columnspan 跨列,跨越的列数 正整数
row 单元格的行号 从0开始的正整数
rowspan 跨行,跨越的行数 正整数
ipadx, ipady 设置子组件之间的间隔,x方向或者y方向,默认单位为像素 非负浮点数,默认0.0
padx,pady 与之并列的组件之间的间隔,x方向或者y方向,默认单位是像素 非负浮点数,默认0.0
sticky 组件紧贴所在单元格的某一角,对应于东南西北中以及4个角 N/S/W/E, NW/SW/SE/NE, CENTER(默认)
  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. from tkinter import *
  4. from tkinter.filedialog import askopenfilename
  5. from tkinter.filedialog import asksaveasfilename
  6. from tkinter.ttk import *
  7. import sqlite3
  8. def select_db_file():
  9. db_file = askopenfilename(title="请选择BaiduYunCacheFileV0.db文件",filetypes=[('db', '*.db')])
  10. db.set(db_file)
  11. def select_save_file():
  12. save_file = asksaveasfilename(filetypes=[('文件', '*.txt')])
  13. f.set(save_file+".txt")
  14. def write_file(file_dict,f,item,gap=""):
  15. if item=="/":
  16. f.write("━" + "/" + "\n")
  17. for i in file_dict["/"]:
  18. f.write("┣" + "━" + i + "\n")
  19. i = item + i + "/"
  20. if i in file_dict:
  21. write_file(file_dict,f,i, gap="┣━")
  22. else:
  23. gap = "┃ " + gap
  24. for i in file_dict[item]:
  25. f.write(gap + i + "\n")
  26. i = item + i + "/"
  27. if i in file_dict:
  28. write_file(file_dict,f,i,gap)
  29. def create_baiduyun_filelist():
  30. file_dict = {}
  31. conn = sqlite3.connect(db.get())
  32. cursor = conn.cursor()
  33. cursor.execute("select * from cache_file")
  34. while True:
  35. value = cursor.fetchone()
  36. if not value:
  37. break
  38. path = value[2]
  39. name = value[3]
  40. size = value[4]
  41. isdir = value[6]
  42. if path not in file_dict:
  43. file_dict[path] = []
  44. file_dict[path].append(name)
  45. else:
  46. file_dict[path].append(name)
  47. with open(f.get(),"w",encoding='utf-8') as fp:
  48. write_file(file_dict,fp,"/")
  49. conn.close()
  50. root = Tk()
  51. root.title('百度云文件列表生成工具')
  52. db_select = Button(root, text=' 选择DB文件 ',command=select_db_file)
  53. db_select.grid(row=1,column=1,sticky=W,padx=(2,0),pady=(2,0))
  54. db = StringVar()
  55. db_path = Entry(root,width=80,textvariable = db)
  56. db_path['state'] = 'readonly'
  57. db_path.grid(row=1,column=2,padx=3,pady=3,sticky=W+E)
  58. save_path = Button(root, text='选择保存地址',command=select_save_file)
  59. save_path.grid(row=2,column=1,sticky=W,padx=(2,0),pady=(2,0))
  60. f = StringVar()
  61. file_path = Entry(root,width=80,textvariable = f)
  62. file_path['state'] = 'readonly'
  63. file_path.grid(row=2, column=2,padx=3,pady=3,sticky=W+E)
  64. create_btn = Button(root, text='生成文件列表',command=create_baiduyun_filelist)
  65. create_btn.grid(row=3,column=1,columnspan=2,pady=(0,2))
  66. root.columnconfigure(2, weight=1)
  67. root.mainloop()

参考资料:
Python官方手册:https://docs.python.org/zh-cn/3.8/library/tkinter.ttk.html

版权声明:本文为fylhd2013原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/fylhd2013/p/15006636.html