主頁 > 後端開發 > Python爬蟲教程:短視頻平臺無水印下載

Python爬蟲教程:短視頻平臺無水印下載

2020-10-20 20:44:59 後端開發

作者: Hu.Sir
CSDN個人主頁: 高智商白癡
原文地址: https://blog.csdn.net/qq_44700693/article/details/108089085

 

日常跳轉:

很多人學習python,不知道從何學起,
很多人學習python,掌握了基本語法過后,不知道在哪里尋找案例上手,
很多已經做案例的人,卻不知道如何去學習更加高深的知識,
那么針對這三類人,我給大家提供一個好的學習平臺,免費領取視頻教程,電子書籍,以及課程的源代碼!??¤
QQ群:623406465

    • 匯入:
      • 分平臺解釋:
        • 皮皮蝦
        • 皮皮搞笑
            • 抓包分析
            • 原始碼及結果
        • 抖音 / 抖音極速版
            • 抓包分析
            • 代碼及結果
            • 小優化:
        • 騰訊微視
            • 抓包及分析
            • 代碼及結果
        • 開眼 Eyepetizer
            • 抓包分析
            • 代碼及結果
        • 快手/快手極速版
          • 單個視頻下載
            • 抓包分析
            • 代碼及結果
          • 用戶視頻下載
            • 抓包分析
            • 代碼及結果
        • 抖音火山版/火山極速版
          • 單個視頻下載
            • 代碼及結果:
          • 用戶視頻下載
            • 抓包分析
            • 代碼及結果:
        • 最右
          • 單個視頻下載
            • 代碼及結果
          • 話題視頻下載
            • 代碼及分析
            • 代碼及結果:
            • 小優化:
        • VUE
          • 單個視頻下載
            • 抓包與分析
            • 代碼及結果
          • 話題視頻下載
            • 代碼及結果:
        • 看看視頻
            • 抓包與分析
            • 代碼及結果
            • 小優化
        • 嗶哩嗶哩
        • AcFun
      • 撰寫中,,,

 

匯入:

雖然目前有些軟體還沒適配,但是,我發了 Blink 后有一寫人留言或者私信找我要原始碼,不過我還在增加適配的軟體,所以還沒有時間寫這篇博客,今天呢,就先把我目前適配了的代碼拿出來,后續還會繼續適配的!

分平臺解釋:

皮皮蝦

皮皮蝦的話,我之前就已經寫過一個單獨的博客了,這里就不再贅述:—> Python爬蟲:皮皮蝦短視頻無水印下載


皮皮搞笑

皮皮搞笑與皮皮蝦很類似,也是先獲取分享鏈接,在電腦端進行分析:
在這里插入圖片描述?

抓包分析

在這里插入圖片描述?
我們可以很容易的在抓包資源 HXR 中找到某一固定的鏈接: https://h5.ippzone.com/ppapi/share/fetch_content ,在該鏈接中的 video 欄位可以看到有兩個鏈接,分別打開嘗試一下可以發現: 后綴含有 wm 的鏈接是含有水印的視頻,另一個則是我們的目標鏈接了,但是我們又發現,在 video 欄位下,還有一個全是數字的字串,我們在當前 json 檔案中搜索可以發現:
在這里插入圖片描述?
在上一個標簽 img 下,有一個 id 欄位,和字串標簽一樣,
知道了視頻鏈接的存放位置和獲取方式,接下來開始分析請求:
在這里插入圖片描述?
在這里插入圖片描述?
在嘗試過幾次抓包后發現,請求 URL 始終都沒有變化,只是下面的 請求負載 有所變化,第三個引數 post 默認不變就好,至于前兩個引數,都在分享鏈接跳轉的鏈接中:

https://h5.ippzone.com/pp/post/350259149175?zy_to=copy_link&share_count=1&m=0cd13da8548a1bc85813d8c60d331e22&app=&type=post&did=d2bddf23159ae495&mid=1270840711117&pid=350259149175

原始碼及結果

一切準備作業做好后,開始撰寫代碼:

class PPGX():  # 皮皮搞笑
    def __init__(self, url):
        s_url = url
        self.headers = {
            'Host': 'share.ippzone.com',
            'Origin': 'http://share.ippzone.com',
            'Referer': s_url,
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52'
        }
        self.JSON = {
            "pid": int(str(s_url).split('=')[-1]),
            "mid": int(str(s_url).split('&')[-2].split('=')[-1]),
            "type": "post"
        }

    def ppgx_download(self):
        URL = 'http://share.ippzone.com/ppapi/share/fetch_content'
        r = requests.post(URL, proxies=proxy, headers=self.headers, json=self.JSON)
        video_name = r.json()['data']['post']['content'].replace(' ','')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        video_url = r.json()['data']['post']['videos'][str(r.json()['data']['post']['imgs'][0]['id'])]['url']
        video = requests.get(video_url, proxies=proxy).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
            f.write(video)
        print("【皮皮搞笑】: {}.mp4 無水印視頻下載完成!".format(video_name))

結果:
在這里插入圖片描述?


抖音 / 抖音極速版

接下來以 抖音 為例(抖音極速版的決議方式和抖音相同):
同樣的思路,拿到分享鏈接到電腦瀏覽器中抓包分析:
在這里插入圖片描述?
拿到如下資訊:
擺攤的第二天……#架子鼓演奏 #架子鼓 #樂器 #聽心 https://v.douyin.com/JMKHkqt/ 復制此鏈接,打開【抖音短視頻】,直接觀看視頻!
所以為了方便,使用正則運算式來提取該內容中的鏈接:
url = re.findall('(https?://[^\s]+)', s_url)[0] # 正則提取字串中的鏈接

