現(xiàn)高速批量下載)
DouYin 異步下載原理aiohttp asyncio 如何實(shí)現(xiàn)高速批量下載【免費(fèi)下載鏈接】DouYinAPI of DouYin for Humans used to Crawl Popular Videos and Musics項(xiàng)目地址: https://gitcode.com/gh_mirrors/douyin2/DouYinDouYin 是一個(gè)「為人類設(shè)計(jì)的抖音數(shù)據(jù)接口」開源項(xiàng)目它的核心能力是用 aiohttp asyncio 實(shí)現(xiàn)抖音熱門視頻與音樂的異步下載和批量抓取。傳統(tǒng)同步方式逐個(gè)下載視頻動(dòng)輒數(shù)分鐘而本項(xiàng)目通過協(xié)程并發(fā)與批量調(diào)度把幾十個(gè)文件的下載時(shí)間壓縮到幾秒。本文將從源碼角度拆解這套異步下載原理幫你理解如何用 asyncio 編排任務(wù)、用 aiohttp 處理網(wǎng)絡(luò) IO從而實(shí)現(xiàn)真正的高速批量下載。為什么需要異步下載同步方案慢在哪下載抖音視頻本質(zhì)是「等」網(wǎng)絡(luò)發(fā)請(qǐng)求后 CPU 基本閑置等服務(wù)器返回。同步方案只能排隊(duì)等待一個(gè) 10MB 的視頻下載 3 秒10 個(gè)視頻就要 30 秒而且每多一個(gè)請(qǐng)求就多一份等待成本。aiohttp asyncio 的異步下載方案則不同——協(xié)程在等待網(wǎng)絡(luò)響應(yīng)時(shí)主動(dòng)讓出 CPU讓其他協(xié)程繼續(xù)發(fā)起下載請(qǐng)求多個(gè)下載任務(wù)同時(shí)進(jìn)行總耗時(shí)接近最慢的那個(gè)任務(wù)而非所有任務(wù)之和。核心架構(gòu)Downloader 下載器如何編排異步任務(wù)DouYin 的異步下載由一套「下載器 處理器」架構(gòu)驅(qū)動(dòng)代碼非常清晰下載器負(fù)責(zé)并發(fā)調(diào)度位于douyin/downloaders/base.py處理器負(fù)責(zé)實(shí)際落盤視頻走douyin/handlers/video.py音樂走douyin/handlers/music.py底層文件寫入邏輯統(tǒng)一封裝在douyin/handlers/file.py。下載器維護(hù)一個(gè)handlers列表視頻和音樂可以同時(shí)交給多個(gè)處理器比如同時(shí)存本地和存 MongoDB互不干擾。這種設(shè)計(jì)讓異步下載的職責(zé)單一化調(diào)度歸調(diào)度寫文件歸寫文件。asyncio 事件循環(huán)與批量調(diào)度一次搞定 10 個(gè)任務(wù)異步下載的核心在douyin/downloaders/base.py的process_items方法。它先用asyncio.get_event_loop()拿到事件循環(huán)再按batch參數(shù)默認(rèn) 10把任務(wù)分批每批用asyncio.ensure_future把每個(gè)視頻包裝成 Future 協(xié)程任務(wù)最后用loop.run_until_complete(asyncio.wait(tasks))讓這一批任務(wù)并發(fā)跑完再進(jìn)入下一批。同時(shí)通過task.add_done_callback掛上回調(diào)配合 tqdm 實(shí)時(shí)刷新進(jìn)度條。tasks [asyncio.ensure_future(self.process_item(obj)) for obj in objs_batch] for task in tasks: task.add_done_callback(self.update_progress) loop.run_until_complete(asyncio.wait(tasks))這段代碼就是「高速批量下載」的關(guān)鍵一批 10 個(gè)下載任務(wù)同時(shí)發(fā)起而不是 10 個(gè)排隊(duì)等待。批量大小可以調(diào)節(jié)這正是異步下載性能調(diào)優(yōu)的核心旋鈕。aiohttp 實(shí)戰(zhàn)非阻塞的文件下載實(shí)現(xiàn)真正落盤用的是 aiohttp代碼在douyin/handlers/file.py。它創(chuàng)建aiohttp.ClientSession作為會(huì)話池用session.get(obj.play_url)發(fā)起請(qǐng)求——關(guān)鍵點(diǎn)在于await response.content.read()這個(gè) await 讓出控制權(quán)正是異步下載不阻塞事件循環(huán)的秘訣async with aiohttp.ClientSession() as session: async with session.get(obj.play_url, **kwargs) as response: if response.status 200: extension mime_to_ext(response.headers.get(Content-Type)) with open(full_path, wb) as f: f.write(await response.content.read())下載完成后它根據(jù)響應(yīng)頭的 Content-Type 自動(dòng)推斷擴(kuò)展名MP4、MP3 等以視頻 ID 命名保存。視頻處理器douyin/handlers/video.py和音樂處理器douyin/handlers/music.py都復(fù)用這套異步下載邏輯只是各自過濾對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)。失敗自動(dòng)重試異步下載的容錯(cuò)保障網(wǎng)絡(luò)下載難免失敗DouYin 在douyin/utils/fetch.py里做了雙保險(xiǎn)API 請(qǐng)求使用 requests retrying 裝飾器遇到 ConnectionError、ReadTimeout 會(huì)自動(dòng)重試重試次數(shù)和間隔在douyin/config.py里配置默認(rèn)最多重試 10 次等待 1~5 秒隨機(jī)抖動(dòng)避免集中重試打爆接口。文件下載環(huán)節(jié)則關(guān)閉 SSL 校驗(yàn)、設(shè)置 10 秒超時(shí)保證在弱網(wǎng)環(huán)境下也能穩(wěn)定完成異步下載任務(wù)。完整跑通一條命令批量下載抖音熱門視頻項(xiàng)目提供了開箱即用的示例examples/save_hot_videos_and_musics_to_file.py先調(diào)douyin.hot.video()拿到熱門視頻列表再實(shí)例化FileHandler指定保存目錄最后用VideoDownloader的download方法批量下載handler douyin.handlers.FileHandler(folder./videos) downloader douyin.downloaders.VideoDownloader([handler]) downloader.download(videos)運(yùn)行時(shí)你能看到 tqdm 進(jìn)度條按批次跳動(dòng)一批 10 個(gè)文件并發(fā)寫入幾秒內(nèi)全部完成——這就是 aiohttp asyncio 高速批量下載的最直觀體驗(yàn)??偨Y(jié)這套異步下載設(shè)計(jì)值得借鑒的 3 點(diǎn)任務(wù)分批并發(fā)用asyncio.wait讓每批任務(wù)并行而不是全部一次性塞給事件循環(huán)兼顧速度與穩(wěn)定性下載與處理解耦下載器管調(diào)度、處理器管落盤視頻/音樂/MongoDB 隨意組合重試 超時(shí)兜底網(wǎng)絡(luò)抖動(dòng)有重試異常有容錯(cuò)異步下載不再是「碰運(yùn)氣」。如果你正在寫抖音爬蟲或需要批量下載工具直接參考douyin/downloaders/和douyin/handlers/這兩個(gè)模塊的源碼就能快速?gòu)?fù)刻出一套屬于自己的 aiohttp 異步下載框架?!久赓M(fèi)下載鏈接】DouYinAPI of DouYin for Humans used to Crawl Popular Videos and Musics項(xiàng)目地址: https://gitcode.com/gh_mirrors/douyin2/DouYin創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考