鱼C论坛

 找回密码
 立即注册
查看: 3459|回复: 21

[已解决]用爬虫下载视频,得到视频m3u8的url后,下载后打开不太对

[复制链接]
发表于 2021-10-10 23:14:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这是原代码
'''
流程:
1.拿到网页源代码
2.从源代码中提取到m3u8的url
3.下载m3u8
4.读取m3u8文件,下载视频
5.合并视频
'''

import requests
import re

# 拿到网页的源代码
main_url = 'https://wx.vzan.com/live/tvchat-1353603565?shauid=3L2J-FI9aT8UjjZ1EgQeHA**&vprid=0&sharetstamp=1633088881811&ver=6118677193634a4bb9139998ea15739d#/'
headers = {
    'accept': 'text/plain, */*; q=0.01',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cache-control': 'no-cache',
    'origin': 'https://wx.vzan.com',
    'pragma': 'no-cache',
    'referer': 'https://wx.vzan.com/live/tvchat-1353603565?shauid=3L2J-FI9aT8UjjZ1EgQeHA**&vprid=0&sharetstamp=1633088881811&ver=6118677193634a4bb9139998ea15739d',
    'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
    'sec-ch-ua-mobile': '?0',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'cross-site',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36'
}
resp_main_url = requests.get(main_url, headers=headers)
# print(resp_main_url)
obj = re.compile(r"var hlsUrl = '(?P<m3u8_url>.*?)';", re.S)  # 写正则

# 拿到m3u8的源代码
m3u8_url = obj.search(resp_main_url.text).group('m3u8_url')
print(m3u8_url)
# 下载m3u8文件
resp_m3u8 = requests.get(m3u8_url).content.decode('utf-8')
# print(resp_m3u8)
with open("岩土.m3u8", mode='w') as f:
    f.write(resp_m3u8)
print('over!')


运行结果:
<?xml version='1.0' encoding='utf-8' ?>
<Error>
        <Code>NoSuchKey</Code>
        <Message>The specified key does not exist.</Message>
        <Resource>pull-sh1-1251575313.cos.ap-shanghai.myqcloud.com/2D16I16F10f0k8g14h8V6X18J/8I12y16I12F2b12N14Z0l12Q2O4M12F10T0L2V18f6b16r/replay.1632042576.30049749.m3u8</Resource>
        <RequestId>NjE2MmZmZDNfNzU0OTIyMDlfMTQxZF8xZjhjM2Mw</RequestId>
        <TraceId>OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1NmI1M2E2MTRlY2MzZDhmNmI5MWI1OTkwMTkyODMxODFlYzJhYTVmMmIyNDI0YjMyOGQxMzc1MTJhNjg4YjMxOWNiMGVjYWRiYWRlYTc0MjhlN2M3NWY=</TraceId>
</Error>


