前言
講一下,文明爬蟲,從我做起(1.文章中的程序代碼僅供學習,切莫用於商業活動,一經被相關人員發現,本小編概不負責!2.請在服務器閑時運行本程序代碼,以免對服務器造成很大的負擔.)

1. 實現原理
小編這里講的視頻都是快手上的長視頻哈!鏈接為:快手長視頻
我們隨便點擊其中的一個視頻進入,按電腦鍵盤的F12鍵來到開發者模式,在開發者模式下按ctrl+F,輸入:<video,可以找到這個視頻的下載鏈接如下:


我們直接運用selenium這個模塊,直接對這個頁面解析簡簡單單就可以獲取這個視頻的下載鏈接了。
但是沒有這么簡單的哈!快手在這方面還是做的不錯的,為了防止機器人,快手做了一個滑動窗口,如下:

代碼如下:
from selenium import webdriver
driver=webdriver.Chrome()
driver.get(url='https://www.kuaishou.com/video/3xwpkmq75cf2shu?authorId=3x7tp82qssqyteu&tabId=0&area=recommendxxrecommend')
driver.implicitly_wait(5)
downloadUrl=driver.find_element_by_xpath("//video[@class='player-video']").get_attribute("src")
print(downloadUrl)
雖然我們可以通過添加一個while循環實現找到這個視頻的下載鏈接哈!

但這是不是顯得很繁瑣呀!
后來想了一下,這個視頻的下載鏈接可能是使用ajax請求從后台獲取的,你還別說,還真的是這樣的。

查看一下這個請求,發現是post的,請求參數如下:

經過多個視頻的比較,發現只有variables下的字段不同,並且發現如下:

當然,有的視頻鏈接他是沒有area,相對應它的請求參數webPageArea也沒有。我們可以通過使用正則表達式將上述兩個參數值獲取到,但是用代碼發起請求時,發現雖然請求狀態碼為200,但是請求得到的數據卻沒有我們想要的視頻下載鏈接。

cookie字段信息如下:

經過多個視頻比較,這個cookie字段可以是固定的(除了did這個字段的值是隨機生成的之外【隨機生成的直接用固定即可】,其他都是固定的)。
2. 程序代碼
代碼如下:
import requests
from crawlers.userAgent import useragent
import json
import re
videoUrl=input("請輸入視頻的鏈接:")
# https://www.kuaishou.com/video/3xbszt6yravw739?authorId=3x45xripnn3tq5a&tabId=1&area=recommendxxfilm
photoId=re.findall(r"https://www.kuaishou.com/video/(.*)\?.*",videoUrl)[0]
try:
webPageArea=re.findall(r".*area=(.*)",videoUrl)[0]
except Exception as e:
print(e)
webPageArea=''
useragent = useragent()
url = 'https://www.kuaishou.com/graphql'
print(photoId,webPageArea)
headers = {
"user-agent": useragent.getUserAgent(), # 模擬瀏覽器訪問
"content-type": "application/json", # 請求的參數類型為json數據
"Cookie": "kpf=PC_WEB; kpn=KUAISHOU_VISION; clientid=3; did=web_4a95d5c2e09f889043edeffcb9fdb89d; didv=1635052275840",
}
data =json.dumps({"operationName": "visionVideoDetail",
"variables": {"photoId": "%s"%(photoId), "page": "detail", "webPageArea": "{}".format(webPageArea)},
"query": "query visionVideoDetail($photoId: String, $type: String, $page: String, $webPageArea: String) {\n "
"visionVideoDetail(photoId: $photoId, type: $type, page: $page, webPageArea: $webPageArea) {\n "
"status\n type\n author {\n id\n name\n following\n headerUrl\n "
"__typename\n }\n photo {\n id\n duration\n caption\n likeCount\n "
"realLikeCount\n coverUrl\n photoUrl\n liked\n timestamp\n expTag\n "
"llsid\n viewCount\n videoRatio\n stereoType\n croppedPhotoUrl\n manifest {"
"\n mediaType\n businessType\n version\n adaptationSet {\n id\n "
" duration\n representation {\n id\n defaultSelect\n "
" backupUrl\n codecs\n url\n height\n width\n "
" avgBitrate\n maxBitrate\n m3u8Slice\n qualityType\n "
"qualityLabel\n frameRate\n featureP2sp\n hidden\n "
"disableAdaptive\n __typename\n }\n __typename\n }\n "
"__typename\n }\n __typename\n }\n tags {\n type\n name\n "
"__typename\n }\n commentLimit {\n canAddComment\n __typename\n }\n llsid\n "
"danmakuSwitch\n __typename\n }\n}\n"}) # 請求的data數據,json類型
rsp=requests.post(url=url, headers=headers, data=data)
print('響應的狀態碼為:',rsp.status_code)
infos=json.loads(rsp.text)
info=infos['data']['visionVideoDetail']['photo']
videoName=info['caption']
for str_i in ['?','、','╲','/','*','“','”','<','>','|']:
videoName=videoName.replace(str_i,'') # 文件重命名
print('視頻的標題:',videoName)
downloadUrl=info['photoUrl']
print('視頻的下載鏈接為:',downloadUrl)
headers={'user-agent':useragent.getUserAgent()}
rsp2=requests.get(url=downloadUrl,headers=headers)
with open(file="{}.mp4".format(videoName),mode="wb") as f:
f.write(rsp2.content)