抓包分析

在這里插入圖片描述?
我們可以在抓包資源 HXR 中找到某一請求,在該 json 檔案中 play_addr 欄位下可以找到視頻鏈接,用瀏覽器打開:
在這里插入圖片描述?
該鏈接跳轉到了視頻是沒錯,不過直接跳轉到了又水印的鏈接上,這就有點卡住了,
不過,按照皮皮搞笑的鏈接區分來看, wm 是含有水印的視頻的話,

https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f750000bsegsdpphaglno4mqd8g&ratio=720p&line=0

當我們刪掉鏈接中的 wm 欄位后:
在這里插入圖片描述?
沒有加載??????? 而且我們可以發現鏈接根本都還沒有跳轉,
但是: 當我們把設備切換為手機時: 鏈接跳轉到了無水印的視頻鏈接:
在這里插入圖片描述?

代碼及結果

當一切都分析完后,開始撰寫代碼:
注意: 當我們去掉 wm 欄位后,下載視頻時,需要帶上模擬手機端的請求頭!

class DY():  # 抖音
    headers = {  # 模擬手機端
        'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
    }

    def __init__(self, s_url):
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接

    def dy_download(self):
        rel_url = str(requests.get(self.url, proxies=proxy, headers=self.headers).url)
        if 'video' == rel_url.split('/')[4]:
            URL = 'https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=' + rel_url.split('/')[5] + '&dytk='
            r = requests.get(URL, proxies=proxy, headers=self.headers)
            video_url = r.json()['item_list'][0]['video']['play_addr']['url_list'][0].replace('/playwm/', '/play/')
            video_name = r.json()['item_list'][0]['share_info']['share_title'].split('#')[0].split('@')[0].replace(' ','')
            if video_name == '':
                video_name = int(random.random() * 2 * 1000)
            if len(str(video_name)) > 20:
                video_name = video_name[:20]
            video = requests.get(video_url, proxies=proxy, headers=self.headers).content
            with open(path + str(video_name) + '.mp4', 'wb') as f:
                f.write(video)
            print("【抖音短視頻】: {}.mp4 無水印視頻下載完成!".format(video_name))".format(video_name))

結果:由于抖音和抖音極速版的分享內容是一樣的,無法分辨哪個平臺,所以統一輸出,
在這里插入圖片描述?

但是: 我發現抖音沒事就愛搞幺蛾子,有時分享鏈接是上文所示:
有時又是一段原鏈接…所以我,做了一點小小的優化:

小優化:

if 'www.iesdouyin.com' in self.s_url:
    print("【抖音短視頻】: {}.mp4 無水印視頻下載完成!".format(video_name))
if 'v.douyin.com' in self.s_url:
    print("【抖音短視頻/抖音極速版】: {}.mp4 無水印視頻下載完成!".format(video_name))

騰訊微視

套路依舊,獲取分享鏈接:
在這里插入圖片描述?
拿到鏈接:

上不上班無所謂,主要是想蹦迪>>https://h5.weishi.qq.com/weishi/feed/6XSB277Nr1K5nIKb6/wsfeed?wxplay=1&id=6XSB277Nr1K5nIKb6&spid=8813798054214369280&qua=v1_and_weishi_8.0.6_588_312028000_d&chid=100081014&pkg=3670&attach=cp_reserves3_1000370011

抓包及分析

注意: 這里是一個寫爬蟲的常用思路:將設備切換為手機,因為相對于電腦端,手機端的健壯性沒有電腦端好,所以很多東西都可以通過這種方式來抓取,就如這個例子:

未切換:
在這里插入圖片描述?
已切換:
在這里插入圖片描述?

在這里插入圖片描述?
依次檢查請求后發現:鏈接也就擺放在 json 資料中,
那么,接下來直接分析請求:
在這里插入圖片描述?
在這里插入圖片描述?
對于 請求負載 中的引數,我們可以直接在請求鏈接中截取:

https://h5.weishi.qq.com/weishi/feed/6XSB277Nr1K5nIKb6/wsfeed?wxplay=1&id=6XSB277Nr1K5nIKb6&spid=8813798054214369280&qua=v1_and_weishi_8.0.6_588_312028000_d&chid=100081014&pkg=3670&attach=cp_reserves3_1000370011

其他的引數默認就好,而至于請求鏈接,同一個視頻重繪幾次,引數 t 就有多少個值:

https://h5.weishi.qq.com/webapp/json/weishi/WSH5GetPlayPage?t=0.764612279656077&g_tk=
https://h5.weishi.qq.com/webapp/json/weishi/WSH5GetPlayPage?t=0.3168301677339891&g_tk=
https://h5.weishi.qq.com/webapp/json/weishi/WSH5GetPlayPage?t=0.8888910469548954&g_tk=

而且,有時候長度都不一樣,這就把我嚇到了!什么加密?這么復雜!
既然同一個視頻每次重繪都不一樣,是不是跟時間戳有關系???但是這明顯不是啊!
正在我為這個引數發愁時,我也不知道我當時是怎么想的,無聊,隨機修改了引數 t 的幾個數字發現,仍然能夠獲取到視頻!!!!!!!
然后我發現:所有的數全是在 0—1 之間變化,我用Python的 random 產生了一組亂數來看:

import random
print(random.random())

#  結果:
#  0.5890812460827893

我都驚呆了!!就是這種資料啊!我用這個亂數去請求時,結果居然是可行的,這…在這里插入圖片描述?
居然誤打誤撞的給破解了…

代碼及結果

