基於python實現的vip電影爬蟲
序言:關於我CSDN連發五次文章都失敗並且封號一天警告,一怒之下轉博客園發現新大陸這件事。。。。
這篇文章的由來,是我為了一個月內看的三部電影,充了三個網站的會員之后,痛定思痛,決定再也不干這種傻事了,於是乎,我拿起了python—號稱除了生孩子什么都能干的工具。
遺憾的是,在閱遍了CSDN,B站,知乎,博客園之后,並沒有任何一個網站可以解決我的問題,尤其是我最依賴的CSDN,要么就是壓根不能實踐的方法,要么就是很老已經不能用的方法,濫竽充數和渾水摸魚的文章浪費了大量的時間,只能說csdn的知識保護意識很強吧,現在但凡有一點擦邊都不讓發布。
由於解析電影的網站不同,衍生出了數種不同的爬蟲思路,變化性較大,加之解析網站變動較大,這也是在各大資源網站都找不到有用的獲取vip視頻的教程的原因之一。
鄭重聲明:該文章僅供參考學習,他人不得利用非法手段牟利。
目錄:
First and foremost:
電影資源常見解析類型
一.直接解析,另存為保存到本地(簡單暴力下載)
小白食用,極度舒適。
二.可直接抓包的電影
比較簡單的抓包
三.無加密的m3u8格式電影
第一步,打開右鍵打開檢查,在network(網絡)里找到m3u8文件
第二步,通過m3u8文件下載每一個小的ts文件,並完成合並
四.AES加密的的m3u8文件
基於第三種的基礎,這里多了一個加密格式
first.我們需要下載每一的目錄(m3u8文件)
second.我們需要從目錄里提取AES秘鑰和每個ts網址(正則)
last.用得到的秘鑰解密每一個ts文件,開啟多線程下載並合並文件
First and foremost:
本文文字敘述只是整理思路,輔助理解,真正的靈魂在代碼,一定要認真看代碼。
影視資源常見解析類型
適用人群:
1.純小白,就是想白嫖電影的
2.初學者,emmm。。至少要會個requests和基本語法吧
3.較為高級一點的初學者,os,requests,time,基礎re,基礎concurrent,基礎AES(為什么都是基礎?因為我就這水平。。。。)
4.大佬(反正除了123就直接統稱為大佬。。。鼠?)
一.直接解析,另存為保存到本地(簡單暴力下載)
小白食用,極度舒適。
最簡單沒有之一的一種獲取視頻的方法,非常的香,無基礎暢享!
此網站實用於騰訊視頻,愛奇藝,優酷,B站(非大會員)的解析觀影
其中,騰訊視頻直接鼠標兩次右鍵另存為下載到本地。(注意格式是mp4,不是html)
而除了騰訊視頻其他的視頻平台則不能直接右鍵下載。另,此網站不能直接抓包。
二.可直接抓包的電影
這個是僅次於(一)的簡單,打開檢查,選中media(媒體),然后解析播放(切記順序不要亂),就會刷新出文件,雙擊點開文件,進入視頻界面,直接下載。大電影用的比較少,下載也不慢,不妨一試。
呃,比如b站視頻不能直接下載嘛不是,直接抓包就完了。
解析地址選用:90偶爾 - QQ群:1265608 (iiiv.vip)(非常好用)
三.無加密的m3u8格式電影
所用到模塊:requests,os,time,concurrent(不必須)
最近在看羅小黑戰記(時隔七年終於更新了),然鵝,居然只有某站大會員才能看,本着能白嫖絕不三連,呸,花錢,的思想,我找到了一個可以解析某站會員視頻的網站:
順便推薦這個很好地網站,里面東西非常多。(我當時用的時候還好好的,時隔半年,它現在要關注微信公眾號才能順利使用了·····,順便一提,現在大多數資源都要關注公眾號,而且理由都是惡意爬蟲、惡意盜用接口等等,也不知道真的還是想恰個飯。。。。)
選擇OK接口(當時了,現在不行的話隨機應變自己找找吧)
此時就可以觀看該電影,嗯,用過的應該知道,m3u8格式的視頻不在大網站上的話,非常容易卡,十分影響觀影體驗,於是我們選擇下載電影。那么,重點就來了。
對於m3u8格式,簡單來說就是將一個大視頻(幾個小時)切割成上千個小的視頻片段,后綴為ts,可以跟正常的MP4一樣播放。然后你看視頻的時候就一個個片段渲染,更詳細的可以直接在CSDN或者百度搜搜,這里不贅述(其實是我也沒有深入了解嘿嘿嘿)。
所以我們的思路就是:
0.在解析網站中獲取m3u8文件(or php)
1.把所有的網址提取出來,剔除‘#’開頭的沒用數據
2.遍歷獲取每一個視頻片段
3.然后將所有的視頻片段合並成一個大的電影文件
4.刪除下載的每一個視頻片段
#補充
5.編寫一個下載ts片段的函數,用於開創線程池,加快速度
6.下載過程可能會失敗,所以一定要設置最長get時間,並且限定次數防止由於資源問題程序卡死
都是血與淚教訓,一步一步探索出來的東西。
第一步,打開右鍵打開檢查,在network(網絡)里找到m3u8文件
打開檢查,選中XHR,然后解析播放(切記順序不要亂),就會刷新出許多文件
名稱多為index.m3u8,沒有的話就找后綴為m3u8的文件雙擊,就會下載到本地一個文檔,打開之后就是這個樣子的
大概有兩千多行吧。。。。
嗯,這個文件能看到許多的https網址,就是每一個視頻片段,ts格式的。
第二步,編寫python代碼
ok,思路清晰了以后,就開始編寫代碼了。話不多說上代碼(也不算長)
#導入模塊
import requests
import os import time from concurrent.futures import ThreadPoolExecutor start = time.time() #准備下載路徑 m3u8 = [] with open('play.php','r') as file: lst = file.readlines() for i in lst: i = i.strip() if i.startswith('#'): continue else: m3u8.append(i) print(f'目標文件數共{len(m3u8)}個') #下載一個ts文件的函數 def download_ts(i): for _ in range(10): try: with open(f'{i}.ts','wb') as file: resp = requests.get(m3u8[i],timeout=15).content file.write(resp) print(f'第{i}個ts片段已下載完成!') break except: print(f'第{i}個ts文件下載失敗,重新下載!') continue with ThreadPoolExecutor(100) as t: for i in range(len(m3u8)): t.submit(download_ts,i) t.shutdown() #補錄程序 with ThreadPoolExecutor(50) as f: for i in range(len(m3u8)): with open(f'{i}.ts','rb+') as file: if file.read(): continue else: f.submit(download_ts,i) f.shutdown() print('ts文件下載完畢') #ts文件的合並 print('ts文件開始合並....') with open('羅小黑戰記.mp4','wb') as file: for i in range(len(m3u8)): with open(f'{i}.ts','rb') as f: f_view = f.read() file.write(f_view) print('ts文件合並完畢!') #ts文件的刪除操作 print('開始刪除ts文件....') for i in range(len(m3u8)): try: os.remove(rf'C:\Users\我的電腦\Desktop\python學習\python爬蟲項目\vip電影全解\羅小黑戰記番劇\{i}.ts') except FileNotFoundError: continue print('ts文件刪除完畢!') print('電影完美下載!') end = time.time() print('本次下載共耗時長:',end-start,'s')
headers是反爬,在這里不加也沒有影上面的程序開了線程池(ThreadPoolExecutor),所以一部電影三分鍾就能下載下來,不開的話就非常的慢,遍歷下載得一個多小時才行。
另外,由於網絡爬蟲可能存在各種錯誤,所以在downlaod函數和后續刪除ts片段中都用try-except捕獲異常,並且開了一個線程池做補錄,下載第一次未能順利下載下來的內容。
time模塊用來反饋下載電影所用時間,也可以不用。
在XHR里找m3u8,預覽里一般都可以看到上千行的網址,如上圖。
四.AES加密的的m3u8文件
所用到的模塊:requests,re,AES,os,time,concurrent(非必須)
比較進階一點的爬蟲的(真的就是一點點)
在(三)中,我們學會了如何下載m3u8格式的視頻,但並非所有的m3u8都是那么的純潔,有些網站非常的狗,對文件設置了加密(我只見過AES加密的,but據說有其他加密模式反正我沒見到),所以這里我們只討論如何解決有AES加密的視頻。
1.首先,我們需要判斷是否有加密
2.其次,既然是加密,我們就需要秘鑰(key),獲取他
3.通過秘鑰(key)來解析獲取ts文件
#其實就是比(二)多了個解密模塊嘛
我們這里選取B站會員(最難處理的就它了,傲嬌的要死)的羅小黑戰記(37-40集),作為范例。
first.我們需要下載每一集的目錄(m3u8文件)
按照(三)中的方法下載就完了。
b站大會員選ok接口 (很顯然,現如今如果變動了的話隨機應變都是可以解決的)
#導入模塊
import requests
import os from Crypto.Cipher import AES #AES解密模塊 import time from concurrent.futures import ThreadPoolExecutor import re start = time.time() #准備下載路徑 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64' 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.73'} def download_ts(i): for _ in range(10): try: with open(f'{i}.ts', 'wb') as file: response = requests.get(m3u8[i], headers=headers, timeout=15).content cryptor = AES.new(key, AES.MODE_CBC, key) file.write(cryptor.decrypt(response)) print(f'第{i}個ts片段已下載完成!') break except: print(f'第{i}個ts文件下載失敗,重新下載!') continue for _ in range(4): m3u8=[] with open(f'index ({_+7}).m3u8','r+',encoding='utf-8') as file: r = file.read() obj = re.compile(r'URI="(?P<url>.*?)"',re.S) keyurlx = obj.finditer(r) for x in keyurlx: keyurl = x.group('url') file.seek(0,0) lst = file.readlines() for i in lst: i = i.strip() if i.startswith('#'): continue else: m3u8.append(i) print(f'目標文件數共{len(m3u8)}個') respn = requests.get(keyurl,headers=headers) key = respn.text.encode('utf-8') with ThreadPoolExecutor(100) as t: for i in range(len(m3u8)): t.submit(download_ts,i) t.shutdown() #補錄程序 with ThreadPoolExecutor(50) as f: for i in range(len(m3u8)): with open(f'{i}.ts','rb+') as file: if file.read(): continue else: f.submit(download_ts,i) f.shutdown() print('ts文件下載完畢') #ts文件的合並 print('ts文件開始合並....') with open(f'實驗vip電影{_}.mp4','wb') as file: for i in range(len(m3u8)): with open(f'{i}.ts','rb') as f: f_view = f.read() file.write(f_view) print('ts文件合並完畢!') #ts文件的刪除操作 print('開始刪除ts文件....') for i in range(len(m3u8)): try: os.remove(rf'C:\Users\我的電腦\Desktop\python學習\python爬蟲項目\vip電影全解\羅小黑戰記番劇\{i}.ts') except FileNotFoundError: continue print('ts文件刪除完畢!') print('電影完美下載!') end = time.time() print('本次下載共耗時長:',end-start,'s') #很顯然,除了一下下載幾集之外,唯一的不同點就是解密,直接套用解密模板就行了。 response = requests.get(m3u8[i], headers=headers, timeout=15).content cryptor = AES.new(key, AES.MODE_CBC, key) file.write(cryptor.decrypt(response))
就像這樣。
由於這個是幾集,所以key我們選擇從下載的m3u8文件里提取,這里就用到了一點點的re(正則表達式)內容,當然也可以手動提取粘貼到代碼里,就是對於好幾集的劇來說太麻煩了。不過正則在提取每個ts文件網址的時候還是要用的。emmm除非你跟我一樣精,調用字符串startswich函數。。。。
key獲取之后一定要編碼成utf-8的格式,要不然程序會報錯(python這個笨逼他讀不懂其他編碼格式的數據)
上述的四種方法,一般來講前三種就能解決大多數視頻了,並且都不難,就是遇到哪種情況就用對應的方法解決就完了。