下面講一下怎么爬取視頻,這個還是比小白的稍微有一點繞的
首先打開網址:aHR0cDovL3d3dy5wZWFydmlkZW8uY29tL3BvcHVsYXJfNA==
首頁
看一下:
有一個標題和一個href,href只是一個片段,待會肯定要拼接,
先找一下這個頁面有沒有視頻鏈接,很明顯找不著
視頻頁
進入視頻頁
打開元素檢查看一下,也是找不到下載視頻鏈接的,所以肯定是一個動態加載的,我們可以打開檢查,打開視頻,觀察一下,、
打開視頻后,這個鏈接元素才被加載出來
試了一下可以正常訪問的
找元素
但是,我們分析一下這個鏈接,
這個部分
cont-1798951-16047499-hd.mp4
這個第一個數,就是我們在首頁元素頁找的視頻碼,
但是第二個數呢?
我找了半天沒在元素中找到,
剛開始我以為它跟視頻封面圖用的一個鏈接
我以為用的這個
但是拼接了之后訪問的不對
那沒辦法了,元素中找不到就找網絡包
可以看到這個包下的這個響應返回很像一個正常的url
那就試一下唄,
可以發現。。。。是不行的
那么這個url一定是假的
我們對比一下真的url與假的url
對比一下,發現只有cont和第一個參數不一樣,那么只要把這個響應獲取到之后構造為第一個參數就行了
獲取請求參數
這個請求的參數有兩個,第一個就是首頁獲取的id,第二個的話,可以刷新一下其他視頻的接口,看下區別
它竟然不一樣!!!
那。。。。總不會是加密生成的參數吧,我看也不像,這時候不妨隨便改一下這個參數,看看能不能正常返回值
幸運的是,沒有問題
但是這里請求的時候要注意,要加上原來的網址名稱,加到headers里
接口請求code
import requestsheaders = {"Referer": "https://www.pearvideo.com/video_1798952","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
}
url = "https://www.pearvideo.com/videoStatus.jsp?contId=1798952&mrd=0.221312412434"
response = requests.get(url, headers=headers)print(response.text)
print(response)
那響應也拿到了,整個邏輯就非常清晰了
首頁找到id和文章title -> 使用id拼接訪問視頻詳情頁 -> 詳情頁請求接口獲取參數 -> 參數拼接請求
那全部代碼
首頁代碼和面一樣,脫敏處理了一下
import os
import requests
from lxml import etree
import reurl = "aHR0cDovL3d3dy5wZWFydmlkZW8uY29tL3BvcHVsYXJfNA=="
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.79","Referer": "http://www.pearvideo.com/popular_4"
}
def get_response(url,i):headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.79","Referer": f"http://www.pearvideo.com/video_{i}"}res_tail = requests.get(url, headers=headers)return res_tail
def get_name(url):res = requests.get(url)html = etree.HTML(res.text)name = html.xpath('//*[@class="video-tt"]/text()')return name
if __name__ == '__main__':# 獲取頁面內容res = requests.get(url, headers=headers)html = etree.HTML(res.text)hrefs = html.xpath('//*[@class="actplay"]/@href')for i in hrefs:i = i.split('_')[1]url=f"http://www.pearvideo.com/videoStatus.jsp?contId={i}&mrd=0.3239946009256476"res_tail=get_response(url,i)json_data = res_tail.json()video_url = json_data['videoInfo']['videos']['srcUrl']url_list = video_url.replace(video_url.split("/")[6].split("-")[0],"cont-"+i)print(url_list)#下載視頻video_res = requests.get(url_list, headers=headers)if video_res.status_code == 200:# 保存視頻name_url=f"http://www.pearvideo.com/video_{i}"print(name_url)video_name = str(get_name(name_url))with open(video_name, 'wb') as f:f.write(video_res.content)print(f"視頻 {video_name} 下載完成")else:print(f"下載失敗,狀態碼: {video_res.status_code}")
那這就沒問題了
但是這樣只能下載10個視頻,因為視頻翻是動態加載的,我們可以看一下它的網絡請求包
這是4頁的請求接口,試了一會,發現是start的值是視頻從第幾個開始,sort現在還不太明白是什么意思
知道的可以說一下
那其他就沒什么問題了
上代碼
import os
import requests
from lxml import etree
import redef get_response(url,i):headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.79","Referer": f"http://www.pearvideo.com/video_{i}"}res_tail = requests.get(url, headers=headers)return res_tail
def get_name(url):res = requests.get(url)html = etree.HTML(res.text)name = html.xpath('//*[@class="video-tt"]/text()')return name
if __name__ == '__main__':# 獲取頁面內容for page in range(0, 2):url = ZiJodHRwOi8vd3d3LnBlYXJ2aWRlby5jb20vcG9wdWxhcl9sb2FkaW5nLmpzcD9yZXFUeXBlPTQxJmNhdGVnb3J5bGQ9JnN0YXJ0PXtwYWdlKjEwfSZzb3J0PXtwYWdlKjEwfSZtcmQ9MC42Nzc4MjgyNDUwMTk5MDYires = requests.get(url)html = etree.HTML(res.text)hrefs = html.xpath('//*[@class="actplay"]/@href')for i in hrefs:i = i.split('_')[1]url=f"http://www.pearvideo.com/videoStatus.jsp?contId={i}&mrd=0.3239946009256476"res_tail=get_response(url,i)json_data = res_tail.json()video_url = json_data['videoInfo']['videos']['srcUrl']url_list = video_url.replace(video_url.split("/")[6].split("-")[0],"cont-"+i)print(url_list)#下載視頻video_res = requests.get(url_list)if video_res.status_code == 200:# 保存視頻name_url=f"http://www.pearvideo.com/video_{i}"print(name_url)video_name = str(get_name(name_url))+'.mp4'with open(video_name, 'wb') as f:f.write(video_res.content)print(f"視頻 {video_name} 下載完成")else:print(f"下載失敗,狀態碼: {video_res.status_code}")
脫敏處理,有加密的url base64解密一下就可以