目標:爬取自己賬號中購買的課程視頻。
這里采用的是手動輸入驗證碼的方式,有能力的盆友也可以通過圖像識別的方式自動填寫驗證碼。登錄后,采用session保持登錄。
第一步:首先查看驗證碼對應的代碼,可以從圖中看到驗證碼圖片的地址是:https://per.enetedu.com/Common/CreateImage?tmep_seq=1613623257608
顏色標紅的部分tmep_seq=1613623257608,是為了解決瀏覽器緩存問題加的時間戳,因此真正的驗證碼圖片地址是:https://per.enetedu.com/Common/CreateImage
第二步:找出登錄時提交的表單內容和POST地址。
(1) 不填寫用戶名密碼和驗證碼,直接點擊登錄,使用Chrome瀏覽器的Network檢查,找到POST地址:https://per.enetedu.com/AdminIndex/LoginDo
(2) 繼續向下看,找到提交的表單 Form Data。
因此帶有驗證碼的登錄代碼如下:
import requests from PIL import Image #用戶名-密碼-驗證碼方式,登錄 CaptchaUrl = "https://per.enetedu.com/Common/CreateImage" #獲取驗證碼地址 PostUrl = "https://per.enetedu.com/AdminIndex/LoginDo" #post登錄信息地址 client = requests.Session() username = '替換為自己的用戶名' password = '替換為自己的密碼' qr_code = client.get(CaptchaUrl) open('login.jpg', 'wb').write(qr_code.content) #將驗證碼圖片保存至本地 img = Image.open('login.jpg') img.show() #打開圖片 code = input("請輸入驗證碼: \n") #輸入驗證碼 postData = { #構造POST表單 'email': username, 'pwd': password, 'validateCode': code, 'x': '22', 'y': '19' } result = client.post(PostUrl,postData) #向PostUrl提交表單
登錄成功后,檢查視頻播放div對應的代碼,企圖找到視頻地址直接保存至本地。結果,如下圖所示,整個視頻是被分割成一段一段的.ts文件,分段加載到頁面中播放。GET每段視頻的地址為右側紅框圈起來的部分。
百度后才知道,整個視頻如何分段是由一個m3u8文件來決定的。m3u8文件中的內容如下所示,記錄了每段視頻start和end的編號。
#EXTM3U #EXT-X-VERSION:3 #EXT-X-ALLOW-CACHE:YES #EXT-X-TARGETDURATION:10 #EXTINF:10.000000, start_0-end_765064-record.gv.ts #EXTINF:10.000000, start_765064-end_1769567-record.gv.ts #EXTINF:10.000000, start_1769567-end_2600798-record.gv.ts #EXTINF:10.000000, start_2600798-end_3593502-record.gv.ts #EXTINF:10.000000, start_3593502-end_4500784-record.gv.ts #EXTINF:10.000000, start_4500784-end_5399861-record.gv.ts #EXTINF:10.000000, start_5399861-end_6288622-record.gv.ts #EXTINF:10.000000, start_6288622-end_7044459-record.gv.ts #EXTINF:10.000000, start_7044459-end_7878487-record.gv.ts #EXTINF:10.000000, start_7878487-end_8811793-record.gv.ts #EXTINF:10.000000,
因此,下載視頻的關鍵是獲取m3u8文件,通過這個視頻的m3u8文件來分段下載視頻。
我是人工找出m3u8的下載地址,暫時還沒研究出來怎么通過視頻地址自動解析出m3u8地址。找的方法很簡單,還是在Chrome的Network控制臺找。打開Network控制臺,刷新頁面,就可以找到如圖所示的m3u8文件。查看m3u8文件的相關信息,可以看到紅框圈起來的地址就是這個視頻的m3u8下載地址。
對比兩個地址,可以發現文件名前的地址相同,視頻下載地址即為"標紅地址"+"m3u8文件中列出的視頻段文件名":
https://bcdn.enetedu.com/conv/cdnfile/video/2016_06_27/1467034852884_f5821b/hi/record.m3u8
https://bcdn.enetedu.com/conv/cdnfile/video/2016_06_27/1467034852884_f5821b/hi/start_643887-end_1083181-record.gv.ts
因此可以將這部分地址設為:urlroot = https://bcdn.enetedu.com/conv/cdnfile/video/2016_06_27/1467034852884_f5821b/hi
為了方便下載其他視頻時動態修改,改為動態截取:
url = input("請輸入m3u8文件地址:") urlRoot=self.url[0:url.rindex('/')]
這一步使用上一步拼接的地址循環下載ts視頻即可。下載時,使用登錄時創建的session下載。
session是會話的意思,它可以讓服務器“認得”客戶端。簡單理解就是,把每一個客戶端和服務器的互動當作一個“會話”。既然在同一個“會話”里,服務器自然就能知道這個客戶端是否登錄過。代碼如下:
client = requests.Session() client.post(PostUrl,postData) #登錄 resp = client.get(download_path) #下載
碎片拼接的方法:下載完第一個ts片段后,直接在該文件后面繼續寫第二個ts片段,以此類推。而不是新建一個文件寫入。與驗證碼登錄結合起來,完整代碼如下:
import requests from PIL import Image import sys import m3u8 import time import os #用戶名-密碼-驗證碼方式,登錄 CaptchaUrl = "https://per.enetedu.com/Common/CreateImage" #獲取驗證碼地址 PostUrl = "https://per.enetedu.com/AdminIndex/LoginDo" #post登錄信息地址 client = requests.Session() username = '526257482@qq.com' password = 'dashuju_9514' qr_code = client.get(CaptchaUrl) open('login.jpg', 'wb').write(qr_code.content) #將驗證碼圖片保存至本地 img = Image.open('login.jpg') img.show() #打開圖片 code = input("請輸入驗證碼: \n") #輸入驗證碼 postData = { #構造POST表單 'email': username, 'pwd': password, 'validateCode': code, 'x': '56', 'y': '19' } result = client.post(PostUrl,postData) #向PostUrl提交表單 #循環下載ts視頻 class VideoCrawler(): def __init__(self,url): super(VideoCrawler, self).__init__() self.url=url self.final_path=r"D:\Download\Film" #下載并解析m3u8文件 def get_url_from_m3u8(self,readAdr): print("正在解析真實下載地址...") with open('temp.m3u8','wb') as file: file.write(requests.get(readAdr).content) m3u8Obj=m3u8.load('temp.m3u8') print("解析完成") return m3u8Obj.segments def run(self): print("Start!") start_time=time.time() realAdr = self.url #m3u8下載地址 urlList=self.get_url_from_m3u8(realAdr) #解析m3u8文件,獲取下載地址 urlRoot=self.url[0:self.url.rindex('/')] i=1 outputfile=open(os.path.join(self.final_path,'%s.ts'%self.fileName),'wb')#初始創建一個ts文件,之后每次循環將ts片段的文件流寫入此文件中從而不需要在去合并ts文件 for url in urlList: try: download_path = "%s/%s" % (urlRoot, url.uri) #拼接地址 resp = client.get(download_path) #使用拼接地址去爬取數據 progess = i/len(urlList)#記錄當前的爬取進度 outputfile.write(resp.content) #將爬取到ts片段的文件流寫入剛開始創建的ts文件中 sys.stdout.write('\r正在下載:{},進度:{:.2%}'.format(self.fileName,progess))#通過百分比顯示下載進度 sys.stdout.flush()#通過此方法將上一行代碼刷新,控制臺只保留一行 except Exception as e: print("\n出現錯誤:%s",e.args) continue#出現錯誤跳出當前循環,繼續下次循環 i+=1 outputfile.close() print("下載完成!總共耗時%d s"%(time.time()-start_time)) print("開始轉換視頻格式!") success = os.system(r'copy /b D:\Download\Film\{0}.ts D:\Download\Film\{0}.mp4'.format(self.fileName)) #ts轉成mp4格式 if (not success): print("格式轉換成功!") os.remove(self.final_path+'\\'+self.fileName+".ts") #刪除ts和m3u8臨時文件 os.remove("temp.m3u8") if __name__=='__main__': m3u8_addr = input("輸入m3u8文件下載地址:\n") crawler=VideoCrawler(m3u8_addr) crawler.fileName = input("輸入文件名:\n") crawler.run() quitClick=input("請按Enter鍵確認退出!")
代碼可以實現分段加載視頻的爬取功能,其中還有很多細節待完善如:
到此這篇關于Python爬蟲爬取ts碎片視頻+驗證碼登錄功能的文章就介紹到這了,更多相關Python爬蟲爬取視頻內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!
標簽:烏蘭察布 平頂山 烏蘭察布 哈爾濱 郴州 大慶 海南 合肥
巨人網絡通訊聲明:本文標題《Python爬蟲爬取ts碎片視頻+驗證碼登錄功能》,本文關鍵詞 Python,爬蟲,爬取,碎片,視頻,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。