【爬虫逆向】python爬虫爬取网站电影

部署运行你感兴趣的模型镜像

前言:网站存储与播放视频的技术原理

        在现代互联网中,视频内容的存储与播放是网站功能的重要组成部分。为了提升用户体验并优化资源利用,视频网站通常采用一种高效的技术方案:**视频切片与M3U8协议**。本文将详细介绍这一技术的原理及其实现方式。

一、 视频存储的基本原理

在网页中播放视频,通常需要使用HTML5的`<video>`标签。例如:

<video src="xxx.mp4"></video>

然而,直接使用视频文件的URL作为`src`并不是最佳实践。这种方式会导致以下问题:
- **占用大量带宽**:用户需要一次性下载整个视频文件,即使他们只观看了一小部分。
- **内存占用高**:大文件加载会占用大量内存,影响设备性能。
- **用户体验差**:加载速度慢,无法支持流畅的快进、跳转等操作。

为了解决这些问题,视频网站普遍采用**视频切片**技术。

二、视频切片技术

        视频切片技术将完整的视频文件分割成多个小片段(通常为`.ts`文件),每个片段都有独立的URL。用户观看视频时,浏览器会按需加载这些片段,而不是一次性下载整个视频。

切片技术的优势:
- **节省带宽**:只加载用户当前观看的部分,减少不必要的流量消耗。
- **支持快进与跳转**:用户快进时,可以直接加载目标位置的片段,无需等待整个视频下载。
- **减轻服务器压力**:通过分发小文件,降低服务器的负载。

三、M3U8文件的作用

        为了管理这些视频切片,网站会使用一种名为**M3U8**的文件格式。M3U8是一种基于文本的播放列表文件,记录了视频切片的URL及其播放顺序。

M3U8文件示例:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:3.560000,
https://example.com/video/segment0000.ts
#EXTINF:2.000000,
https://example.com/video/segment0001.ts
#EXTINF:1.520000,
https://example.com/video/segment0002.ts
#EXT-X-ENDLIST

M3U8文件的结构:
- **#EXTM3U**:文件头,表示这是一个M3U8文件。
- **#EXT-X-VERSION**:指定M3U8文件的版本。
- **#EXT-X-TARGETDURATION**:每个切片的最大时长。
- **#EXTINF**:每个切片的时长和URL。
- **#EXT-X-ENDLIST**:表示播放列表结束。

四、 视频播放的工作流程

视频网站通常采用以下步骤来加载和播放视频:

1. **请求M3U8文件**:
   - 浏览器首先请求M3U8文件,获取视频切片的播放列表。

2. **加载切片文件**:
   - 根据M3U8文件中的URL,按需加载视频切片(`.ts`文件)。

3. **播放视频**:
   - 将加载的切片按顺序拼接并播放,用户可以看到流畅的视频内容。

五、实际案例分析

        以某视频网站为例,我们可以通过浏览器的开发者工具(F12)抓取网络请求,观察M3U8文件和切片文件的加载过程。

抓包结果:
- **第一层M3U8文件**:

  #EXTM3U
  #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128,RESOLUTION=1142x480
  900k_0X480_64k_25/hls/index.m3u8

所有的带#号的都是字段名称,不带#号的一般是路径或者文件名称。

900k_0X480_64k_25/hls/index.m3u8

很明显这里是一个网页的路径,对应一个新的M3U8文件

那么我们找到下面的M3U8文件,对比一下路径

https://pptv.1080tg.com/202312/21/BxEB9XJSw23/video/900k_0X480_64k_25/hls/index.m3u8

发现第一个M3U8文件里的路径就是第二个M3U8文件的URL。

该文件指向第二层M3U8文件的URL。

- **第二层M3U8文件内容**:

  #EXTM3U
  #EXT-X-VERSION:3
  #EXT-X-TARGETDURATION:4
  #EXT-X-MEDIA-SEQUENCE:0
  #EXTINF:3.560000,
  https://example.com/video/segment0000.ts
  #EXTINF:2.000000,
  https://example.com/video/segment0001.ts
  #EXT-X-ENDLIST


        该文件包含了所有视频切片的URL。里面最重要的就是每一个ts文件的路径了,而且这个ts文件是没有加密的。