class TXWS():  # 騰訊微視
    headers = {  # 模擬手機端
        'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
    }

    def __init__(self, s_url):
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接
        self.data = https://www.cnblogs.com/sn8888/p/{'datalvl': "all",
            'feedid': str(self.url).split('/')[5],
            'recommendtype': '0',
            '_weishi_mapExt': '{}'
        }

    def txws_download(self):  # 引數 t 為亂數
        url = 'https://h5.weishi.qq.com/webapp/json/weishi/WSH5GetPlayPage?t={}&g_tk='.format(random.random())
        r = requests.post(url, proxies=proxy, headers=self.headers, data=https://www.cnblogs.com/sn8888/p/self.data)
        video_name = r.json()['data']['feeds'][0]['feed_desc'].replace(' ','')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        video_url = r.json()['data']['feeds'][0]['video_url']
        video = requests.get(video_url, proxies=proxy, headers=self.headers).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
            f.write(video)
        print("【騰訊微視】: {}.mp4 無水印視頻下載完成!".format(video_name))

結果:
在這里插入圖片描述?


開眼 Eyepetizer

雖然 開眼 下載的視頻,并沒有水印,但是下載好的視頻只能在軟體內觀看,但是我還是想讓它下載到它該下載的地址:
套路,套路,還是套路:
在這里插入圖片描述?

抓包分析

在這里插入圖片描述?
還是很簡單的,沒什么反爬機制,很容易就會找到了視頻的下載地址,接下來直接分析請求:
在這里插入圖片描述?
請求鏈接中只有幾個數字需要決議,但是我們發現,它就出現在分享鏈接中:

https://www.eyepetizer.net/detail.html?vid=208234&utm_campaign=routine&utm_medium=share&utm_source=others&uid=0&resourceType=video&udid=c65aab71b05749d584eac4ee7944bb6274e17596&vc=6030061&vn=6.3.6&size=1080X2070&deviceModel=9&first_channel=xiaomi&last_channel=xiaomi&system_version_code=27

代碼及結果

class KY_Eyepetizer():  # 開眼
    def __init__(self, url):
        self.vid = str(url).split('=')[1].split('&')[0]
        self.headers = {
            'origin': 'https://www.eyepetizer.net',
            'referer': url,
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.58'
        }

    def ky_download(self):
        url = 'https://baobab.kaiyanapp.com/api/v1/video/{}?f=web'.format(self.vid)
        r = requests.get(url, proxies=proxy, headers=self.headers)
        video_name = r.json()['title'].replace(' ','')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        video_url = r.json()['playUrl']
        video = requests.get(video_url, proxies=proxy, headers=self.headers).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
            f.write(video)
        print("【開眼 Eyepetizer】: {}.mp4 無水印視頻下載完成!".format(video_name))

結果:
在這里插入圖片描述?


快手/快手極速版

單個視頻下載

我們還是以快手為例(快手極速版的決議規則和快手一樣):
依舊按照套路來,不過因為快手的限制,必須登錄才能分享:
在這里插入圖片描述?

抓包分析

按照以前的套路,將鏈接粘貼到瀏覽器,F12 抓包,結果并沒有獲取到任何與當前視頻鏈接相關的資訊,既然不在 json檔案中,難道在網頁原始碼中???去挨個兒查看后,也不是,這該怎么爬取呢??
別忘了我前面提到的方法:更改設備,
當我把設備換成手機端后,json 資料中也還是沒有相關資料,不過!!我在網頁原始碼中找到了我們想要的鏈接:
在這里插入圖片描述?
到這里我們也已經找到了鏈接存放的地址,接下來則是,如何在這么多的字符里將鏈接提取出來呢???
答案是: 使用正則運算式 ,

代碼及結果

class KS():  # 快手
    def __init__(self, s_url):
        self.s_url=s_url.replace('\n','')
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
        }

    def ks_download(self):
        html = requests.get(self.url, headers=self.headers).text
        video_name = re.findall('name":"(.*?)"', html)[0].replace(' ','')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        video_url = re.findall('srcNoMark":"(.*?)"', html)[0]
        video = requests.get(video_url, proxies=proxy, headers=self.headers).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
            f.write(video)
        if '【快手App】' in self.s_url:
            print("【快手】: {}.mp4 無水印視頻下載完成!".format(video_name))
        elif '【快手極速版App】' in self.s_url:
            print("【快手極速版】: {}.mp4 無水印視頻下載完成!".format(video_name))

結果:
在這里插入圖片描述?


用戶視頻下載

同樣的我們拿到用戶首頁的分享地址:

看了這么多快手,還是「貝貝兔很」最好玩了! https://v.kuaishou.com/69cjtE 復制此鏈接,打開【快手】直接觀看!

抓包分析

還是一貫的套路,更改設備,模擬手機向下重繪發現:
在這里插入圖片描述?
在新加載出的 json 檔案中,含有兩個重要資訊:

  • feeds :包含第19條到37條的視頻資訊(不是鏈接,而是一個中亞引數,我后面會提到怎么使用),
  • pcursor :請求某一部分視頻的重要引數

既然包含了第19條到37條的視頻,那么第1到第18條的視頻資訊在哪里呢?
根據前面的教訓,我直接查看了切換到移動設備時的原始碼發現:
在這里插入圖片描述?
這里確實是有18條資料,而且每一個鏈接直接導向了該視頻的首頁,那么決議方式就和單個視頻的下載方式一樣了!
對于這18條資料,我們同樣可以用正則運算式直接提取,但是后面的幾十條資料就需要我們來進行決議了,

我們從新加載的 json 檔案中可以看到,這里面包含了很多資訊,但是卻沒有視頻的鏈接,但是,既然重繪又必須加載它,說明肯定有什么重要的東西:
后來我發現正則運算式提取出的鏈接都有像是之處,所以我拿出了幾個用正則運算式提取出的鏈接,(默認前綴)

