摸魚微信視頻號視頻 - Fiddler + Python
前言:
前面有個(gè)做視頻剪輯的朋友問我能不能從微信視頻號下載一些視頻來作為他視頻剪輯的素材。這個(gè)問題是肯定的。今天來操作并分享一下。

首先是利用Fiddler進(jìn)行抓包,單個(gè)手動(dòng)下載,步驟如下:

下載Fiddler并安裝好(下載地址:https://www.telerik.com/fiddler),建議從官網(wǎng)下載;
設(shè)置一下Fiddler;
菜單欄 - tools - options - HTTPS - 勾選Decrypt HTTPS traffic和Ignore server certificate errors(unsafe)
右側(cè)窗口,勾選Filters - 設(shè)置Hosts -?Show only the following Hosts -? finder.video.qq.com(下圖中標(biāo)號5和6)
還是filters,設(shè)置Request headers - 勾選Show only If URL contains(下圖標(biāo)號7)

登錄電腦版微信 - 點(diǎn)開視頻號(在微信電腦版的左側(cè)菜單欄)
開始手動(dòng)刷視頻(這里可以先找好自己想要摸魚的視頻或者視頻主);
在Fiddler里查找視頻的地址;將地址放在瀏覽器就可以直接打開,然后在瀏覽器選擇下載就好了;
貼個(gè)視頻配合上面的內(nèi)容:

做到這里,那些只想單個(gè)手動(dòng)下載視頻的同學(xué)你們就可以下課了。

第二是利用Fiddler進(jìn)行抓包,然后多個(gè)自動(dòng)下載

下面開始自動(dòng)下載視頻。如果一時(shí)間我們刷了好幾百或者好幾百視頻,單個(gè)手動(dòng)下載手應(yīng)該會(huì)酸或者會(huì)廢。是時(shí)候考慮用Python摸魚了。還是打開Fiddler和微信電腦版客戶端,刷視頻,刷到自己不想刷為止。然后在Fiddler的sessions面板Ctrl + A全選會(huì)話列表進(jìn)行保存(按下圖中的順序保存):

保存好后的數(shù)據(jù)不建議用記事本打開,因?yàn)?,可能程序?huì)GG,用Notepad或者editplus這種代碼編輯軟件打開比較靠譜。下面是用editplus打開后的截圖:

乍一看數(shù)據(jù)還是有規(guī)律的,規(guī)律在代碼的注釋中有說明。下面是敲代碼思路:
讀取txt文檔里的內(nèi)容;
提取文檔中的視頻播放地址(僅僅是視頻,不要圖片,圖片網(wǎng)址要處理掉,在處理txt文檔的時(shí)候直接舍棄丟棄);
利用提取到的視頻播放地址請求視頻的二進(jìn)制數(shù)據(jù)保存到本地;
上代碼:
# -*- encoding: utf-8 -*-
# @Time: 2022/5/17 8:29
# @Author: 、一葉孤城
# @File: spider.py
# @IDE: PyCharm
# @Motto: ABC(Always Be Coding)
import os.path
import random
import re
import time
import urllib.request
import requests
from atexit import register
import concurrent.futures
def get_response_by_requests(page_url):
? ?"""獲取網(wǎng)頁數(shù)據(jù)的函數(shù)"""
? ?headers = {
? ? ? ?'Cookie':'自己都有自己的cookie',
? ? ? ?# 'Referer':'video.qq.com',
? ? ? ?'Host':'finder.video.qq.com',
? ? ? ?'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
? ?}
? ?response = requests.get(url=page_url, headers=headers)
? ?response.raise_for_status()
? ?response.encoding = response.apparent_encoding
? ?response.encoding = 'utf-8'
? ?return response
def get_response_by_urllib(page_url):
? ?"""獲取網(wǎng)頁數(shù)據(jù)的函數(shù)"""
? ?headers = {
? ? ? ?'Cookie': '各自的cookie',
? ? ? ?# 'Referer':'video.qq.com',
? ? ? ?'Host': 'finder.video.qq.com',
? ? ? ?'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
? ?}
? ?request = urllib.request.Request(url=page_url, headers=headers) # 請求對象
? ?response = urllib.request.urlopen(request) # 用urllib打開上面的這個(gè)請求對象
? ?return response #返回給調(diào)用它的行
def save_video(videoUrl):
? ?"""
? ? ? ?一個(gè)保存視頻的函數(shù)
? ?"""
? ?# 文件保存地址
? ?filePath = './微信視頻/video/'
? ?if not os.path.exists(filePath):
? ? ? ?# os.mkdir(filePath) # 如果是路徑只有一對/,可以用mkdir
? ? ? ?os.makedirs(filePath) # ?如果路徑有兩個(gè)以上的/,就要用makedirs
? ?# 通過電腦端微信刷的視頻是沒有標(biāo)題的,所以需要定義一種標(biāo)題的方式
? ?# 觀察一下視頻的地址,就取它(encfilekey=)后面的12位字符串,且統(tǒng)一保存為mp4格式
? ?videoName = re.findall('encfilekey=(.*?)snsvideoflag', videoUrl)[0][
? ? ? ? ? ? ? ?0:12] ?# 第一個(gè)大括號是取列表里的第一項(xiàng),第二個(gè)大括號是取字符串從開始到11個(gè)字符串的位置,也就是標(biāo)題
? ?print(videoName)
? ?# 調(diào)用get_response_by_requests 請求文件二進(jìn)制數(shù)據(jù)
? ?# videoContent = get_response_by_requests(page_url=videoUrl).content # 獲取不到數(shù)據(jù),要換一種請求方式
? ?# print(videoContent)
? ?# 調(diào)用get_response_by_urllib 請求二進(jìn)制數(shù)據(jù)
? ?videoContent = get_response_by_urllib(page_url=videoUrl).read() # 與requests不一樣,這里只需要read()一下數(shù)據(jù)就ok了
? ?# print(videoContent)
? ?# 嘗試保存
? ?try:
? ? ? ?with open(filePath + videoName + '.mp4', mode='wb') as f:
? ? ? ? ? ?f.write(videoContent)
? ? ? ? ? ?print(f'****【{videoName}】**** 保存成功!')
? ?except:
? ? ? ?print('有異常,請檢查!')
def process_data():
? ?"""
? ?通過fiddler保存了一個(gè)txt的文本文檔,現(xiàn)在來處理這個(gè)文本文檔
? ?處理這個(gè)文檔只有一個(gè)目標(biāo),就是提取出視頻的網(wǎng)址,而不是圖片網(wǎng)址也要。
? ?思路:
? ?# 保存的文檔里有Content-Type,這個(gè)字段的值有image/jpg,video/mp4等,我們利用這個(gè)值來判斷是圖片還是視頻
? ?# 如果Content-Type的值是video/mp4,我們就提取它請求的網(wǎng)址
? ?"""
? ?# 處理Fiddler保存的文本的函數(shù)
? ?qqVideosUrls = [] # 一個(gè)空列表,用以存儲(chǔ)處理數(shù)據(jù)過后的網(wǎng)址
? ?fileName = '4_Headers.txt'
? ?with open(fileName, mode='r', encoding='utf-8', errors='ignore') as f:
? ? ? ?lines = f.readlines() # 一個(gè)列表
? ? ? ?# print(len(lines)) # 總行數(shù)
? ? ? ?lineStr = ''.join(lines)
? ? ? ?# hrCounts = re.findall('------------------------------------------------------------------', lineStr)
? ? ? ?# print(len(hrCounts)) # 279
? ? ? ?# print(lineStr)
? ? ? ?# 再以文檔中的分割線切割成列表
? ? ? ?lineListSplitbyhr = lineStr.split('------------------------------------------------------------------')
? ? ? ?# print(lineListSplitbyhr)
? ? ? ?# print(len(lineListSplitbyhr)) # 280 因?yàn)榉指畹牡谝豁?xiàng)沒有分割線,所有上面的統(tǒng)計(jì)是279,而列表項(xiàng)是280
? ? ? ?# 著手處理以分割線處理的列表,主要是從列表的每一項(xiàng)中確定是不是有video/mp4的字段,如果有,表示是視頻,我們就提取該項(xiàng)的請求地址
? ? ? ?for videorequestinfo in lineListSplitbyhr:
? ? ? ? ? ?# print(videorequestinfo) # 遍歷出來的是字符串,可以通過字符串的處理方式處理,也可以通過正則處理
? ? ? ? ? ?try:
? ? ? ? ? ? ? ?if videorequestinfo.__contains__('Content-Type: video/mp4'): # 如果字符串中包含該值,就執(zhí)行下列代碼
? ? ? ? ? ? ? ? ? ?videoEncUrl = re.findall('GET (.*?) HTTP/1.1', videorequestinfo)[0] # 取出視頻地址
? ? ? ? ? ? ? ? ? ?qqVideosUrls.append(videoEncUrl) # 追加到列表
? ? ? ? ? ? ? ?else:
? ? ? ? ? ? ? ? ? ?pass
? ? ? ? ? ?except:
? ? ? ? ? ? ? ?print(f'可能文本中{fileName}沒有video/mp4,也就是該文本中沒有請求到視頻網(wǎng)址,請手動(dòng)查看!')
? ?# print(qqVideosUrls) # 數(shù)據(jù)正確
? ?# print(len(qqVideosUrls)) # 長度正確
? ?return qqVideosUrls # 返回給調(diào)用它的行
def _main():
? ?# 為了函數(shù)運(yùn)行的順序性,再定義一個(gè)入口函數(shù)
? ?qqVideosUrls = process_data() # 取得所有視頻播放地址
? ?for qqvideourl in qqVideosUrls:
? ? ? ?# 調(diào)用多線程處理函數(shù),據(jù)說是一個(gè)高級線程,但是感覺上跟單線程差不多,可能我用法不精準(zhǔn)
? ? ? ?with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
? ? ? ? ? ?executor.submit(save_video, qqvideourl)
? ? ? ?# # 如果是單線程的話應(yīng)該像下面這樣
? ? ? ?# time.sleep(random.uniform(2, 5)) # 隨機(jī)休眠
? ? ? ?# save_video(videoUrl=qqvideourl)
# 注冊一個(gè)退出函數(shù)
@register
def _atexit():
? ?print('所有任務(wù)完成于:【{}】'.format(time.strftime("%Y-%m-%d %H:%M:%S"), time.localtime(time.time())))
if __name__ == "__main__":
? ?_main()
代碼擼完,這里我采了一個(gè)坑,就是python的requests模塊是獲取不到數(shù)據(jù)的。就是簡單的無響應(yīng),不知道服務(wù)端是怎么判定的。所以得另某他途,最后想到了用另外一個(gè)很古老的模塊兒 - urllib,這個(gè)也可以請求數(shù)據(jù)。發(fā)現(xiàn)最終可以獲取到視頻數(shù)據(jù)。沒有什么技術(shù)含量,其實(shí)就是對文本進(jìn)行處理、對字符串進(jìn)行處理、然后將過濾出來的視頻網(wǎng)址(因?yàn)槲襾G棄了圖片網(wǎng)址)用Python請求。
申明:本文僅用于學(xué)習(xí)與交流使用,不做他途,如有侵權(quán),請聯(lián)系我刪除。謝謝。