用Python自动化下载多集QQ视频

1. 背景

因为不希望儿子太多使用平板并联网看视频,所以都是把视频下载到盒子中并用一个十几年的康佳小电视看,话说回来,康佳电视品质不错。如果有类似需要,比如说希望把QQ视频下载到存储卡里离线看,可参考本文。

本文使用Python等一系列工具,感觉非程序员勿入。如果你是有QQ视频会员的程序员,希望对你有参考意义。说视频会员还有一个好处,选集切换时没有广告干扰,画质也可以选择高清。

2. 下载视频的基本原理(M3U8)

QQ视频网站使用M3U8 格式传输流媒体。M3U8是 Unicode 版本的 M3U,用 UTF-8 编码。M3U有一个长长的名字,MP3 URL or Moving Picture Experts Group Audio Layer 3 Uniform Resource Locator。简单地说,这是一种类似于播放列表的文件格式,只不过,像QQ视频这些地方会把视频拆成大约10秒一部分的一个.ts文件。打个比方,看了一个一分钟的视频,可能对应一个M3U,其中包括了第一个片段到第六个片段的URL信息。这些流媒体片段会在你在网页版QQ视频观看过程中自动下载并有序播放,当然你感觉不到多个片段之间的跳变。所以想要下载完整视频,也就是说要根据M3U8中的列表信息,下载这些片段,并自动将其合并成单个视频文件。

3.手工下载的做法

手工下载我之前就在用,也因此还经常要坐在电脑前一集一集手工下载。QQ视频不能直接下载,需要借助一些工具,比如说专门的M3U8下载器。对照过一些,不是每个都那么好用或者说能下载到质量符合期望的视频。如果想尝试手工下载,建议阅读本节和相关的内容。如果想直接尝试自动的,建议跳过本节。

我们需要一个M3U8的下载器。下载器不仅下载这些流媒体片段,也包括把这些片段合并起来。既然要下载,就要有下载的URL。使用下面的JS代码,就可以“挖”出一个页面中的视频URL。简单地说,页面中有一个名为PLAYER的JS对象,其中暴露了当前视频的URL,当然也可以用于获取当前选集的名称等。

javascript:var a=prompt(PLAYER._DownloadMonitor.context.dataset.title,PLAYER._DownloadMonitor.context.dataset.ckc?PLAYER._DownloadMonitor.context.dataset.currentVideoUrl:PLAYER._DownloadMonitor.context.dataset.currentVideoUrl.replace(/:.*qq.com/g,"://defaultts.tc.qq.com/defaultts.tc.qq.com"));

以动画片 舒克贝塔第一季 第01集 舒克为例,页面链接如下:

01_舒克贝塔第一季_1080P在线观看平台_腾讯视频

其中的视频URL则是下面这个。M3U8下载工具就是需要这个URL。

https://defaultts.tc.qq.com/defaultts.tc.qq.com/AKN1YRgZqO53AVS38t9P2KGlizFAV17d__SoanbV_uFc/uwMROfz2r5xgoaQXGdGnC2df64gVTKzl5C_X6A3JOVT0QIb-/_imPHrjJpsBsZ6YIV35kAY8FQpmcS5kYLswcH6AGxxBXXOcVPQ8bwgc7SZf8Xt1qJTKGZENJuayuY3gt7xTa5C3zGADpP1mckFZVCBqQwItemfBm4L17wV_zoUkPeuPDdqjZlpsAoHeT15q0EesRXSlYh6j78xNJ2pkiptc60wc/v0032sn0o61.321004.ts.m3u8?ver=4

确实想要尝试的话,下面引用其它网友提到的手动获取QQ视频下载URL的说明,并附上M3U8下载工具的链接(链接未亲测),可供参考。

腾讯视频M3U8获取下载MP4 - 玩友资源网​www.wyp88.com

https://www.wyp88.com/post/2129

m3u8下载工具.zip - 蓝奏云​www.lanzoux.com

https://www.lanzoux.com/i1Y2de4r7uh

4.自动下载的做法

4.1自动下载的原理和工具集

要自动下载,需要Python脚本来实现自动化的编程。同时也需要一些Python第三方库,甚至需要其它一些工具软件(组件)。

实现自动地批量下载多集视频的Python脚本是这样考虑的。

(1)用浏览器而不是requests组件,因为我们需要执行脚本,而不是简单地获取和解析HTML内容。要切换选集,也可以在浏览器中模拟人的单击选集操作。自动化浏览器的操作,需要使用Selenium这个Python第三方库。当然,Selenium是很有名的工具,很多语言都可以用,不只是Python。要使用Selenium组件,除了安装这个Python库外,还需要搭配对应的浏览器驱动。我使用的是Google Chrome浏览器,所以下载了chromedriver。只不过,chromedriver下载和使用需要注意两点:一个是它不能直接从官方下载了,可以使用镜像下载(https://npm.taobao.org/mirrors/chromedriver/),另一个是要检查它支持的Chrome版本和你正在使用的Chrome是否兼容。

(2)还需要一个名为m3u8downloader的Python库。请使用命令pip install m3u8downloader安装,这个库装上好,提供了CLI界面,也就是说,可以使用命令行调用它。类似的组件还有其它,本文并不探讨和对比哪个更好,这个组件用的时候也发现一些问题,暂时先通过修改源码(后面会说)处理了,修改后实测还算好用。该组件的详细内容,见以下网址。

https://pypi.org/project/m3u8downloader/

(3)m3u8downloader在做下载视频后的合并时,又需要另一个工具,ffmpeg。可以在https://ffmpeg.org/download.html#build-windows 网址下载并解压到适当目录。建议把这个下载的ffmpeg和前面下载的chromedriver都放在一起,并需要设置PATH变量,让这些命令可以直接使用。

4.2脚本及说明

脚本如下,供参考:

import argparse

import os

from time import sleep

from selenium import webdriver

from selenium.common.exceptions import NoSuchElementException

parser = argparse.ArgumentParser(prog='autoseleniumvqq',

                                description="download video at QQ Video")

parser.add_argument('--destdir', default='D:\\', help='specify Destination Directory')

parser.add_argument('url', metavar='URL', help='the m3u8 url')

args = parser.parse_args()

browser = webdriver.Chrome()

browser.get(args.url)

input('登录成功并切换到高清后,请按回车键:')

while True:

    sleep(1)

    title = browser.execute_script("return $('.item_detail_half.current').text().trim().replace(' ', '')")

    videoURLJS = 'PLAYER._DownloadMonitor.context.dataset.ckc?PLAYER._DownloadMonitor.context.dataset.currentVideoUrl:PLAYER._DownloadMonitor.context.dataset.currentVideoUrl.replace(/http.*:.*qq.com/g,"http://defaultts.tc.qq.com/defaultts.tc.qq.com")'

    videoURL = browser.execute_script(f'return {videoURLJS}')

    outDir = args.destdir

    fileName = title + '.mp4'

    print('downloading ', fileName)

    os.system(f'downloadm3u8 -o {outDir}{fileName} {videoURL}')

    try:

        # break

        next = browser.find_element_by_css_selector('.item_detail_half.current + span a')

        next.click()

    except NoSuchElementException:

        browser.execute_script('console.log("DONE")')

        break

对脚本的说明如下:

(1)使用argparse获取可选参数--destdir(目标路径),也就是下载的MP4文件保存的位置,默认保存在D盘根目录。获取必选参数url。这个URL给定多集中的第一集的URL。注意URL就是浏览器地址栏里的URL。

(2)程序打开Chrome浏览器并打开(1)中给定的URL对应的页面。之后暂时等待输入回车。在浏览器中登录QQ会员并切换到高清后再回车。

(3)程序进入循环。在循环中程序执行浏览器中的JS脚本得到当前选集的标题(例如第一集的标题是“01舒克”),得到视频URL(本质上讲视频的M3U8文件的URL),并通过执行带参数的downloadm3u8命令(这个命令来自于前面提到的m3u8downloader的安装)下载当前选集的视频到指定的目录中。

(4)除了下载当前选集外,循环的最后,通过对CSS选择器找到下一集的超链接并模拟单击操作,直到把播放列表中找不到下一集时循环结束,程序完成下载任务。

(5)补充说明:在Windows 10上的实际运行效果来看,ffmpeg命令不能适应太长的路径,会导致不能正常运行合并视频片段为完整视频。究其原因,是因为QQ视频的真实URL太长,会导致形成一个名称多达171个字的目录。不得已,我只有修改m3u8downloader的源码,避免这种过长的目录名称。具体地修改在

\Python\Python38-32\Lib\site-packages\m3u8downloader\main.py文件中,对get_local_file_for_url()函数做了调整,在函数最后一句 return os.path.normpath(os.path.join(tempdir, path))之前加上了这几句:

# QQ视频的路径太长,ffmpeg不正常工作

    TRUNC_LEN = 30

    parts = path.split('/')

if len(parts[-2]) > TRUNC_LEN:

        parts[-2] = parts[-2][0:TRUNC_LEN]

        path = ''.join(parts)

最后运行脚本如下:

python autoseleniumvqq.py https://v.qq.com/x/cover/ean263o58zvxwpm/v0032sn0o61.html

5.结语

这篇文章是在学习Python时想到的尝试和实践基础上形成的,让我看到了Python语言在自动化方面的独到优势。想当年在爬虫一词还没有流行时,我还曾经用传统语言用下载了别的网站的连载漫画图片(给朋友帮忙),现在再看Python手段果然更为简洁方便。

有这个脚本,我下载整部动画片就不用像之前那样,手工去获取视频URL,手工去下载,手工去改文件名了。现在只要启动脚本,几十集动画片就等着它下载完成了。

第一次写简书,写得有点啰嗦,脚本本身也没有什么特别之处,请见谅。另外,软件可能也会随着版本升级发生变化,QQ视频也可能,所以说文章内容希望更多的交流经验,不希望复制粘贴地用。如果觉得还可供参考,更加欢迎。碰到问题,欢迎交流。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容