手把手教你抖音系列視頻批量下載器開發(fā)
回復(fù)“書籍”即可獲贈(zèng)Python從入門到進(jìn)階共10本電子書
??博客主頁(yè):https://blog.csdn.net/as604049322
??歡迎點(diǎn)贊 ?? 收藏 ?留言 ?? 歡迎討論!
??本文由?小小明-代碼實(shí)體?原創(chuàng),首發(fā)于?CSDN??
??未來(lái)很長(zhǎng),值得我們?nèi)Ρ几案篮玫纳?
程序使用演示
大家好,我是小小明。這里開發(fā)了一個(gè)抖音視頻下載器,打開效果如下:

如果本地的谷歌游覽器之前從來(lái)沒有訪問過抖音主頁(yè),點(diǎn)擊開始下載按鈕會(huì)有如下輸出:

此時(shí)我們只需要點(diǎn)擊 訪問抖音主頁(yè),程序則會(huì)使用本地的谷歌游覽器訪問抖音主頁(yè)。再次點(diǎn)擊下載按鈕:

可以看到該視頻是一個(gè)合集視頻:

那么程序只需要勾選第一個(gè)選項(xiàng)即可下載整個(gè)合集:

這樣一次性就將整個(gè)合集都下載下來(lái)了:

開發(fā)流程
首先根據(jù)上一篇文章:提取谷歌游覽器Cookie的五重境界
讀取谷歌游覽器安裝的位置和本地抖音相關(guān)的cookie:
"""
小小明的代碼
CSDN主頁(yè):https://blog.csdn.net/as604049322
"""
__author__?=?'小小明'
__time__?=?'2022/1/23'
import?base64
import?json
import?os
import?sqlite3
import?winreg
import?win32crypt
from?cryptography.hazmat.primitives.ciphers.aead?import?AESGCM
def?load_local_key(localStateFilePath):
????"讀取chrome保存在json文件中的key再進(jìn)行base64解碼和DPAPI解密得到真實(shí)的AESGCM?key"
????with?open(localStateFilePath,?encoding='u8')?as?f:
????????encrypted_key?=?json.load(f)['os_crypt']['encrypted_key']
????encrypted_key_with_header?=?base64.b64decode(encrypted_key)
????encrypted_key?=?encrypted_key_with_header[5:]
????key?=?win32crypt.CryptUnprotectData(encrypted_key,?None,?None,?None,?0)[1]
????return?key
def?decrypt_value(key,?data):
????"AESGCM解密"
????nonce,?cipherbytes?=?data[3:15],?data[15:]
????aesgcm?=?AESGCM(key)
????plaintext?=?aesgcm.decrypt(nonce,?cipherbytes,?None).decode('u8')
????return?plaintext
def?fetch_host_cookie(host):
????"獲取指定域名下的所有cookie"
????userDataDir?=?os.environ['LOCALAPPDATA']?+?r'\Google\Chrome\User?Data'
????localStateFilePath?=?userDataDir?+?r'\Local?State'
????cookiepath?=?userDataDir?+?r'\Default\Cookies'
????#?97版本已經(jīng)將Cookies移動(dòng)到Network目錄下
????if?not?os.path.exists(cookiepath)?or?os.stat(cookiepath).st_size?==?0:
????????cookiepath?=?userDataDir?+?r'\Default\Network\Cookies'
????#?print(cookiepath)
????sql?=?f"select?name,encrypted_value?from?cookies?where?host_key?like?'%.{host}'"
????cookies?=?{}
????key?=?load_local_key(localStateFilePath)
????with?sqlite3.connect(cookiepath)?as?conn:
????????cu?=?conn.cursor()
????????for?name,?encrypted_value?in?cu.execute(sql).fetchall():
????????????cookies[name]?=?decrypt_value(key,?encrypted_value)
????return?cookies
def?get_chrome_path():
????try:
????????key?=?winreg.OpenKey(winreg.HKEY_CLASSES_ROOT,?r"ChromeHTML\Application")
????????path?=?winreg.QueryValueEx(key,?"ApplicationIcon")[0]
????????chrome_path?=?path[:path.rfind(",")]
????????return?chrome_path
????except?FileNotFoundError?as?e:
????????return
if?__name__?==?'__main__':
????print(fetch_host_cookie("douyin.com"))
????print(get_chrome_path())
有了這個(gè)工具類,我們就不再需要使用selenium。
然后是視頻解析的核心代碼如下:
def?get_video_url(url,?cookies):
????headers?=?{
????????"User-Agent":?"Mozilla/5.0?(Windows?NT?10.0;?Win64;?x64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/87.0.4280.66?Safari/537.36",
????????"referer":?"https://www.douyin.com"
????}
????res?=?requests.get(url,?headers=headers,?cookies=cookies)
????if?res.status_code?==?200:
????????RENDER_DATA,?=?re.findall(
????????????r'',?res.text)
????????data?=?json.loads(unquote(RENDER_DATA))
????????key?=?'8'?if?url.find("collection")?!=?-1?else?'34'
????????try:
????????????detail?=?data[key]['aweme']['detail']
????????????title?=?detail['desc']
????????except?Exception?as?e:
????????????print(f"{url}無(wú)效,報(bào)錯(cuò)的key:",?e)
????????????return
????????if?not?title:
????????????title,?=?re.findall("]+>\s*([^>]+)\s* ",?res.text)
????????video_url?=?urljoin(url,?detail['video']['playApi'])
????????collection_urls?=?set(re.findall("http://www.douyin.com/collection/\d+/\d+",?res.text))
????????collection_urls?=?[urljoin("https://www.douyin.com",?url)?for?url?in?collection_urls]
????????collection_urls.sort(key=lambda?s:?int(s[s.rfind("/")?+?1:]))
????????collection_title?=?re.findall("]+>([^<>]+)
",?res.text)[0]
????????return?video_url,?title,?collection_urls,?collection_title
????else:
????????print('視頻鏈接請(qǐng)求失?。。?!')
視頻下載的核心代碼:
def?download_video(video_url,?title,?folder):
????start_time?=?time.time()
????res?=?requests.get(url=video_url,?stream=True)
????done_size,?total?=?0,?int(res.headers['content-length'])
????chunk_size?=?1024?*?1024
????title?=?format_filename(title)
????file_size?=?round(int(res.headers['content-length'])?/?1024?/?1024,?2)
????basename?=?f"{title}.mp4"
????filename?=?f"{folder}/{title}.mp4"
????if?os.path.exists(filename):
????????print(basename,?"已存在,跳過...")
????????return
????print("-----------------------------------")
????print(f'開始下載文件:{basename}\n當(dāng)前文件大?。?span style="color: #e06c75;line-height: 26px;">{file_size}MB')
????with?open(filename,?'wb')?as?f:
????????for?chunk?in?res.iter_content(chunk_size):
????????????f.write(chunk)
????????????done_size?+=?len(chunk)
????????????cost_time?=?time.time()?-?start_time
????????????yield?done_size,?cost_time,?total
????????????# print(f"進(jìn)度:{done_size / total:.2%},{done_size / cost_time / 1024 / 1024:.2f}MB/s")
????cost_time?=?time.time()?-?start_time
????print(f'文件:{basename}?下載完成!\n耗時(shí):{cost_time:0.2f}?秒')
關(guān)于視頻鏈接的分析,大家可以參考才哥的文章:
鏈接:https://mp.weixin.qq.com/s/NNVT6IH6dpT0rTeu1-oD6w
UI界面設(shè)計(jì)核心代碼如下:
layout?=?[
????[sg.Text('抖音視頻地址:',?font=("楷體",?12)),
?????sg.In(key='url',?size=(70,?1),?text_color="#bb8b59",
???????????default_text="https://www.douyin.com/video/6803929443069988103")],
????[sg.Checkbox('如果是一個(gè)合集則下載整個(gè)合集',?key="download_collection",?default=False),
?????sg.Button('開始下載'),
?????sg.Button('清空輸出'),
?????sg.Button('訪問抖音主頁(yè)'),
?????sg.Button('訪問當(dāng)前地址'),
?????],
????[sg.Output(size=(85,?10),?key="out",?text_color="#15d36a")],
????[
????????sg.ProgressBar(1000,?size=(20,?20),?key='video_bar',?bar_color=("#bb8b59",?"#295273")),
????????sg.Text('000.0MB,00/00\n00:00<00:00',?key="message_video"),
????????sg.ProgressBar(1000,?size=(20,?20),?key='progressbar',?bar_color=("#15d36a",?"#295273")),
????????sg.Text('00.00MB/00.00MB\n00.00MB/s',?key="message")
????],
????[sg.Text('輸出目錄:',?font=("楷體",?12)),
?????sg.In(size=(35,?1),?key="save_dir"),
?????sg.FolderBrowse('...',?target='save_dir',?initial_folder="."),
?????sg.Checkbox('?下載完畢后?\n打開所在目錄',?key="open_folder",?default=True),
?????sg.Button('打開輸出目錄'),
?????],
????[sg.Text("@小小明:https://blog.csdn.net/as604049322"),?],
]
程序下載
該工具的完整代碼和已打包的工具下載地址:
https://gitcode.net/as604049322/python_gui/-/tree/master/douyin
小伙伴們,快快用實(shí)踐一下吧!如果在學(xué)習(xí)過程中,有遇到任何問題,歡迎加我好友,我拉你進(jìn)Python學(xué)習(xí)交流群共同探討學(xué)習(xí)。
-------------------?End?-------------------
往期精彩文章推薦:

歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持
想加入Python學(xué)習(xí)群請(qǐng)?jiān)诤笈_(tái)回復(fù)【入群】
萬(wàn)水千山總是情,點(diǎn)個(gè)【在看】行不行
/今日留言主題/
隨便說(shuō)一兩句吧~~
