如果貼上全部的程式碼一個一個講,閱讀性太差了
這是我找別人資料參考時的想法
三百多行的程式,自己寫的就還好,看別人的真的催眠,一眼就想睡
不過有可能有人想看,整個程式碼可能會再發一篇就是了
所以我把我遇到的問題貼一些上來
希望可以幫助後面也想用pytube這個模組的同好解決一些找不到的問題
不過我已經完成了程式,無法(懶得)再現問題點,可能還是會有些遺漏
2022/02/07
錯誤訊息
NoneType' object has no attribute 'span'
沒意外又是YouTube改版
解決辦法
YouTube 2022/01/20 改版,pytube 抓不到影音資料
錯誤訊息如下
During handling of the above exception, another exception occurred: Traceback (most recent call last): File "d:\ytdownload\test.py", line 12, in <module> yt.streams.all() File "C:\Users\teacher\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\__main__.py", line 292, in streams return StreamQuery(self.fmt_streams) File "C:\Users\teacher\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\__main__.py", line 184, in fmt_streams extract.apply_signature(stream_manifest, self.vid_info, self.js) File "C:\Users\teacher\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\extract.py", line 409, in apply_signature cipher = Cipher(js=js) File "C:\Users\teacher\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\cipher.py", line 33, in __init__ raise RegexMatchError( pytube.exceptions.RegexMatchError: __init__: could not find match for ^\w+\W |
cipher.py 中的 ^\w+\W 有問題
有人已經提出問題,並且有人解決
找到 cipher.py 將原本的 ^\w+\W
改成 ^\$*\w+\W 存檔解決
caption 抓字幕問題
使用模組時還是要確認型態,不然蝦測會浪費很多時間
下圖例子 caption 出來的型態是<class 'pytube.query.CaptionQuery'>
到pytube.io 看他原始碼
往上看他的caption.py
有name跟code可以用,name 是字幕語言,code 是語系代碼
人看的是 name,程式看的是 code,怎麼利用看個人
caption download出錯
比如程式碼如下
yt = pytube.YouTube("網址")
yt.captions["zh"].download()
會出現錯誤KeyError: 'start',具體錯誤我懶得還原了,好像是他模組內 xml轉 srt的方法有錯(或是YOUTUBE有更新)
解決方法我直接抄網路答案拉
找到 caption.py覆蓋過去搞定
分辨下載影片有沒有聲音
網路上教學都是使用subprocess,Popen控制臺檢查影片有沒有聲音
不過 pytube中已經有檢查下載的影片有沒有聲音的方法
或是檢查是不是漸進式下載也可以
下載影片時整個程式無回應的問題
按下載按鈕時,整個程式會卡住,直到下載完成時才會釋放資源
這樣不好,因為我還有 text的 box要顯示下載進度,如果下載時就卡在那
那使用體驗很差,這時候就要使用多執行緒
使用 threading模組
原理每一行 threading.Thread(target = 啟動函數, args = (啟動函式的輸入變數)) 使用一個執行緒
但是在下載按鈕 command的地方不能直接接執行緒啟動
所以要再寫一個函式,從函式中啟動,如果發現還是無法改善
嘗試把 tkinter設定的 StringVar變數都再丟進全域變數中
讓下載的函式都調用全域變數就好
拿我的程式來說
downloadbutton = Button(window, text = "下載影片", width = 15, command = threadstart) def subthreadstart(): global caption, captionbox downloadbutton["state"] = DISABLED analysisbutton["state"] = DISABLED filepathbutton["state"] = DISABLED downloadsubbutton["state"] = DISABLED caption = captionbox.get() threading.Thread(target = downloadYTsub).start() |
通過 threadstart去啟動下載函式
雖然略顯麻煩但可以在這個函式中插入按鈕狀態設定什麼的,一些全域變數的設定也可以在這裡
當作一個啟動階段