Python爬蟲進階之爬取某視訊並下載的實現
這幾天在家閒得無聊,意外的挖掘到了一個資源網站(你懂得),但是網速慢廣告多下載不了種種原因讓我突然萌生了爬蟲的想法。
下面說說流程:
一、網站分析
首先進入網站,F12檢查,本來以為這種低端網站很好爬取,是我太低估了web主。可以看到我重新整理網頁之後,出現了很多js檔案,並且響應獲取的程式碼與原始碼不一樣,這就不難猜到這個網站是動態載入頁面。
目前我知道的動態網頁爬取的方法只有這兩種:1、從網頁響應中找到JS指令碼返回的JSON資料;2、使用Selenium對網頁進行模擬訪問。原始碼問題好解決,重要的是我獲取的原始碼中有沒有我需要的東西。我再一次進入網站進行F12檢查原始碼,點選左上角然後在頁面點選一個視訊獲取一個元素的程式碼,結果裡面沒有嵌入的原視訊連結(看來我真的是把別人想的太笨了)。
沒辦法只有進行抓包,去找js請求的介面。再一次F12開啟網頁除錯工具,點選單獨的一個視訊進行播放,然後在Network中篩選一下,只看HXR響應(HXR全稱是XMLHTTPRequest,HMLHTTP是AJAX網頁開發技術的重要組成部分。除XML之外,XMLHTTP還能用於獲取其它格式的資料,如JSON或者甚至純文字。)。
然後我一項一項的去檢查返回的響應資訊,發現當我點選播放的時候有後綴為.m3u8的連結,隨後就不斷重新整理.ts檔案的連結。
本來以為這就是原視訊的地址,我傻傻的直接從這個m3u8檔案的headers中的URL直接進入網站看看,結果傻眼了,獲取的是一串串.ts的檔名。
沒辦法只能百度君了。 科普了一下,也就說我們必須把ts檔案都下載下來進行合併之後才能轉成視訊。
好了,視訊原地址弄清楚了,現在我們開始從一個視訊擴充套件到首頁的整個頁面的視訊。再一次進行抓包分析,發現一個API中包含了首頁的分類列表,然而裡面並沒有進入分類的URL地址,只有一個tagid值和圖片的地址。
於是我又在主頁點一個分類,再次進行抓包,發現了一個API中包含了一個分類的單頁所有視訊的資訊,通過他們的headers中的URL對比發現,關於視訊的前一部分都是https:xxxxxxx&c=video,然後m=categories,通過字面意思我們都可以知道是分類,而每個tagid值對應不同的分類。並且還發現每個URL中都追加了時間戳timestamp(這是web主為了確保請求不會在它第一次被髮送後即快取,看來還是有小心機啊)。當m=lists,則是每個分類下的視訊列表,這裡面我們就可以找到每個視訊對應的ID了。
通過id我們可以獲取到視訊的詳細資訊,並且還有m3u8檔案URL地址的後面一部分。
好了,網站我們解析清楚了,現在開始堆碼了。
二、寫程式碼
匯入相關模組
import requests from datetime import datetime import re #import json import time import os #視訊分類和視訊列表URL的前一段 url = "http://xxxxxxx/api/?d=pc&c=video&" #m3u8檔案和ts檔案的URL前一段 m3u8_url ='https://xxxxxxxxxxxxx/videos/cherry-prod/2020/03/01/2dda82de-5b31-11ea-b5ae-1c1b0da2bc3f/hls/480/' #構造請求頭資訊 header = {"user-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML,like Gecko) Version/5.1.7 Safari/534.57.2"} #建立空列表存放視訊資訊 vediomassag='' #返回當前時間戳 TimeStamp = int(datetime.timestamp(datetime.now()))
2.定義函式,獲取網站首頁分類列表資訊
#自定義函式獲取分類 def get_vediocategory(url,TimeStamp): cgURL = url + "m=categories×tamp=" + str(TimeStamp) + '&' response = requests.get(cgURL,headers=header) category = response.text # strrr='"%s"'%category # return strrr return category
3.定義函式,通過上一個函式返回的分類資訊,根據分類對應的id,輸入id並傳輸到當前URL中以便獲取分類下的視訊列表資訊
#獲取分類後的視訊列表 def get_vedioList(url,TimeStamp,tagID): listURL = url + "m=lists×tamp=" + str(TimeStamp) + '&' + "page=1&tag_id=" + str(tagID) + "&sort_type=&is_vip=0" response = requests.get(listURL,headers=header) vedioLists = response.text return vedioLists
4.在視訊列表資訊中獲取視訊對應的id,獲取單個視訊詳細資訊的URL
#獲取單個視訊的詳細資訊 def get_vediomassages(url,vedioID): videoURL = url + "m=detail×tamp=" + str(TimeStamp) + '&' + "&id=" + str(vedioID) response = requests.get(videoURL,headers=header) vediomassag = response.text return vediomassag
5.在視訊詳細資訊中找到m3u8檔案的下載地址,並將檔案儲存到建立的檔案中
#將下載的m3u8檔案放進建立的ts列表檔案中 def get_m3u8List(m3u8_url,vediomassag): lasturl = r'"m3u8_720_url":"(.*?)","download_url' last_url =re.findall(lasturl,vediomassag) lastURL=m3u8_url+str(last_url) response = requests.get(lastURL,headers=header) tsList = response.text cur_path='E:\\files' #在指定路徑建立資料夾 try: if not os.path.isdir(cur_path): #確認資料夾是否存在 os.makedirs(cur_path) #不存在則新建 except: print("資料夾存在") filename=cur_path+'\\t2.txt' #在資料夾中存放txt檔案 f = open(filename,'a',encoding="utf-8") f.write(tsList) f.close print('建立%s檔案成功'%(filename)) return filename
6.將m3u8檔案中的ts單個提取出來放進列表中。
# 提取ts列表檔案的內容,逐個拼接ts的url,形成list def get_tsList(filename): ls = [] with open(filename,"r") as file: line = f.readlines() for line in lines: if line.endswith(".ts\n"): ls.append(line[:-1]) return ls
7.遍歷列表獲取單個ts地址,請求下載ts檔案放進建立的資料夾中
# 批量下載ts檔案 def DownloadTs(ls): length = len(ls) root='E:\\mp4' try: if not os.path.exists(root): os.mkdir(root) except: print("資料夾建立失敗") try: for i in range(length): tsname = ls[i][:-3] ts_URL=url+ls[i] print(ts_URL) r = requests.get(ts_URL) with open(root,'a') as f: f.write(r.content) f.close() print('\r' + tsname + " -->OK ({}/{}){:.2f}%".format(i,length,i * 100 / length),end='') print("下載完畢") except: print("下載失敗")
程式碼整合
import requests from datetime import datetime import re #import json import time import os url = "http://xxxxxxxx/api/?d=pc&c=video&" m3u8_url ='https://xxxxxxxxxxxxxxx/videos/cherry-prod/2020/03/01/2dda82de-5b31-11ea-b5ae-1c1b0da2bc3f/hls/480/' header = {"user-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML,like Gecko) Version/5.1.7 Safari/534.57.2"} vediomassag='' TimeStamp = int(datetime.timestamp(datetime.now())) #自定義函式獲取分類 def get_vediocategory(url,headers=header) category = response.text # strrr='"%s"'%category # return strrr return category #獲取分類後的視訊列表 def get_vedioList(url,headers=header) vedioLists = response.text return vedioLists #獲取單個視訊的詳細資訊 def get_vediomassages(url,headers=header) vediomassag = response.text return vediomassag #將下載的m3u8檔案放進建立的ts列表檔案中 def get_m3u8List(m3u8_url,encoding="utf-8") f.write(tsList) f.close print('建立%s檔案成功'%(filename)) return filename # 提取ts列表檔案的內容,逐個拼接ts的url,形成list def get_tsList(filename): ls = [] with open(filename,"r") as file: line = f.readlines() for line in lines: if line.endswith(".ts\n"): ls.append(line[:-1]) return ls # 批量下載ts檔案 def DownloadTs(ls): length = len(ls) root='E:\\mp4' try: if not os.path.exists(root): os.mkdir(root) except: print("資料夾建立失敗") try: for i in range(length): tsname = ls[i][:-3] ts_URL=url+ls[i] print(ts_URL) r = requests.get(ts_URL) with open(root,end='') print("下載完畢") except: print("下載失敗") '''# 整合所有ts檔案,儲存為mp4格式(此處函式複製而來未做實驗,本人直接在根目錄 命令列輸入copy/b*.ts 檔名.mp4,意思是將所有ts檔案合併轉換成自己命名的MP4格式 檔案。) def MergeMp4(): print("開始合併") path = "E://mp4//" outdir = "output" os.chdir(root) if not os.path.exists(outdir): os.mkdir(outdir) os.system("copy /b *.ts new.mp4") os.system("move new.mp4 {}".format(outdir)) print("結束合併")''' if __name__ == '__main__': # 將獲取的分類資訊解碼顯示出來 # print(json.loads(get_vediocategory(url,TimeStamp))) print(get_vediocategory(url,TimeStamp)) tagID = input("請輸入分類對應的id") print(get_vedioList(url,tagID)) vedioID = input("請輸入視訊對應的id") get_vediomassages(url,vedioID) get_m3u8List(m3u8_url,vediomassag) get_tsList(filename) DownloadTs(ls) # MergeMp4()
此時正在下載
三、問題:
首先對於這種網站採取的爬取方法有很多,而我的方法相對來說有點太低端了,並且我也 是第一次寫部落格,第一次寫爬蟲這類程式,在格式上命名上存在著很多問題,函式的用法不全面。並且在執行的時候效率低速度太慢。在獲取分類列表和視訊列表時,因為是JSON檔案,需要轉碼,過程太多加上程式不夠穩定我就註釋掉了。還有就是對於這種動態網頁瞭解不夠,所以學爬蟲的小夥伴一定要把網頁的基礎搞好。希望各位大佬多指正多批評,讓我們這些小白一起努力學好Python。
注意:裡面所有的連結我的給打碼了,怕被和諧了哈哈
到此這篇關於Python爬蟲進階之爬取某視訊並下載的實現的文章就介紹到這了,更多相關Python 爬取某視訊並下載內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!