3530366912 发表于 2021-10-10 23:14:19

用爬虫下载视频,得到视频m3u8的url后,下载后打开不太对

这是原代码
'''
流程:
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>


百度也没百度到啥东西,看错误说明大致可以猜到是被加密了,请问有啥办法么?

wp231957 发表于 2021-10-11 06:38:27

这代码不是自己写的吧,自己走亲自抓包木有??

suchocolate 发表于 2021-10-11 09:02:30



import requests
import re


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


if __name__ == '__main__':
    main()

3530366912 发表于 2021-10-11 12:17:18

wp231957 发表于 2021-10-11 06:38
这代码不是自己写的吧,自己走亲自抓包木有??

是自己写的啊,跟着视频教程写的,只是把网页url换了,想下这个视频

3530366912 发表于 2021-10-11 12:21:06

suchocolate 发表于 2021-10-11 09:02


非常感谢!我研究一下你这个代码~

人造人 发表于 2021-10-12 01:57:11

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

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

import re
import requests
import threadpool
import shutil
import os
import sys
import subprocess

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

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

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

def get_media_play_list(url):
    play_list = get_file(url).decode()
    master_play_list = re.findall(r'^.+\.m3u8$', play_list, re.MULTILINE)
    if len(master_play_list) == 0: return play_list
    master_play_list = get_list_full_path(master_play_list, get_base_url(url))
    return get_file(master_play_list).decode()

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

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

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

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

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

session = requests.Session()

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

media_play_list = get_media_play_list(url)
ts_list = get_ts_list(media_play_list)

pool = threadpool.ThreadPool(8)
requests = threadpool.makeRequests(download_file, [((url, path), None) for url in ts_list])

pool.wait()

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

print(convert_video_format(path + '/index.m3u8', '31.mp4'))

3530366912 发表于 2021-10-12 22:08:49

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

{:5_106:}{:5_109:}哇!!非常感谢!!最近在学爬虫,用多线程或者协程来爬,正好有个视频要下,就干脆爬这个了,确实非常非常的大,毕竟是个学术报告~哈哈~

3530366912 发表于 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

人造人 发表于 2021-10-12 22:22:30

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

发代码看看

3530366912 发表于 2021-10-12 22:59:47

人造人 发表于 2021-10-12 22:22
发代码看看

# 里面有很多没用的东西,因为是根据别人的代码改编过来的
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)

人造人 发表于 2021-10-13 12:59:39

奇怪,你的回复我这边没有收到通知,还好我记得这件事,点进来才发现你已经回复了我,我找时间看看

人造人 发表于 2021-10-13 19:33:28

岩土.txt 的内容是什么?
看报错信息是超时了

3530366912 发表于 2021-10-13 20:28:26

人造人 发表于 2021-10-13 19:33
岩土.txt 的内容是什么?
看报错信息是超时了

内容就是下载下来的m3u8文件内容,我把它弄到txt文件里面去了~

人造人 发表于 2021-10-13 20:41:58

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

那么,文件后缀应该是 m3u8,不是 txt

人造人 发表于 2021-10-13 20:42:28

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

你发一下这个文件的内容吧

3530366912 发表于 2021-10-13 21:24:59

人造人 发表于 2021-10-13 20:42
你发一下这个文件的内容吧

#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:3.999,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3968_0.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3989_1.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3968_2.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3989_3.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3968_4.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3989_5.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3968_6.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3989_7.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3968_8.ts
#EXTINF:4,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_3989_9.ts
#EXTINF:2.579,
http://pull-sh1.weizan.cn/1885047439/468616706126501938/703220957200-3_2560_10.ts
就是这个,视频片段的链接~我把它重命名成txt了,,(别问为啥重命名,问就是无聊哈哈哈)

3530366912 发表于 2021-10-13 21:25:51

人造人 发表于 2021-10-13 20:42
你发一下这个文件的内容吧

为啥我的回复要审核啊,,你之前说没收到通知的那次,也是要审核,,

人造人 发表于 2021-10-13 22:02:48

3530366912 发表于 2021-10-13 21:25
为啥我的回复要审核啊,,你之前说没收到通知的那次,也是要审核,,

我有时候也要,回复的内容不能出现某些单词、句子,具体是哪些我也不清楚

3530366912 发表于 2021-10-14 17:40:35

人造人 发表于 2021-10-13 22:02
我有时候也要,回复的内容不能出现某些单词、句子,具体是哪些我也不清楚

txt文件的内容,就是16楼的那堆东西

人造人 发表于 2021-10-14 18:19:17

3530366912 发表于 2021-10-14 17:40
txt文件的内容,就是16楼的那堆东西

用代码格式发,不然无法复制
页: [1] 2
查看完整版本: 用爬虫下载视频,得到视频m3u8的url后,下载后打开不太对