/fw/photo/3x3m9e644ep95qg?cc=share_copylink&fid=574031739&shareId=227013708994&shareToken=X8rcLJByeLfC10c_A&appType=21&kpn=KUAISHOU
/fw/photo/3xggwttf4kquza9?cc=share_copylink&fid=574031739&shareId=227013708994&shareToken=X8rcLJByeLfC10c_A&appType=21&kpn=KUAISHOU

我發現對于同一個用戶,所有視頻的基本形式除了黃色部分不一樣以外,其余的都是固定的!這不就是一個引數的問題嘛, json 檔案中那么多的資料,不信找不到:我一一嘗試后終于找到了那個引數:
在這里插入圖片描述?
既然我們已經知道如何拼接每個視頻的鏈接,那么,最主要的就是如何獲取那個視頻的關鍵引數,
我前面已經說了,在 json 檔案中的 pcursor 欄位很是重要!
在這里插入圖片描述?
在這里插入圖片描述?
我嘗試多次后終于發現發現:前一個 post 請求所回傳資料中的 pcursor 欄位的值,就是下一次請求所需要的引數!而兩次請求中,視頻的順序剛好和用戶的一樣,所以如何請求后續的視頻資訊,我們已經知道方法了,不過,第一次的請求的引數是怎么來的呢??
在這里插入圖片描述?
解決: 在撰寫代碼時,我給第一次 post 請求的引數 pcursor 賦了個空值,也是能夠請求成功的!
而請求結束的標志就是:pcursor 欄位的值等于 no_more
在這里插入圖片描述?

代碼及結果

class KS():  # 快手
    def __init__(self, s_url):
        self.s_url=s_url.replace('\n','')
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
        }
        self.video_list = []
        self.rel_url = requests.get(self.url, proxies=proxy, headers=self.headers)  # 真實網址

    def ks_download(self):
        if 'user' != self.rel_url.url.split('/')[4]:
            self.ks_download_video()
        if 'user' == self.rel_url.url.split('/')[4]:
            self.ks_download_user()

    def ks_download_video(self):
        video_name = re.findall('name":"(.*?)"', self.rel_url.text)[0].replace(' ', '')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        video_url = re.findall('srcNoMark":"(.*?)"', self.rel_url.text)[0]
        video = requests.get(video_url, proxies=proxy, headers=self.headers).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
            f.write(video)
        if '【快手App】' in self.s_url:
            print("【快手】: {}.mp4 無水印視頻下載完成!".format(video_name))
        elif '【快手極速版App】' in self.s_url:
            print("【快手極速版】: {}.mp4 無水印視頻下載完成!".format(video_name))

    def ks_download_user(self):
        global user_name
        headers = {
            'Cookie': '粘貼自己的Cookie資訊',
            'Origin': 'https://c.kuaishou.com',
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.125'
        }
        rel_url = requests.get(self.url, proxies=proxy, headers=headers)  # 真實網址
        user_name = re.findall('<div >(.*?)</div>', rel_url.text)[-1]
        if os.path.exists(path + user_name + '/'):
            pass
        else:
            os.makedirs(path + user_name + '/')
        videos = re.findall('<a href="https://www.cnblogs.com/sn8888/p/(.*?)" role="ev" data-lazy=', rel_url.text)
        for video1 in videos:
            self.video_list.append('https://c.kuaishou.com' + video1)
        pcursor = ''
        url = 'https://c.kuaishou.com/rest/kd/feed/profile'
        flag = 1
        while flag:
            data = https://www.cnblogs.com/sn8888/p/{"eid": str(rel_url.url).split('/')[-1].split('?')[0], "count": 18, "pcursor": pcursor}
            r = requests.post(url, proxies=proxy, headers=headers, json=data)
            for video2 in tqdm(r.json()['feeds'], desc='正在準備視頻鏈接: '):
                photoId = video2['share_info'].split('=')[-1]
                temp_last = '?' + self.video_list[0].split('?')[-1]
                self.video_list.append('https://c.kuaishou.com/fw/photo/' + photoId + temp_last)
            pcursor = r.json()['pcursor']
            if r.json()['pcursor'] == "no_more":
                flag = 0
        print('用戶 {} 共 {} 個視頻!'.format(user_name,len(self.video_list)))
        for video_url in self.video_list:
            html = requests.get(video_url, headers={
                'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X)'})  # 真實網址
            print(html.text)
            video_name = int(random.random() * 2 * 1000)
            video_url = re.findall('srcNoMark":"(.*?)"', html.text)[0]
            video = requests.get(video_url, proxies=proxy, headers=headers).content
            with open(path + user_name + '/' + str(video_name) + '.mp4', 'wb') as f:
                f.write(video)
                print("【快手】: {}.mp4 無水印視頻下載完成!".format(video_name))

結果:
在這里插入圖片描述?


抖音火山版/火山極速版

單個視頻下載

對于這兩個軟體的決議,其實我是偷懶了,嘿嘿嘿,我翻看以前別人的博客,細細研究后發現了一個快手視頻決議的介面:
其實很抱歉我忘記了我在哪個地方看到的那片文章,通過那篇文章,我們可以獲取到原火山小視頻的視頻加載api :

https://api-hl.huoshan.com/hotsoon/item/video/_source/?item_id=6859730122820291840 原火山小視頻無水印介面
https://api.huoshan.com/hotsoon/item/video/_reflow/?item_id=6859730122820291840 抖音火山版水印介面
https://api.huoshan.com/hotsoon/item/video/_source/?item_id=6859730122820291840 抖音火山版無水印介面