百度也没百度到啥东西,看错误说明大致可以猜到是被加密了,请问有啥办法么?
最佳答案
2021-10-11 09:02:30


  1. import requests
  2. import re


  3. def main():
  4.     url = 'https://wx.vzan.com/live/tvchat-1353603565?shauid=3L2J-FI9aT8UjjZ1EgQeHA**&vprid=0&sharetstamp' \
  5.           '=1633088881811&ver=6118677193634a4bb9139998ea15739d#/'
  6.     headers = {'user-agent': 'Mozilla'}
  7.     r = requests.get(url, headers=headers)
  8.     m3 = re.findall(r"var hlsUrl = '(.*?)'", r.text)[0].split('/')[-1]
  9.     zbid = re.findall(r"zbid: (.*?),", r.text)[0]
  10.     stream = re.findall(r"stream: '(.*?)',", r.text)[0]
  11.     m3u8_url = f"https://pull-sh1.weizan.cn/{zbid}/{stream}/{m3}"  # html自带的不能直接用,得自己合成。
  12.     r = requests.get(m3u8_url, headers=headers)
  13.     print(r.text)


  14. if __name__ == '__main__':
  15.     main()
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-10-11 06:38:27 From FishC Mobile | 显示全部楼层
这代码不是自己写的吧,自己走亲自抓包木有??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-11 09:02:30 | 显示全部楼层    本楼为最佳答案   


  1. import requests
  2. import re


  3. def main():
  4.     url = 'https://wx.vzan.com/live/tvchat-1353603565?shauid=3L2J-FI9aT8UjjZ1EgQeHA**&vprid=0&sharetstamp' \
  5.           '=1633088881811&ver=6118677193634a4bb9139998ea15739d#/'
  6.     headers = {'user-agent': 'Mozilla'}
  7.     r = requests.get(url, headers=headers)
  8.     m3 = re.findall(r"var hlsUrl = '(.*?)'", r.text)[0].split('/')[-1]
  9.     zbid = re.findall(r"zbid: (.*?),", r.text)[0]
  10.     stream = re.findall(r"stream: '(.*?)',", r.text)[0]
  11.     m3u8_url = f"https://pull-sh1.weizan.cn/{zbid}/{stream}/{m3}"  # html自带的不能直接用,得自己合成。
  12.     r = requests.get(m3u8_url, headers=headers)
  13.     print(r.text)


  14. if __name__ == '__main__':
  15.     main()
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-11 12:17:18 | 显示全部楼层
wp231957 发表于 2021-10-11 06:38
这代码不是自己写的吧,自己走亲自抓包木有??

是自己写的啊,跟着视频教程写的,只是把网页url换了,想下这个视频
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-11 12:21:06 | 显示全部楼层

非常感谢!我研究一下你这个代码~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-12 01:57:11 | 显示全部楼层
来迟了
服务器可能使用了某种反爬虫机制,这个地址我这边一开始是会报错的,和你的报错信息一样,之后我使用 curl 和 wget 一个参数一个参数的排除,然后现在是不添加 headers 也可以用了
我没有弄明白服务器检查了哪个参数,因为我现在这边正常了,我弄不回那个不能用的状态了,没办法再一个参数一个参数的排除了
还有,你这个视频 13 个小时,一共有 15245 个 ts 视频,8 线程下载这些 ts 我这边花了 1 个多小时,合并视频花了 5 个多小时,合并后的 mp4 文件 11.9GB,^_^

