基于Python實(shí)現(xiàn)全自動(dòng)下載抖音視頻
很多人喜歡玩抖音,我也喜歡看抖音小姐姐,可拿著手機(jī)一個(gè)個(gè)找視頻太費(fèi)勁。作為一個(gè)程序員,如何能在電腦前一邊編程一邊輕松地看抖音小姐姐呢?
下面利用Python,簡(jiǎn)單的三個(gè)步驟就可以將你喜歡的抖音小姐姐的視頻自動(dòng)下載下來(lái)了。
Charles
Charles是一個(gè)App抓包工具,與Filddler的功能相似,利用它可以得到App運(yùn)行過(guò)程中發(fā)生的所有網(wǎng)絡(luò)請(qǐng)求和響應(yīng)內(nèi)容。
在電腦端下載安裝完Charles后,需要配置證書(shū),最后開(kāi)啟SSL監(jiān)聽(tīng)。
手機(jī)端則是需要與電腦在同一網(wǎng)絡(luò)下,比如都連接家里的Wi-Fi,然后在手機(jī)的Wi-Fi高級(jí)選項(xiàng)里使用Charles代理,輸入電腦的IP地址,端口8888,最后為證書(shū)命名。
連好以后,手機(jī)打開(kāi)抖音App,隨著操作App的動(dòng)作,可以獲取到視頻的請(qǐng)求信息。
通過(guò)多次實(shí)驗(yàn),發(fā)現(xiàn)鏈接的后面是會(huì)不停的改變,只有鏈接的前頭始終不變,即「http://v1-dy」「http://v6-dy」「http://v9-dy」不變。
所以在寫(xiě)腳本的時(shí)候,可以用這些信息做為鏈接開(kāi)頭。
MitmProxy
利用MitmProxy中的mitmdump組件,對(duì)接Python腳本,用Python實(shí)現(xiàn)監(jiān)聽(tīng)后的處理。
這里我只是利用腳本獲取鏈接,并沒(méi)有直接利用腳本下載視頻。
因?yàn)槲沂窃趍itmdump.exe文件所在的文件夾運(yùn)行腳本,腳本里導(dǎo)入不了requests模塊。
不想配置環(huán)境變量了,所以只獲取鏈接。
利用鏈接再去下載視頻,視頻鏈接需要去重,因?yàn)榭赡軙?huì)有重復(fù)的。
Python腳本如下:
def response(flow): urls = [’http://v1-dy’, ’http://v3-dy’, ’http://v6-dy’, ’http://v9-dy’] # 對(duì)url進(jìn)行篩選,只選取視頻的url for url in urls: if url in flow.request.url: print(’nn抖音視頻nn’) with open(’douyin.csv’, ’a+’, encoding=’utf-8-sig’) as f:f.write(flow.request.url + ’n’)
配置抖音的Appium參數(shù):
點(diǎn)擊藍(lán)色按鈕,手機(jī)自動(dòng)啟動(dòng)抖音App。接著操作手機(jī),然后點(diǎn)擊Appium的刷新鍵,獲取元素定位代碼。
通過(guò)本次的實(shí)踐發(fā)現(xiàn)Appium有時(shí)并不能很好的獲取元素的定位,針對(duì)找不到的元素,我直接對(duì)手機(jī)屏幕位置進(jìn)行點(diǎn)擊。
由于大家手機(jī)屏幕大小不同,這個(gè)參數(shù)肯定是會(huì)變化的,所以存在弊端,無(wú)法通用。
左右滑動(dòng)切換圖片
大致操作如上圖。UP主的主頁(yè)圖漏了,請(qǐng)自行腦補(bǔ),Python代碼如下:
import timeimport randomfrom appium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom appium.webdriver.common.touch_action import TouchActionfrom selenium.webdriver.support import expected_conditions as ECdef main(): # 設(shè)置驅(qū)動(dòng)配置 server = ’http://localhost:4723/wd/hub’ desired_caps = { ’platformName’: ’Android’, ’deviceName’: ’STF_AL00’, ’appPackage’: ’com.ss.android.ugc.aweme’, ’appActivity’: ’.main.MainActivity’, # 關(guān)閉手機(jī)軟鍵盤(pán) ’unicodeKeyboard’: True, ’resetKeyboard’: True } driver = webdriver.Remote(server, desired_caps) wait = WebDriverWait(driver, 60) # 同意用戶隱私協(xié)議,點(diǎn)擊 button_1 = wait.until(EC.presence_of_element_located((By.ID, ’com.ss.android.ugc.aweme:id/q6’))) button_1.click() # 禁止電話權(quán)限,點(diǎn)擊 button_2 = wait.until(EC.presence_of_element_located((By.ID, ’com.android.packageinstaller:id/permission_deny_button’))) button_2.click() # 禁止位置權(quán)限,點(diǎn)擊 button_3 = wait.until(EC.presence_of_element_located((By.ID, ’com.android.packageinstaller:id/permission_deny_button’))) button_3.click() time.sleep(2) # 向上滑動(dòng),進(jìn)入抖音視頻播放頁(yè)面 TouchAction(driver).press(x=515, y=1200).move_to(x=515, y=1000).release().perform() # 這里需要設(shè)置一個(gè)較長(zhǎng)時(shí)間的延遲,因?yàn)槎兑粲幸龑?dǎo)操作和提示,需等待片刻 time.sleep(20) # 點(diǎn)擊抖音'喜歡'處,以此進(jìn)入登錄界面 TouchAction(driver).press(x=950, y=800).release().perform() # 點(diǎn)擊密碼登錄 button_4 = wait.until(EC.presence_of_element_located((By.ID, ’com.ss.android.ugc.aweme:id/afg’))) button_4.click() # 輸入賬號(hào) button_5 = wait.until(EC.presence_of_element_located((By.ID, ’com.ss.android.ugc.aweme:id/ab_’))) button_5.send_keys(’你的賬號(hào)’) # 輸入密碼 button_6 = wait.until(EC.presence_of_element_located((By.ID, ’com.ss.android.ugc.aweme:id/aes’))) button_6.send_keys(’你的密碼’) time.sleep(2) # 因?yàn)闀?huì)跳出軟鍵盤(pán),會(huì)遮擋登錄按鈕,需點(diǎn)擊軟鍵盤(pán)取消 TouchAction(driver).press(x=980, y=1850).release().perform() time.sleep(2) # 點(diǎn)擊登錄按鈕 button_7 = wait.until(EC.presence_of_element_located((By.ID, ’com.ss.android.ugc.aweme:id/abb’))) button_7.click() time.sleep(2) # 登錄成功,進(jìn)入抖音視頻界面,點(diǎn)擊下方標(biāo)題欄 '我' TouchAction(driver).press(x=990, y=1850).release().perform() # 進(jìn)入個(gè)人主頁(yè),點(diǎn)擊關(guān)注處 button_8 = wait.until(EC.presence_of_element_located((By.ID, ’com.ss.android.ugc.aweme:id/a_7’))) button_8.click() # 進(jìn)入關(guān)注欄,點(diǎn)擊第二個(gè)關(guān)注 button_9 = wait.until(EC.presence_of_element_located((By.XPATH, ’ /hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.LinearLayout/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout[2]/android.widget.RelativeLayout[1]’))) button_9.click() # 進(jìn)入U(xiǎn)P主主頁(yè),點(diǎn)擊第一個(gè)視頻 button_10 = wait.until(EC.presence_of_element_located((By.ID, ’com.ss.android.ugc.aweme:id/aqm’))) button_10.click() # 不斷下滑頁(yè)面,直到底部 while True: TouchAction(driver).press(x=515, y=1247).move_to(x=515, y=1026).release().perform() time.sleep(float(random.randint(5, 10)))if __name__ == ’__main__’: main()
下載視頻代碼,需要對(duì)視頻鏈接去重:
import pandas as pdimport requestsimport osnum = 0dom = []folder_path = 'F:/video/'os.makedirs(folder_path)df = pd.read_csv(’douyin.csv’, header=None, names=['url'])# 對(duì)鏈接去重及去除剛進(jìn)入抖音獲取的視頻鏈接for i in df[’url’][2:]: if i not in dom: dom.append(i)# 下載視頻for j in dom: url = j num += 1 response = requests.get(url, stream=True) filename = str(num) + ’.mp4’ with open(’F:video’ + filename, ’ab+’) as f: f.write(response.content) f.flush() print(filename + ’下載完成’)
最后成功獲取小姐姐們的全部視頻:
我打算將視頻里喜歡的妹子全剪輯出來(lái),做一個(gè)「最美瞬間」系列的視頻,分享給大家!
源碼地址:
https://github.com/Tobby-star/douyin
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. ASP實(shí)現(xiàn)加法驗(yàn)證碼2. 使用Spry輕松將XML數(shù)據(jù)顯示到HTML頁(yè)的方法3. 詳解盒子端CSS動(dòng)畫(huà)性能提升4. asp批量添加修改刪除操作示例代碼5. PHP循環(huán)與分支知識(shí)點(diǎn)梳理6. JSP之表單提交get和post的區(qū)別詳解及實(shí)例7. 三個(gè)不常見(jiàn)的 HTML5 實(shí)用新特性簡(jiǎn)介8. IE6/IE7/IE8/IE9中tbody的innerHTML不能賦值的完美解決方案9. 淺談SpringMVC jsp前臺(tái)獲取參數(shù)的方式 EL表達(dá)式10. 詳解JSP 內(nèi)置對(duì)象request常見(jiàn)用法