現在,已經知道視頻加載的 api 后,就只需獲取視頻的 item_id 引數了,這個引數在跳轉鏈接中就可以找到,

代碼及結果:

所以我直接寫出來決議代碼:

class DY_HSB():
    headers = {   # 模擬手機
        'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
    }

    def __init__(self, s_url):
        self.s_url=s_url
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接

    def dyhsb_download(self):
        rel_url = str(requests.get(self.url, proxies=proxy, headers=self.headers).url)
        video_name = int(random.random() * 2 * 1000)
        video_url = 'https://api.huoshan.com/hotsoon/item/video/_source/?item_id=' + \
                     rel_url.split('=')[1].split('&')[0]
        video = requests.get(video_url, proxies=proxy, headers=self.headers).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
             f.write(video)
        if '【抖音火山版】' in self.s_url:
             print("【抖音火山版】: {}.mp4 無水印視頻下載完成!".format(video_name))
        elif '【火山極速版】' in self.s_url:
             print("【火山極速版】: {}.mp4 無水印視頻下載完成!".format(video_name))

結果:因為這個 api 無法獲取其余資訊,所以就以亂數來命名,
在這里插入圖片描述?
在這里插入圖片描述?

用戶視頻下載

我們還是拿到用戶首頁的分享鏈接:

「天使航拍」也在抖音火山版,快來看 TA 的精彩作品吧!「天使航拍」上傳了 173 個視頻作品,一起來圍觀>>https://share.huoshan.com/hotsoon/s/FJ0C7M5rWa8/ 復制此鏈接,打開【抖音火山版】,直接找到TA~

抓包分析

在這里插入圖片描述?
我們可以很快地找到一個用戶視頻的請求介面,然后拿到視頻的 item_id 引數,但是!這個介面好像有引數去限制請求視頻的數量,目前我只是試了一下修改請求引數,不過也只能最多爬取該用戶40—50 個視頻,如果以后有時間,我再去研究一下,
雖然請求引數較多,但是經過我的嘗試,只有兩個引數是必須的:

  • encrypted_id : 在請求跳轉鏈接中以 to_user_id 的引數存在,
  • count :請求數量,(但是最多只能請求40—50個??這是怎么回事,我目前還沒弄清楚!)

https://share.huoshan.com/pages/user/index.html?to_user_id=MS4wLjABAAAA6iUfN2mZ0H4Z7iLtZQ73TYdXoyTUIjk6oDdVWuRtn_g&timestamp=1597806131&share_ht_uid=0&did=67279005018&iid=3113420875114797&utm_medium=huoshan_android&tt_from=copy_link&app=live_stream&utm_source=copy_link&schema_url=sslocal%3A%2F%2Fprofile%3Fid%3D75014355319

在這里插入圖片描述?

代碼及結果:

class DY_HSB():
    headers = {   # 模擬手機
        'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
    }

    def __init__(self, s_url):
        self.s_url=s_url
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接

    def dyhsb_download(self):
        rel_url = str(requests.get(self.url, proxies=proxy, headers=self.headers).url)
        if 'item' == rel_url.split('/')[4]:  # 單個視頻
            video_name = int(random.random() * 2 * 1000)
            video_url = 'https://api.huoshan.com/hotsoon/item/video/_source/?item_id=' + \
                        rel_url.split('=')[1].split('&')[0]
            video = requests.get(video_url, proxies=proxy, headers=self.headers).content
            with open(path + str(video_name) + '.mp4', 'wb') as f:
                f.write(video)
            if '【抖音火山版】' in self.s_url:
                print("【抖音火山版】: {}.mp4 無水印視頻下載完成!".format(video_name))
            elif '【火山極速版】' in self.s_url:
                print("【火山極速版】: {}.mp4 無水印視頻下載完成!".format(video_name))
        if 'user' == rel_url.split('/')[4]:  # 用戶視頻
            ##########
            # 缺陷:最多支持下載 40--50 個該用戶視頻,
            ##########
            to_user_id = rel_url.split('=')[1].split('&')[0]
            info_json = requests.get('https://share.huoshan.com/api/user/info?encrypted_id={}'.format(to_user_id))
            item_count = info_json.json()['data']['item_count']
            user_name = info_json.json()['data']['nickname']
            if os.path.exists(path + user_name + '/'):
                pass
            else:
                os.makedirs(path + user_name + '/')
            videos_url = 'https://share.huoshan.com/api/user/video?encrypted_id={}&count={}'.format(to_user_id,
                                                                                                    item_count)
            video_info = requests.get(videos_url, proxies=proxy, headers=self.headers).json()['data']
            for info in tqdm(video_info, desc='正在下載用戶 {} 的視頻:'.format(user_name)):
                video_name = int(random.random() * 2 * 1000)
                video_url = 'https://api.huoshan.com/hotsoon/item/video/_source/?item_id=' + info['item_id']
                video = requests.get(video_url, proxies=proxy, headers=self.headers).content
                with open(path + user_name + '/' + str(video_name) + '.mp4', 'wb') as f:
                    f.write(video)
            if '【抖音火山版】' in self.s_url:
                print("【抖音火山版】: 用戶 {} 的無水印視頻下載完成!".format(user_name))
            elif '【火山極速版】' in self.s_url:
                print("【火山極速版】: 用戶 {} 的無水印視頻下載完成!".format(user_name))

結果:
在這里插入圖片描述?
在這里插入圖片描述?


最右

依舊是通過拿到分享鏈接,然后抓包分析:
在這里插入圖片描述?
拿到分享鏈接:

#最右#分享一條有趣的內容給你,不好看算我輸,請戳鏈接>> https://share.izuiyou.com/hybrid/share/post?pid=191652885&zy_to=applink&share_count=1&m=ce86942098b72ec745e740e69ab9f6ec&d=fd238824d489ba3c1d65dfb74793074fd42ce27cafa76630b9eecfd7d657f50c&app=zuiyou&recommend=top_ctr&name=use_push_only&title_type=post

單個視頻下載

基本思路也還是不變,更改設備后查看原始碼,將部分原始碼提取出來:
在這里插入圖片描述?

在這里插入圖片描述?
將這部分原始碼拿到 JSON在線決議的網站上去:
在這里插入圖片描述?
雖然提示有錯誤,不過我們可以編輯一下原始碼,改正這個錯誤:
先搜索錯誤的資訊:
在這里插入圖片描述?
然后修改:
在這里插入圖片描述?
因為這個引數不影響我們的爬取,所以,無論改成什么字符都可以,切記一定要雙引號!

隨后,經過我的一番查找,終于找到了視頻的無水印鏈接:
在這里插入圖片描述?
由于這并不是標準的 json 資料,所以,我們還是直接用正則運算式來提取,

代碼及結果

class ZY():  # 最右
    headers = {  # 模擬成手機
        'Host': 'share.izuiyou.com',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
    }

    def __init__(self, s_url):
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接

    def zy_download(self):
        url_flag = str(self.url).split('/')[3]
        html = requests.get(self.url, proxies=proxy, headers=self.headers).text
        flag = re.findall('"imgs":\[{"id":(.*?),"h":', html)[0]
        video_name = re.findall('{"id":.*?,"share":.*?,"content":"(.*?)","title":"', html)[0].replace(' ','')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        video_url = re.findall(',"thumb":' + flag + ',"playcnt":.*?"url":"(.*?)","prior', html)[0] \
            .replace('u002F', '').replace('\\', '/')
        video = requests.get(video_url, proxies=proxy).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
            f.write(video)
        print("【最右】: {}.mp4 無水印視頻下載完成!".format(video_name))

結果:
在這里插入圖片描述?

話題視頻下載

同樣的,我們拿到某一話題的鏈接:

#最右#發現一個超給力的話題,快來圍觀!請戳鏈接>> https://share.izuiyou.com/topic/429972?m=ce86942098b72ec745e740e69ab9f6ec&d=fd238824d489ba3c1d65dfb74793074fd42ce27cafa76630b9eecfd7d657f50c&app=zuiyou

代碼及分析

對于這一話題,我們在電腦抓包 XHR 選項中可以看到有一個 list 欄位,里面就是關于該話題的視頻資訊:
在這里插入圖片描述?

備注: 因為此次都是用電腦瀏覽器抓的包,并沒有去分析手機端的 APP 請求方式,所以對于話題下載,只能下載前 10個視頻,后續有機會或者有需求的話,我會再抓包分析!
對與請求鏈接:https://share.izuiyou.com/api/topic/details ,并沒有發生什么變化,但是傳參就有點復雜了:
在這里插入圖片描述?
不過在我幾次篩選之后發現有用的引數并不復雜:

  • app: 默認 “zuiyou” 就好!
  • d、m、tid: 雖然不知道這個引數是干嘛的,不過我們可以在主頁鏈接中找到,注意: 引數 tid 是 int 型別的引數,
  • ua: 這個就很明顯了啊,就是請求的 User-Agent

于是我們就可以構建一下請求負載:
這里需要注意的是:請求負載是 JSON 型別的資料,而不是最常見的 DATA :
在這里插入圖片描述?

JSON = {
        'app': "zuiyou",
        'd': str(self.url).split('=')[2].split('&')[0],
        'm': str(self.url).split('=')[1].split('&')[0],
        'tid': int(str(self.url).split('/')[4].split('?')[0]),
        'ua': "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.125"
         }

同樣的我們發現,在 video 欄位下,還有一個全是數字的字串:
在這里插入圖片描述?
我們在當前 json 檔案中搜索可以發現,在 img 欄位的資訊里有一串一模一樣的欄位:
在這里插入圖片描述?

代碼及結果:

知道了視頻鏈接保存的地方與請求方式,下面開始撰寫代碼:

class ZY():  # 最右
    headers = {  # 模擬成手機
        'Host': 'share.izuiyou.com',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.105'
    }

    def __init__(self, s_url):
        self.url = re.findall('(https?://[^\s]+)', s_url)[0]  # 正則提取字串中的鏈接

    def zy_download(self):
        url_flag = str(self.url).split('/')[3]
        if 'hybrid' == url_flag:
            html = requests.get(self.url, proxies=proxy, headers=self.headers).text
            flag = re.findall('"imgs":\[{"id":(.*?),"h":', html)[0]
            video_name = re.findall('{"id":.*?,"share":.*?,"content":"(.*?)","title":"', html)[0].replace(' ','')
            if video_name == '':
                video_name = int(random.random() * 2 * 1000)
            if len(str(video_name)) > 20:
                video_name = video_name[:20]
            video_url = re.findall(',"thumb":' + flag + ',"playcnt":.*?"url":"(.*?)","prior', html)[0] \
                .replace('u002F', '').replace('\\', '/')
            video = requests.get(video_url, proxies=proxy).content
            with open(path + str(video_name) + '.mp4', 'wb') as f:
                f.write(video)
            print("【最右】: {}.mp4 無水印視頻下載完成!".format(video_name))
        if 'topic' == url_flag:
            ###########
            #  缺陷:話題區最多下載 10 個視頻
            ###########
            JSON = {
                'app': "zuiyou",
                'd': str(self.url).split('=')[2].split('&')[0],
                'm': str(self.url).split('=')[1].split('&')[0],
                'tid': int(str(self.url).split('/')[4].split('?')[0]),
                'ua': "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.125"
            }
            URL = 'https://share.izuiyou.com/api/topic/details'
            r = requests.post(URL, json=JSON, proxies=proxy, headers=self.headers)
            video_info = r.json()['data']['list']
            type_name = r.json()['data']['topic']['topic'].replace(' ','')
            if os.path.exists(path + type_name + '/'):
                pass
            else:
                os.makedirs(path + type_name + '/')
            for video_info in tqdm(video_info, desc='正在下載型別 【{}】 的視頻: '.format(type_name)):
                video_name = video_info['content'].replace(' ','')
                if video_name == '':
                    video_name = int(random.random() * 2 * 1000)
                if len(str(video_name)) > 20:
                    video_name = video_name[:20]
                flag = video_info['imgs'][0]['id']
                video_url = video_info['videos'][str(flag)]['url']
                video = requests.get(video_url, proxies=proxy).content
                with open(path + type_name + '/' + str(video_name) + '.mp4', 'wb') as f:
                    f.write(video)
            print("【最右】: 型別 【{}】 無水印視頻下載完成!".format(type_name))

小優化:

  • 1、因為后來我發現在話題區可能有圖片的動態,不是視頻的話,可能會出錯,所以我對可能會出錯的地方進行了處理
  • 2、當我在測驗的程序中發現,有些視頻的神評中也含有視頻,所以我準備再加一點點代碼,把那些也都下載下來:

先找到審評的保存地方:
在這里插入圖片描述?
對于神評中的視頻,規則和單個視頻很相似:在 video 欄位下,還有一個全是數字的字串:
在這里插入圖片描述?
在當前 json 檔案中搜索可以發現,在 img 欄位的資訊里有一串一模一樣的欄位:
在這里插入圖片描述?
然而,也有可能在神評中沒有視頻或者沒有神評,所以這一次直接把可能出現問題的地方處理掉:

#
#  上面不做修改
#

if 'topic' == url_flag:
    ###########
    #  缺陷:話題區最多下載 10 個視頻
    ###########
    JSON = {
        'app': "zuiyou",
        'd': str(self.url).split('=')[2].split('&')[0],
        'm': str(self.url).split('=')[1].split('&')[0],
        'tid': int(str(self.url).split('/')[4].split('?')[0]),
        'ua': "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/84.0.4147.125"
    }
    URL = 'https://share.izuiyou.com/api/topic/details'
    r = requests.post(URL, json=JSON, proxies=proxy, headers=self.headers)
    video_info = r.json()['data']['list']
    type_name = r.json()['data']['topic']['topic'].replace(' ','')
    if os.path.exists(path + type_name + '/'):
        pass
    else:
        os.makedirs(path + type_name + '/')
    for video_info in tqdm(video_info, desc='正在下載型別 【{}】 的視頻: '.format(type_name)):
        video_name = video_info['content'].replace(' ','')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        flag = video_info['imgs'][0]['id']
        try:
            video_url = video_info['videos'][str(flag)]['url']
            video = requests.get(video_url, proxies=proxy).content
            with open(path + type_name + '/' + str(video_name) + '.mp4', 'wb') as f:
                f.write(video)
        except:
            pass
        try:
            video_info1=video_info['god_reviews'][0]['videos']
            for a in tqdm(range(len(video_info1)),desc="正在下載該視頻下的評論視頻:"):
                flag1=video_info['god_reviews'][0]['imgs'][a]['id']
                video_url1=video_info['god_reviews'][0]['videos'][str(flag1)]['url']
                video_name = int(random.random() * 2 * 1000)
                video = requests.get(video_url1, proxies=proxy).content
                with open(path + type_name + '/' + str(video_name) + '.mp4', 'wb') as f:
                    f.write(video)
        except:
            pass
    print("【最右】: 型別 【{}】 無水印視頻下載完成!".format(type_name))

結果:
在這里插入圖片描述?

VUE

單個視頻下載

vue平臺雖然視頻本身沒有頻臺水印,但是卻沒有給我們提供下載功能,所以我才會撰寫這段代碼:
同樣拿到某一個視頻的分享鏈接:
在這里插入圖片描述?
拿到的分享鏈接:

https://v.vuevideo.net/share/post/-5263687500195767823

抓包與分析

在這里插入圖片描述?
在電腦端打開分享網站后,又檢查工具查看,我們所需要的東西都可以很輕松的找到,于是:

代碼及結果

class VUE():  # VUEvlog
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59'
    }

    def __init__(self, url):
        self.url = url

    def vue_download(self):
        rel = requests.get(self.url, proxies=proxy, headers=self.headers)
        video_name = parsel.Selector(rel.text).xpath('//div[@]/text()').extract()[0].replace(' ',
                                                                                                               '')
        if video_name == '':
            video_name = int(random.random() * 2 * 1000)
        if len(str(video_name)) > 20:
            video_name = video_name[:20]
        video_url = parsel.Selector(rel.text).xpath('//div[@]/video/@src').extract()[0]
        video = requests.get(video_url, proxies=proxy).content
        with open(path + str(video_name) + '.mp4', 'wb') as f:
            f.write(video)
        print("【VUE】: {}.mp4 視頻下載完成!".format(video_name))

結果:
在這里插入圖片描述?

話題視頻下載

對于話題區,我們也還是拿到分享鏈接:
在這里插入圖片描述?

https://v.vuevideo.net/share/topics/193

######## 抓包與分析
在這里插入圖片描述?

代碼及結果:

按照單個視頻下載的方式,同樣的能夠獲得我們所需要的所有資訊,每一個 <li>…</li> 標簽都包裹著每一個視頻的資訊,所以:

