批量獲取百度網盤文件目錄


當網盤文件超過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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM