jjzjj

python爬虫练习18:爬虫抓取视频思路2

<编程路上> 2024-05-10 原文

想要抓取一个视频:

  1. 找到m3u8 (各种手段)
  2. 通过m3u8下载到ts文件
  3. 可以通过各种手段(不仅是编程手段) 把ts文件合并为一个mp4文件

找到一个视频网址打开,查看源码和F12

获取该链接,但是发现不是真正的m3u8

真正的m3u8在这个链接里面
从中获取合成真正的m3u8下载地址

先用代码完成这一部分:

url='http://48ys.top/vodplay/cW7JJJJN-1-1.html'
headers = {'User-Agent': str(UserAgent().random)}
resp = requests.get(url,headers=headers)
res=re.compile(r'"link_pre":"","url":"(?P<url>.*?)",', re.S)# re.S: 让.能匹配换行符
m3u8_url = res.search(resp.text).group('url')
m3u8_url = m3u8_url.replace('\\','')
truth_left = m3u8_url.split('/2')[0]
resp1 = requests.get(m3u8_url,headers=headers)
truth_url =truth_left+resp1.text.split('1280x720\n')[1]
print(truth_url)

输出如下:

使用获得的地址下载m3u8文件

resp2 = requests.get(truth_url.replace('\n',''),headers=headers)#去掉尾部的\n
with open('monv2.m3u8', mode="wb") as f:
    f.write(resp2.content)
f.close()


观看一下真是的视频地址:

所以需要我们进行一下处理,变成真正的视频下载地址。

# 3.2 下载第二层m3u8文件
with open("monv2.m3u8", mode="r", encoding="utf-8") as f:
        for line in f:
            if line.startswith("#"):
                continue
            else:
                line = line.strip()  # 去掉空白或者换行符  hls/index.m3u8
                # 准备拼接第二层m3u8的下载路径
                second_m3u8_url = truth_left + line
                print(second_m3u8_url)
f.close()
print('ok')


所以视频地址获取到了,但是如果下载的话太慢了,所以采用协程方法快速下载,完整代码如下:

import requests
from bs4 import BeautifulSoup
import re
import asyncio
import aiohttp
import aiofiles
from Crypto.Cipher import AES  # pycryptodome
import os
from fake_useragent import UserAgent


def main():
    print('ok')

def m3u8_allurl(name,truth_left):
    # 3.2 下载第二层m3u8文件
    urls = list()
    with open(name, mode="r", encoding="utf-8") as f:
        for line in f:
            if line.startswith("#"):
                continue
            else:
                line = line.strip()  # 去掉空白或者换行符  hls/index.m3u8
                # 准备拼接第二层m3u8的下载路径
                second_m3u8_url = truth_left + line
                urls.append(second_m3u8_url)

    f.close()
    return  urls

def m3u8_download(name,truth_url):
    headers = {'User-Agent': str(UserAgent().random)}
    resp2 = requests.get(truth_url.replace('\n', ''), headers=headers)  # 去掉尾部的\n
    with open(name, mode="wb") as f:
        f.write(resp2.content)
    f.close()
    print(name,' download!!!')


def m3u8_get(url):
    headers = {'User-Agent': str(UserAgent().random)}
    resp = requests.get(url, headers=headers)
    res = re.compile(r'"link_pre":"","url":"(?P<url>.*?)",', re.S)  # re.S: 让.能匹配换行符
    m3u8_url = res.search(resp.text).group('url')
    m3u8_url = m3u8_url.replace('\\', '')
    truth_left = m3u8_url.split('/2')[0]
    resp1 = requests.get(m3u8_url, headers=headers)
    truth_url = truth_left + resp1.text.split('1280x720\n')[1]
    return  truth_left,truth_url.strip()

async def download_ts(url, name, session):

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

async def aio_download(allurls,name):
    tasks = []
    n = 1
    async with aiohttp.ClientSession() as session:  # 提前准备好session
      for i_url in allurls:
        task = asyncio.create_task(download_ts(i_url, name+f'_{n}.ts',session))  # 创建任务
        n += 1
        tasks.append(task)
      await asyncio.wait(tasks)  # 等待任务结束




if __name__ == '__main__':
    url = 'http://48ys.top/vodplay/cW7JJJJN-1-1.html'
    truth_left,m3u8 = m3u8_get(url)
    print(m3u8)
    m3u8_download('monv2.m3u8',m3u8)
    allurls = m3u8_allurl('monv2.m3u8', truth_left)

    print(allurls)

    asyncio.run(aio_download(allurls, 'monv2/monv2'))
    print(len(allurls))
    main()


合成mp4视频的话建议使用一下工具,用代码的话有点慢,我的.py文件必须在这些视频的文件夹内运行才能合成,使用文件夹/文件名不能合成,也不清楚什么原因。还有一个问题就是所有ts文件不能一起合成,我也不清楚什么原因,因为不报错也不生成视频,使用我每100个ts合成一个大的ts,将这些大的ts统一合成一个mp4.

import os

lst = []
n=1
#将所有的文件名放入列表
with open("monv2.m3u8", mode="r", encoding="utf-8") as f:
    for line in f:
        if line.startswith("#"):
            continue
        line = line.strip()
        lname = line.split('/')[-1]
        lst.append(lname)


#每100个ts文件名放入一个列表
k=[[] for i in range(0,100)]
num=-1
for i in range(0, len(lst)):
    if(i%100==0):
        num+=1
        # print(num)
    # print(i)
    k[num].append(lst[i])

#100个ts先合成一个大的ts
ts=[]
for i in range(0,num+1):
    s = "+".join(k[i])
    print(s)
    os.system(f"copy/b {s} he{i}.ts")
    ts.append(f'he{i}.ts')
    print(f'{i} is ok')

print(ts)

#将大的ts合成一个mp4
s = "+".join(ts)
os.system(f"copy/b {s} he.mp4")
print('he.mp4 is ok')

这是成功合成好的视频:

有关python爬虫练习18:爬虫抓取视频思路2的更多相关文章

  1. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby-on-rails - Rails 3 I18 : translation missing: da. datetime.distance_in_words.about_x_hours - 2

    我看到这个错误:translationmissing:da.datetime.distance_in_words.about_x_hours我的语言环境文件:http://pastie.org/2944890我的看法:我已将其添加到我的application.rb中:config.i18n.load_path+=Dir[Rails.root.join('my','locales','*.{rb,yml}').to_s]config.i18n.default_locale=:da如果我删除I18配置,帮助程序会处理英语。更新:我在config/enviorments/devolpment

  4. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  5. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  6. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  7. ruby-on-rails - Ruby on Rails I18n 插值 - 2

    大家好!我对我的:username字段进行了一个小的验证,它应该是4到30个字符。我写了一个验证::length=>{:within=>4..30,:message=>I18n.t('activerecord.errors.range')-我想显示一个错误各种错误的消息(不像,太长或太短),但这里有一个问题-我可以将最小值和最大值都传递给翻译,以便有类似的东西:用户名应该在4到30个字符之间。目前我有:range:"shouldbebetween%{count}and%{count}characters",这显然不起作用(只是为了检查)。是否可以从范围中获取这些值?谢谢大家的指教!

  8. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  9. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  10. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

随机推荐