class VUE():  # VUEvlog
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59'
    }

    def __init__(self, url):
        self.url = url

    def vue_download(self):
        rel = requests.get(self.url, proxies=proxy, headers=self.headers)
        if str(rel.url).split('/')[4] == 'post':  # 單個視頻
            video_name = parsel.Selector(rel.text).xpath('//div[@]/text()').extract()[0].replace(' ',
                                                                                                                   '')
            if video_name == '':
                video_name = int(random.random() * 2 * 1000)
            if len(str(video_name)) > 20:
                video_name = video_name[:20]
            video_url = parsel.Selector(rel.text).xpath('//div[@]/video/@src').extract()[0]
            video = requests.get(video_url, proxies=proxy).content
            with open(path + str(video_name) + '.mp4', 'wb') as f:
                f.write(video)
            print("【VUE】: {}.mp4 視頻下載完成!".format(video_name))
        if str(rel.url).split('/')[4] == 'topics':  # 主題視頻
            all_li = parsel.Selector(rel.text).xpath('//div[@]').extract()
            topics_name = re.findall('><span>(.*?)</span><', rel.text)[0].replace(' ', '')
            for li_info in tqdm(all_li, desc="正在下載型別為 {} 的視頻:".format(topics_name)):
                video_name = re.findall('="post-title-text">(.*?)</span></div', li_info)[0].replace(' ', '').replace(
                    ':', '')
                if video_name == '':
                    video_name = int(random.random() * 2 * 1000)
                if len(str(video_name)) > 20:
                    video_name = video_name[:20]
                video_url = re.findall('src="https://www.cnblogs.com/sn8888/p/(.*?)"', li_info)[1].replace(' ', '')
                if os.path.exists(path + topics_name + '/'):
                    pass
                else:
                    os.makedirs(path + topics_name + '/')
                video = requests.get(video_url, proxies=proxy).content
                with open(path + topics_name + '/' + str(video_name) + '.mp4', 'wb') as f:
                    f.write(video)
            print("【VUE】: 型別 【{}】 無水印視頻下載完成!".format(topics_name))

結果:

在這里插入圖片描述?

看看視頻

看看視頻,是將一部電視劇的主要情節剪輯下來,讓你在上廁所的時候追完一部劇,
按照我們以前的套路,我們肯定要先拿到視頻的分享鏈接,不過,看看視頻并沒有給我們提供這樣的功能,但是,我們直接分享到QQ時發現,這就是一個分享鏈接:

https://micro.kankan.com/index?productId=207063&setId=220133&productName=隱秘的角落&userId=-1&userid=-1&moviesId=207063

抓包與分析

將鏈接放到瀏覽器抓包可以很快的找到視頻資訊的保存地址:
在這里插入圖片描述?
同樣的我們能夠得到全部和單個視頻的請求介面,

代碼及結果

我們對結果進行梳理后,開始撰寫代碼:

class KKSP():  # 看看視頻
    def __init__(self, s_url):
        self.moviesId = str(s_url).split('=')[-1]
        print(self.moviesId)
        self.headers = {
            'Host': 'svideo-api.kankan.com',
            'Origin': 'https://micro.kankan.com',
            'Referer': s_url,
            'terminal': 'H5',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.44',
            'userid': '-1'
        }

    def kksp_download(self):
        global video_url, video_name
        url = 'https://svideo-api.kankan.com/microvision/getSetListByMoviesId?moviesId=' + self.moviesId
        print(url)
        r = requests.get(url, proxies=proxy, headers=self.headers)
        video_infos = r.json()['data']['moviesSetList']
        name = r.json()['data']['moviesName']
        print(name)

但是當我運行以上代碼時發現在 ’Referer’: s_url 的地方出現了錯誤,時編碼的問題:

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 73-77: ordinal not in range(256)
大致翻譯為:
UnicodeEncodeError:“ latin-1”編解碼器無法對位置73-77中的字符進行編碼:序數不在范圍內(256)
原因是鏈接中含有中文,

小優化

class KKSP():  # 看看視頻
    def __init__(self, s_url):
        self.moviesId = str(s_url).split('=')[-1]
        self.headers = {
            'Host': 'svideo-api.kankan.com',
            'Origin': 'https://micro.kankan.com',
            'Referer': quote(s_url),
            'terminal': 'H5',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.44',
            'userid': '-1'
        }

    def kksp_download(self):
        global video_url, video_name
        url = 'https://svideo-api.kankan.com/microvision/getSetListByMoviesId?moviesId=' + self.moviesId
        print(url)
        r = requests.get(url, proxies=proxy, headers=self.headers)
        video_infos = r.json()['data']['moviesSetList']
        name = r.json()['data']['moviesName']
        if os.path.exists(path + name):
            pass
        else:
            os.makedirs(path + name)
        video_num = 0
        for video_info in tqdm(video_infos, desc="正在下載 {}: ".format(name)):
            video_num += 1
            video_name = '第{}集 '.format(video_num) + video_info['des']
            if video_name == '':
                video_name = int(random.random() * 2 * 1000)
            if len(str(video_name)) > 20:
                video_name = video_name[:20]
            video_url = video_info['moviesSetScreenList'][0]['vodurl']
            video = requests.get(video_url, proxies=proxy).content
            with open(path + name + '/' + str(video_name) + '.mp4', 'wb') as f:
                f.write(video)
        print("【看看視頻】: {}.mp4 視頻下載完成!".format(name))

結果:

在這里插入圖片描述?

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/182733.html

標籤:Python

上一篇:Python獲取各大地圖平臺經緯度資料,哪家的資料最準確?

下一篇:Python爬蟲:爬取ts視頻檔案并合成為mp4格式

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more