最近發現一些網站,可以解析各大視頻網站的vip。仔細想了想,這也算是爬蟲呀,爬的是視頻數據。 首先選取一個視頻網站,我選的是 影視大全 ,然後選擇上映不久的電影 “一齣好戲” 。 分析頁面 我用的是chrome瀏覽器,F12進入查看。選擇NetWork的Doc,發現主體部分的數據是從這個網站獲取的。 ...
最近發現一些網站,可以解析各大視頻網站的vip。仔細想了想,這也算是爬蟲呀,爬的是視頻數據。
首先選取一個視頻網站,我選的是 影視大全 ,然後選擇上映不久的電影 “一齣好戲” 。
分析頁面
我用的是chrome瀏覽器,F12進入查看。選擇NetWork的Doc,發現主體部分的數據是從這個網站獲取的。
在地址欄輸入這個鏈接,跳轉到了視頻來源的播放頁面。
當然,在這個頁面就可以直接觀看視頻了,但是我們要把視頻下載下來。
尋找視頻文件
仍然是之前那個頁面,在Other中,我們發現了一些奇怪的東西。
查一下,m3u8是個啥東西。
m3u8是蘋果公司推出一種視頻播放標準,是m3u的一種,不過 編碼方式是utf-8,是一種文件檢索格式,將視頻切割成一小段一小段的ts格式的視頻文件,然後存在伺服器中(現在為了減少I/o訪問次數,一般存在伺服器的記憶體中),通過m3u8解析出來路徑,然後去請求。
這下就清楚了,這就是我們要找的東西。
點擊Response,查看這個.m3u8的文件。觀察發現,.ts尾碼的文件地址是有規律的。我們只需要下載所有的.ts尾碼文件,然後把它們整合成一個文件即可。
合併.ts文件
命令行:“copy /b F:\f\*.ts E:\f\new.ts”。
執行該命令後,F:\f目錄下的全部TS文件就被合併成一個new.ts文件了(你原來的那堆文件仍然存在)。
這裡使用copy命令的文件合併功能進行ts文件的合併,copy後面的 /b 參數表示把文件按二進位格式來合併,如果不加這個參數,則會把目標當成文本文件來合併,併在文件內添加不必要的標記,這會導致播放出錯,所以必須加 /b 參數。
編寫腳本,下載.ts文件
from urllib import request import urllib from time import sleep import socket class CatchVideo(object): def __init__(self): self.headers = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36" self.url = "" def set_url(self, i): if i < 1000: self.url = "https://cdn.letv-cdn.com/20180811/YLDUgCD6/1000kb/hls/DtrOg2412%03d.ts" % i else: self.url = "https://cdn.letv-cdn.com/20180811/YLDUgCD6/1000kb/hls/DtrOg2412%04d.ts" % i # 獲取並下載ts文件 def dl_ts(self, i): rq = request.Request(self.url) rq.add_header('User-Agent', self.headers) response = request.urlopen(rq) resread = response.read() with open(str(i)+".ts", "wb") as f: f.write(resread) response.close()# 關閉urlopen方法,防止被ban def start_work(self): for i in range(0, 1563+1): self.set_url(i) try: self.dl_ts(i) print(str(i) + ".ts success") sleep(1) except urllib.error.URLError as e: print(e.reason) break except socket.timeout as e2: print(e2.reason) self.dl_ts(i) if __name__ == '__main__': catch_video = CatchVideo() socket.setdefaulttimeout(20) catch_video.start_work()
運行過程中,出現了兩次報錯,分別是:
- urllib.error.URLError :[WinError 10054] 遠程主機強迫關閉了一個現有的連接
-
socket.timeout read讀取超時
解決辦法:
1.增加response.close,關閉urlopen方法。
2.增加time.sleep,有一秒緩衝時間
3.設置socket.setdefaulttimeout,給socket預留緩衝時間
還存在問題
實際運行過程中,腳本執行效率略低。之後會加入多線程,繼續改進,增加運行效率。
參考博客:
https://blog.csdn.net/a33445621/article/details/80377424
https://blog.csdn.net/illegalname/article/details/77164521
更新代碼,加入多進程
修改了start_work方法和主進程:
def start_work(self, i): self.set_url(i) try: self.dl_ts(i) print(str(i) + ".ts success") sleep(1) except urllib.error.URLError as e: print(e.reason) self.dl_ts(i) except socket.timeout as e2: print(e2.reason) self.dl_ts(i) if __name__ == '__main__': catch_video = CatchVideo() socket.setdefaulttimeout(20)# 設置socket層超時時間20秒 I = 0 while I < 1563+1: # 5個進程併發運行 p_l = [Process(target=catch_video.start_work, args=(i,)) for i in range(I, I+5)] for p in p_l: p.start() for p in p_l: p.join() I = I + 5
這裡設置了5個進程同時運行,太多遠程主機會拒絕請求。
OK,這樣就能很快下載了。隔了幾天終於想起來還有個電影沒看,哈哈 ^_^