下面这个代码是我前不久写的,思路和你的完全一样,不过就是没有第 1 步和第 2 步,毕竟这个代码不是我用的,是帮别人写的,所以这些简单的部分我就没有写
  1. #!/usr/bin/env python
  2. #coding=utf-8

  3. import re
  4. import requests
  5. import threadpool
  6. import shutil
  7. import os
  8. import sys
  9. import subprocess

  10. def get_file(url):
  11.     global session
  12.     while True:
  13.         try: content = session.get(url).content
  14.         except: sys.stderr.write('"' + url + '": download failed, retry!\n'); continue
  15.         break
  16.     return content

  17. def get_base_url(url):
  18.     return re.search(r'^(.+?://.+?)/', url).group(1)

  19. def get_list_full_path(url_list, base_url):
  20.     for i in range(len(url_list)):
  21.         url_list[i] = url_list[i] if re.search(r'^.+?://', url_list[i]) else base_url + url_list[i]
  22.     return url_list

  23. def get_media_play_list(url):
  24.     play_list = get_file(url).decode()
  25.     master_play_list = re.findall(r'^.+\.m3u8$', play_list, re.MULTILINE)
  26.     if len(master_play_list) == 0: return play_list
  27.     master_play_list = get_list_full_path(master_play_list, get_base_url(url))
  28.     return get_file(master_play_list[0]).decode()

  29. def get_ts_list(media_play_list):
  30.     return re.findall(r'^.+?://.+?\.ts$', media_play_list, re.MULTILINE)

  31. def download_file(url, path):
  32.     filename = re.search(r'^.+/(.+)$', url).group(1)
  33.     with open(path + '/' + filename, 'wb') as f: f.write(get_file(url))
  34.     sys.stdout.write(path + ': ' + url + '\n')

  35. def get_video_info(path):
  36.     ffprobe_cmd = ['ffprobe', '-protocol_whitelist', 'https,file,crypto,tls,tcp', '-show_streams', '-print_format', 'json', path]
  37.     startupinfo = subprocess.STARTUPINFO()
  38.     startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
  39.     startupinfo.wShowWindow = subprocess.SW_HIDE
  40.     ffprobe = subprocess.Popen(ffprobe_cmd, stdout = subprocess.PIPE, startupinfo = startupinfo)
  41.     ffprobe.wait()
  42.     return json.loads(ffprobe.stdout.read())

  43. def convert_video_format(v1, v2):
  44.     ffmpeg_cmd = ['ffmpeg', '-y', '-protocol_whitelist', 'https,file,crypto,tls,tcp', '-i', v1, '-c:v', 'h264', v2]
  45.     ffmpeg = subprocess.Popen(ffmpeg_cmd)
  46.     ffmpeg.wait()
  47.     return ffmpeg.returncode

  48. url = 'https://pull-sh1.weizan.cn/1885047439/468616706126501938/replay.1632042576.30049749.m3u8'

  49. session = requests.Session()

  50. path = 'download'
  51. shutil.rmtree(path, True)
  52. os.mkdir(path)

  53. media_play_list = get_media_play_list(url)
  54. ts_list = get_ts_list(media_play_list)

  55. pool = threadpool.ThreadPool(8)
  56. requests = threadpool.makeRequests(download_file, [((url, path), None) for url in ts_list])
  57. [pool.putRequest(req) for req in requests]
  58. pool.wait()

  59. media_play_list = re.sub(r'^.+/(.+?\.ts)$', r'\1', media_play_list, flags = re.MULTILINE)
  60. with open(path + '/index.m3u8', 'w') as f: f.write(media_play_list)

  61. print(convert_video_format(path + '/index.m3u8', '31.mp4'))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 22:08:49 | 显示全部楼层
人造人 发表于 2021-10-12 01:57
来迟了
服务器可能使用了某种反爬虫机制,这个地址我这边一开始是会报错的,和你的报错信息一样,之后我使 ...

哇!!非常感谢!!最近在学爬虫,用多线程或者协程来爬,正好有个视频要下,就干脆爬这个了,确实非常非常的大,毕竟是个学术报告~哈哈~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 22:11:32 | 显示全部楼层
人造人 发表于 2021-10-12 01:57
来迟了
服务器可能使用了某种反爬虫机制,这个地址我这边一开始是会报错的,和你的报错信息一样,之后我使 ...

随便能请教一个问题么?我用异步协程下载视频ts文件,出现了这样的错误是怎么回事?
File "D:\Python_study\爬虫\爬取视频\简单版本 爬取朱德霖\下载(异步,有问题).py", line 6, in download_ts
    async with session.get(url) as resp:
  File "D:\Python_study\venv\lib\site-packages\aiohttp\client.py", line 1117, in __aenter__
    self._resp = await self._coro
  File "D:\Python_study\venv\lib\site-packages\aiohttp\client.py", line 619, in _request
    break
  File "D:\Python_study\venv\lib\site-packages\aiohttp\helpers.py", line 656, in __exit__
    raise asyncio.TimeoutError from None
asyncio.exceptions.TimeoutError
Task exception was never retrieved
future: <Task finished name='Task-5706' coro=<download_ts() done, defined at D:\Python_study\爬虫\爬取视频\简单版本 爬取朱德霖\下载(异步,有问题).py:5> exception=TimeoutError()>
Traceback (most recent call last):
  File "D:\Python_study\爬虫\爬取视频\简单版本 爬取朱德霖\下载(异步,有问题).py", line 6, in download_ts
    async with session.get(url) as resp:
  File "D:\Python_study\venv\lib\site-packages\aiohttp\client.py", line 1117, in __aenter__
    self._resp = await self._coro
  File "D:\Python_study\venv\lib\site-packages\aiohttp\client.py", line 619, in _request
    break
  File "D:\Python_study\venv\lib\site-packages\aiohttp\helpers.py", line 656, in __exit__
    raise asyncio.TimeoutError from None
