批量獲取百度網盤檔案目錄
當網盤檔案超過100G的時候,找檔案就有點苦惱了,不記得放在什麼資料夾,也不記得名字,就想著從目錄著手。
現在百度網盤還未推出目錄功能,這裡就套用網上推薦的查詢目錄的方式。後面附有程式碼。
整體思路
檢視網盤快取資料庫檔案
百度網盤在本地有個資料庫檔案BaiduYunCacheFileV0.db
,裡面存放著檔案路徑和檔名等資訊,兩者結合提取出目錄資訊。該檔案可以用Navicat Premium 15開啟。
程式碼分析
#!/usr/bin/env python3 # -*- coding:utf-8 -*- from tkinter import * from tkinter.filedialog import askopenfilename from tkinter.filedialog import asksaveasfilename from tkinter.ttk import * import sqlite3
這裡用到了用於GUI圖形介面開發的庫,Tkinter 模組(Tk 介面),其中Tkinter filedialog是檔案對話方塊控制元件。由於tkinter模組下的元件,整體風格較老較醜,同時也匯入了元件更加美觀、功能更加強大的ttk 元件。ttk新增了 LabeledScale( 帶標籤的Scale)、Notebook( 多文件視窗)、Progressbar(進度條)、Treeview(數)等元件。
def select_db_file(): db_file = askopenfilename(title="請選擇BaiduYunCacheFileV0.db檔案",filetypes=[('db', '*.db')]) db.set(db_file) def select_save_file(): save_file = asksaveasfilename(filetypes=[('檔案', '*.txt')]) 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變數的宣告寫在了函式的外面且後面出現,而不是函式內部,呀呀,就是不能寫在函式內部,在函式外面才是全域性變數。
當然也可以理解為回撥函式,當按鈕被點選時,變數就存在了,不用擔心它宣告在後面
核心函式
def write_file(file_dict,f,item,gap=""):
if item=="/":
f.write("━" + "/" + "\n")
for i in file_dict["/"]:
f.write("┣" + "━" + i + "\n")
i = item + i + "/"
if i in file_dict:
write_file(file_dict,f,i, gap="┣━")
else:
gap = "┃ " + gap
for i in file_dict[item]:
f.write(gap + i + "\n")
i = item + i + "/"
if i in file_dict:
write_file(file_dict,f,i,gap)
遞迴函式write_file(file_dict,f,item,gap="")
,引數分別是存放路徑和對應檔案的字典file_dict
,f是待寫入內容的txt檔案,item是路徑,gap是間隙
函式主體分析:如果路徑item是最外層的路徑,就將最外層路徑對應的檔名,寫入到f檔案中,然後根據檔名重新賦值一個新路徑,判斷這個新路徑是否在字典中,如果在,就遞迴呼叫該函式,檢查檔名是否是資料夾(也就是檔名包裝後的新路徑在字典中)
如果路徑不是根路徑,每次呼叫函式gap會變化,將新路徑對應的檔名,寫入到f檔案中,然後在檔名前面加上上一級路徑後面加上/,賦值一個新路徑,在字典中檢查,也就是判斷該檔名變成路徑後,是否還有下一級路徑,如果字典中有它
就表示有下一級路徑,然後繼續呼叫該函式。
連線資料庫提取內容
def create_baiduyun_filelist():
file_dict = {}
conn = sqlite3.connect(db.get())
cursor = conn.cursor()
cursor.execute("select * from cache_file")
while True:
value = cursor.fetchone()
if not value:
break
path = value[2]
name = value[3]
size = value[4]
isdir = value[6]
if path not in file_dict:
file_dict[path] = []
file_dict[path].append(name)
else:
file_dict[path].append(name)
with open(f.get(),"w",encoding='utf-8') as fp:
write_file(file_dict,fp,"/")
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()
關閉資料庫連線
主函式
root = Tk()
root.title('百度雲檔案列表生成工具')
db_select = Button(root, text=' 選擇DB檔案 ',command=select_db_file)
db_select.grid(row=1,column=1,sticky=W,padx=(2,0),pady=(2,0))
db = StringVar()
db_path = Entry(root,width=80,textvariable = db)
db_path['state'] = 'readonly'
db_path.grid(row=1,column=2,padx=3,pady=3,sticky=W+E)
save_path = Button(root, text='選擇儲存地址',command=select_save_file)
save_path.grid(row=2,column=1,sticky=W,padx=(2,0),pady=(2,0))
f = StringVar()
file_path = Entry(root,width=80,textvariable = f)
file_path['state'] = 'readonly'
file_path.grid(row=2, column=2,padx=3,pady=3,sticky=W+E)
create_btn = Button(root, text='生成檔案列表',command=create_baiduyun_filelist)
create_btn.grid(row=3,column=1,columnspan=2,pady=(0,2))
root.columnconfigure(2, weight=1)
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()
此函式呼叫視窗的無限迴圈,因此視窗將等待任何使用者互動,直到我們將其關閉。
grid()方法相關引數
選項 | 說明 | 取值範圍 |
---|---|---|
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(預設) |
整體程式碼
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfilename
from tkinter.ttk import *
import sqlite3
def select_db_file():
db_file = askopenfilename(title="請選擇BaiduYunCacheFileV0.db檔案",filetypes=[('db', '*.db')])
db.set(db_file)
def select_save_file():
save_file = asksaveasfilename(filetypes=[('檔案', '*.txt')])
f.set(save_file+".txt")
def write_file(file_dict,f,item,gap=""):
if item=="/":
f.write("━" + "/" + "\n")
for i in file_dict["/"]:
f.write("┣" + "━" + i + "\n")
i = item + i + "/"
if i in file_dict:
write_file(file_dict,f,i, gap="┣━")
else:
gap = "┃ " + gap
for i in file_dict[item]:
f.write(gap + i + "\n")
i = item + i + "/"
if i in file_dict:
write_file(file_dict,f,i,gap)
def create_baiduyun_filelist():
file_dict = {}
conn = sqlite3.connect(db.get())
cursor = conn.cursor()
cursor.execute("select * from cache_file")
while True:
value = cursor.fetchone()
if not value:
break
path = value[2]
name = value[3]
size = value[4]
isdir = value[6]
if path not in file_dict:
file_dict[path] = []
file_dict[path].append(name)
else:
file_dict[path].append(name)
with open(f.get(),"w",encoding='utf-8') as fp:
write_file(file_dict,fp,"/")
conn.close()
root = Tk()
root.title('百度雲檔案列表生成工具')
db_select = Button(root, text=' 選擇DB檔案 ',command=select_db_file)
db_select.grid(row=1,column=1,sticky=W,padx=(2,0),pady=(2,0))
db = StringVar()
db_path = Entry(root,width=80,textvariable = db)
db_path['state'] = 'readonly'
db_path.grid(row=1,column=2,padx=3,pady=3,sticky=W+E)
save_path = Button(root, text='選擇儲存地址',command=select_save_file)
save_path.grid(row=2,column=1,sticky=W,padx=(2,0),pady=(2,0))
f = StringVar()
file_path = Entry(root,width=80,textvariable = f)
file_path['state'] = 'readonly'
file_path.grid(row=2, column=2,padx=3,pady=3,sticky=W+E)
create_btn = Button(root, text='生成檔案列表',command=create_baiduyun_filelist)
create_btn.grid(row=3,column=1,columnspan=2,pady=(0,2))
root.columnconfigure(2, weight=1)
root.mainloop()
執行結果
參考資料:
Python官方手冊:https://docs.python.org/zh-cn/3.8/library/tkinter.ttk.html