六、 技术实现:从M3U8到视频下载

        接着我们来看一下整个过程,首先我们需要先通过这个网站把m3u8文件获取到。

        直接搜一下网页的源代码,发现m3u8文件的链接就在这个url的字段里面。

        我们拿到这个文件就可以去获取第二个m3u8文件,接着再取解析m3u8文件,然后爬取电影切片数据。

步骤如下:

    (1)通过网页源码获取第一层m3u8文件地址
    (2)下载第一层m3u8文件,获取第二层m3u8文件地址
    (3)解析第二层m3u8文件,爬取视频切片
    (4)对TS文件进行合并,还原回MP4文件

第一步,我们需要从网页源码中,通过数据解析的方式,拿到第一层m3u8的链接

代码实现

def GetFirstM3u8Url():
    # 拿到页面源码
    url = "https://www.yunbtv.org/vodplay/sandadui-2-1.html"
    resp= requests.get(url)
    resp.encoding="utf-8"

    tree=etree.HTML(resp.text)
    # 解析出url
    script_content=tree.xpath('//script[contains(text(), "player_aaaa")]/text()')[0]

    # 我们需要从脚本中提取JSON部分
    json_str = script_content[script_content.find('{'):script_content.rfind('}') + 1]

    # 解析JSON字符串
    data = json.loads(json_str)

    # 提取URL值
    url_value = data.get("url", "")

    print(url_value)

输出结果如下:

这样的话第一步就完成了。

第一层M3U8的链接拿到之后,接下来需要下载到第二层的M3U8文件

代码实现

def DownloadM3u8File(first_m3u8_url):
    resp = requests.get(first_m3u8_url)
    resp.encoding = "utf-8"
    url2  = resp.text.split()[-1]

    # 移除第一个URL的最后一个分段(即去掉'/index.m3u8')
    base_url = first_m3u8_url.rsplit('/', 1)[0]
    # 第二层M3U8的地址
    Second_m3U8_Url = f"{base_url}/{url2}"

    #下载M3U8文件
    M3u8Resp=requests.get(Second_m3U8_Url)
    M3u8Resp.encoding = "utf-8"

    with open("m3u8.txt",mode="w",encoding="utf-8") as f:
        f.write(M3u8Resp.text)

实际效果:

        现在我们的m3u8文件就已经下载下来了,接下来处理这个M3U8文件,用协程逐个下载ts文件

代码实现


# 下载单个ts文件
async def download_one(url):
   print("正在下载:"+url)
   # 重试10次 防止下载失败
   for i in range(10):
       try:
           file_name=url.split("/")[-1]
           async with aiohttp.ClientSession() as session:
               async with session.get(url) as resp:
                   content=await  resp.content.read()
                   async with aiofiles.open(f"./TsFiles/{file_name}",mode="wb") as f:
                       await f.write(content)
           break
       except:
           print("下载失败:"+url)
           await asyncio.sleep((i+1)*5)



async def download_all_ts():
   # 准备好任务列表
   tasks=[]
   # 读取m3u8文件
   with open("m3u8.txt",mode="r",encoding="utf-8") as f:
       for line in f:
           # 排除所有#开头的
           if line.startswith("#"):
               continue
           line=line.strip()
           task=asyncio.create_task(download_one(line))
           tasks.append(task)

   # 等待任务全部结束
   await asyncio.wait(tasks)

这样的话,我们的ts文件就下载完成了

 接着通过TS的文件名,进行合并

代码实现

def MergeTsFiles():
    print("正在合并文件")
    name_list=[]
    with open("m3u8.txt",mode="r",encoding="utf-8") as f:
        for line in f:
            # 排除所有#开头的
            if line.startswith("#"):
                continue
            line=line.strip()
            file_name=line.split("/")[-1]
            name_list.append(file_name)


    with open(".\TsFiles\m3u8.txt", mode="w", encoding="utf-8") as f:
        for data in name_list:
            f.write("file "+"'"+data+"'"+"\n")


    # 记录当前的工作目录
    now_dir = os.getcwd()
    # 切换工作目录
    os.chdir("./TsFiles")
    os.system("D:\\ffmpeg\\ffmpeg.exe -f concat -safe 0 -i m3u8.txt -c copy output.mp4")
    # 所有操作后要把工作目录切换回来
    os.chdir(now_dir)
    print("文件合并完成")

这样的话,所有爬虫视频的工作就完成了

转载原文:鬼手56博主 
使用爬虫爬取热门电影_爬虫查找vip视频的真实地址-优快云博客

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值