asyncio.exceptions.TimeoutError

进程已结束,退出代码为 -1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-12 22:22:30 | 显示全部楼层
3530366912 发表于 2021-10-12 22:11
随便能请教一个问题么?我用异步协程下载视频ts文件,出现了这样的错误是怎么回事?
File "D:\Python_s ...

发代码看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 22:59:47 | 显示全部楼层

# 里面有很多没用的东西,因为是根据别人的代码改编过来的
import aiofiles
import aiohttp
import asyncio

async def download_ts(url, name, session):
    async with session.get(url) as resp:
        async with aiofiles.open(f"岩土视频/{name}.ts", mode="wb") as f:
            await f.write(await resp.content.read())  # 把下载到的内容写入到文件中
    print(f"{name}下载完毕")


# 解析m3u8文件 异步下载
async def aio_download():
    tasks = []
    n = 1
    async with aiohttp.ClientSession() as session:  # 提前准备好session
        async with aiofiles.open("岩土.txt", mode="r", encoding='utf-8') as f:
            async for line in f:
                if line.startswith("#"):
                    continue
                line = line.strip()
                task = asyncio.create_task(download_ts(line, n, session))  # 创建任务
                tasks.append(task)
                n = n + 1
            await asyncio.wait(tasks)  # 等待任务结束



def main(url, headers):
    asyncio.run(aio_download())  


if __name__ == '__main__':
    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36"
    }
    url = "https://www.91kanju.com/vod-play/58988-1-1.html" # 根据别人的代码改的,别在意这个url
    main(url, headers)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-13 12:59:39 From FishC Mobile | 显示全部楼层
奇怪,你的回复我这边没有收到通知,还好我记得这件事,点进来才发现你已经回复了我,我找时间看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-13 19:33:28 | 显示全部楼层
岩土.txt 的内容是什么?
看报错信息是超时了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-13 20:28:26 | 显示全部楼层
人造人 发表于 2021-10-13 19:33
岩土.txt 的内容是什么?
看报错信息是超时了

内容就是下载下来的m3u8文件内容,我把它弄到txt文件里面去了~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-13 20:41:58 | 显示全部楼层
3530366912 发表于 2021-10-13 20:28
内容就是下载下来的m3u8文件内容,我把它弄到txt文件里面去了~

那么,文件后缀应该是 m3u8,不是 txt
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-13 20:42:28 | 显示全部楼层
3530366912 发表于 2021-10-13 20:28
内容就是下载下来的m3u8文件内容,我把它弄到txt文件里面去了~

你发一下这个文件的内容吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-13 21:24:59 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-13 21:25:51 | 显示全部楼层
人造人 发表于 2021-10-13 20:42
你发一下这个文件的内容吧

为啥我的回复要审核啊,,你之前说没收到通知的那次,也是要审核,,
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-13 22:02:48 | 显示全部楼层
3530366912 发表于 2021-10-13 21:25
为啥我的回复要审核啊,,你之前说没收到通知的那次,也是要审核,,

我有时候也要,回复的内容不能出现某些单词、句子,具体是哪些我也不清楚
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-14 17:40:35 | 显示全部楼层
人造人 发表于 2021-10-13 22:02
我有时候也要,回复的内容不能出现某些单词、句子,具体是哪些我也不清楚

txt文件的内容,就是16楼的那堆东西
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-14 18:19:17 | 显示全部楼层
3530366912 发表于 2021-10-14 17:40
txt文件的内容,就是16楼的那堆东西

用代码格式发,不然无法复制
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-28 03:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表