单线程多任务协程vip电影爬取

​ ——仅供学习使用勿作商用如有违规后果自负!!!

这几天一直在使用python爬取电影,主要目的也是为了巩固前段时间强化学习的网络爬虫,也算是一个不错的检验吧,面对众多的反爬机制,爬虫真的是一件不容易的事,但我们本着“没有爬不下来的东西,只有懒惰的程序员”的坊间箴言,在遵守有关法律法规的前提下,与反爬机制作斗争,也是一个提升自我的过程。下面言归正传,今天我们学习一下使用单线程多任务协程方式来爬取普通电影和vip电影

一、明确几个概念

  1. 关于网络抓包:

    1. elements里面是当前所见的网页,网页变化elements里面的标签元素也会变化,它只是记录某一时刻的网页内容,可以将它视为“快照”。
    2. 而network内则记录从你打开检查开始网页上出现的所有的包,既然是从你打开检查开始,因此会存在一些漏包,建议先清空network,然后重新刷新页面,就能捕捉到所有的包,就不会出现漏包。
  2. 各大优酷腾讯爱奇艺等主流互联网视频网站,为了反爬以及防止过度占用媒体资源,抓包中是不提供.mp4文件,一般都以.m3u8的格式呈现。
    1. M3U8 是 Unicode 版本的 M3U,用 UTF-8 编码。"M3U" 和 "M3U8" 文件都是苹果公司使用的 HTTP Live Streaming(HLS) 协议格式的基础,这种协议格式可以在 iPhone 和 Macbook 等设备播放。简而言之,HLS 是新一代流媒体传输协议,其基本实现原理为将一个大的媒体文件进行分片,将该分片文件资源路径记录于 m3u8 文件(即 playlist)内,其中附带一些额外描述(比如该资源的多带宽信息···)用于提供给客户端。客户端依据该 m3u8 文件即可获取对应的媒体资源,进行播放。链接:https://www.jianshu.com/p/e97f6555a070
    2. 抓m3u8真的是件很不容易的事情,无论vip还是普通电影,都能搜索到.m3u8的数据(url),打开检查后,最好再刷新一下网页,因为很多都是打开网页m3u8就立马加载的,爬取电影分vip爬取和普通爬取进行讲解。

二、普通电影爬取

  • 直接f12抓包,搜索.m3u,能找到m3u8的url

  • 获得后下载m3u8,用python编写代码(代码与vip下载相同,不做重复说明)下载里面的.ts文件,合成.mp4,如果能够播放,但是时长显示错误的话,需要用ffmpeg转码。

    ffmpeg -i out.ogv -vcodec h264 out.mp4
    ffmpeg -i out.ogv -vcodec mpeg4 out.mp4
    ffmpeg -i out.ogv -vcodec libxvid out.mp4
    ffmpeg -i out.mp4 -vcodec wmv1 out.wmv
    ffmpeg -i out.mp4 -vcodec wmv2 out.wmv
    #-i 后面是输入文件名。-vcodec 后面是编码格式,h264 最佳,但 Windows 系统默认不安装。如果是要插入 ppt 的视频,选择 wmv1 或 wmv2 基本上万无一失。 附加选项:-r 指定帧率,-s 指定分辨率,-b 指定比特率;于此同时可以对声道进行转码,-acodec 指定音频编码,-ab 指定音频比特率,-ac 指定声道数,例如

三、VIP电影抓取

  1. 如果不是会员,vip电影直接在主流视频完整抓包是抓不到完整的m3u8的,所以我们用http://jx.618g.com/?url=视频地址,去解析。关于解析网站值得说明的是,如果把优酷上的某个电影网址输入,找到的不一定是你想要的,但一般不会错。比如找房祖名的某部电影,然后找到的竟然是该名的外国片。所以jx.618g.com是在全网找这部关键字的电影哦,所以并非如你所想。解析网站也不是把原网页的电影给解析出来,主流的视频vip电影哪有这么容易就解析出来。

  2. 下面我们开始爬取电影

    • 用requests.get(url=url)获取m3u8文件,确实能获取到,但是有时那个.m3u8文件是不对的,因为真正的m3u8有时是动态加载的。所以要用抓包搜m3u8,然后真正的m3u8(几十K)。下载m3u8完毕后,合成电影有两种方式:
    1. 使用ffmpeg合成

      ffmpeg -i "网址" -vcodec copy -acodec copy 电影.mp4
      • 成功率不高,几千个ts文件,总有出错的,存在电影文件无法读取的隐患
    2. 使用python下载.ts文件并合成(推荐),请看源码讲解。

      1. conf.py文件:配置文件

        import re
        #'''
        # n_times用于在下载上千个ts文件时,对待个别未成功下载的文件需要再次运行main完成下载
        # 每次运行一次main更改一次数字
        #'''
        n_times=1 #'''
        # 永远不变
        #'''
        #undo_list为未下载成功后生成的未下载序号
        undo_list='未下载'+str(n_times)+'.txt'
        #new_m3u8_list为未下载成功后生成的待下载的.ts文件列表
        new_m3u8_list='new_m3u8_list'+str(n_times)+'.txt' #'''
        # 每次下载一部电影都要更改
        #'''
        #m3u8原始路径
        path_m3u8 = '新扎师妹.m3u8'
        #下载地址的base目录
        path_base='https://youku.cdn-tudou.com/20180611/6359_a2aef4b6/1000k/hls/'
        #root为电影ts文件下载目录
        root = r"D:\movie\vip8"
        #对某部电影匹配正则运算,找到电影序号
        ret = re.compile('de5a(.*?).ts')
      2. create_m3u8_list.py:对m3u8源文件进行提取下载列表

        from conf import path_m3u8
        import os
        def m3u8_table(path_m3u8):
        m3u8_list=path_m3u8+'.txt'
        with open(path_m3u8,mode='r',encoding='utf-8')as f:
        if not os.path.isfile(m3u8_list):
        for line in f:
        if '.ts' in line:
        with open(m3u8_list, mode='a', encoding='utf-8')as f1:
        f1.write(line)
        return m3u8_list
        m3u8_list=m3u8_table(path_m3u8)
      3. m3u8_main.py:运行的主文件

        import requests
        import aiohttp
        import asyncio
        import re
        import os
        import time
        from time import sleep
        from conf import *
        from create_m3u8_list import m3u8_list#无论from还是直接import都会运行那个模块的
        from functools import partial# partial(偏函数)可以把函数包装成另外一个函数
        start=time.time() headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'} num=0#计算到第几个文件
        async def get_request(sem,url):
        global num
        async with sem:
        async with aiohttp.ClientSession() as s:
        async with await s.get(url,headers=headers) as response:
        rep = await response.read()#read()返回的是byte类型的数据
        num += 1
        print('------------{}'.format(num))
        return rep tasks = []
        #最大并发数
        sem = asyncio.Semaphore(50) # 向回调函数传递参数
        def parse(line,task):
        try:
        res = ret.findall(line)
        ct = "%04d" % int(res[0])
        rep = task.result()
        abs_path = os.path.join(root, ct + '.ts')
        with open(abs_path, mode='wb')as f1:
        f1.write(rep)
        except Exception as e:
        with open(undo_list,mode='a',encoding='utf-8')as f2:
        f2.write(ct+'\n')
        print(e) def run(path):
        with open(path,mode='r',encoding='utf-8')as f:
        for line in f:
        line=line.strip('\n')
        if 'http' not in line:
        line=path_base+line
        c = get_request(sem,line)
        task = asyncio.ensure_future(c)
        task.add_done_callback(partial(parse,line))
        #还是要用回调的,传参的回调,一边下一边就能保存,比后面同步的后续处理要好,因为不需要task都完毕了才保存。
        tasks.append(task)
        loop = asyncio.get_event_loop()
        loop.run_until_complete(asyncio.wait(tasks)) def main():
        run(exec_list)
        with open(undo_list, mode='r', encoding='utf-8') as f3, open(m3u8_list, mode='r', encoding='utf-8')as f4, open(new_m3u8_list, mode='a', encoding='utf-8') as f5:
        whole = f4.readlines()
        for line in f3:
        line = line.strip('\n')
        f5.write(whole[int(line)])
        print(time.time()-start) if __name__ == '__main__':
        # 第一遍执行文件exc_list选择m3u8_list,第二遍选择new_m3u8_list1,第三遍以此类推
        if n_times==1:
        exec_list=m3u8_list
        else:
        exec_list='new_m3u8_list'+str(n_times-1)+'.txt'
        main() #后面不适用回调,为同步处理数据,感觉不好,一错俱错
        # if __name__ == '__main__':
        # run(path)
        # for task in tasks:
        # try:
        # # 这个ct放try后面顺序就不会乱,否则,一旦有个不能下载,就一直保持连续,都不知道谁有问题不能下。
        # ct += 1
        # rep = task.result()
        # ct1 = "%04d" % int(ct)
        # abs_path = os.path.join(root,ct1+'.ts')
        # with open(abs_path, mode='wb')as f1:
        # f1.write(rep)
        # except Exception:
        # print(task.cancel())
        # continue
        # print(time.time()-start)
      4. m3u8_combine.py:合成ts文件为mp4格式

        # 整合所有ts文件,保存为mp4格式
        import os
        import sys
        import shutil
        def tsToMp4():
        print("开始合并...")
        root = r"D:\Movie\vip7"
        outdir = r"D:\Movie\output"
        #很重要,一定要切换到目录下
        os.chdir(root)
        if not os.path.exists(outdir):
        os.mkdir(outdir)
        os.system("copy /b *.ts new.mp4")
        os.system("move new.mp4 {}".format(outdir))
        print("结束合并...")
        tsToMp4()
      5. 如果存在普通电影爬取所说的能看而时长错误,可以使用ffmpeg转码

                强烈建议大家注册为会员观看vip电影,电影爬取仅为学习使用,不可作为商业用途,产生侵权等法律问题由当事人承担
        书写不易,请留有余香

单线程多任务协程vip电影爬取的更多相关文章

  1. python 多协程异步IO爬取网页加速3倍。

    from urllib import request import gevent,time from gevent import monkey#该模块让当前程序所有io操作单独标记,进行异步操作. m ...

  2. 猫眼电影爬取(三):requests+pyquery,并将数据存储到mysql数据库

    还是以猫眼电影为例,这次用pyquery库进行爬取 1.简单demo,看看如何使用pyquery提取信息,并将提取到的数据进行组合 # coding: utf-8 # author: hmk impo ...

  3. 猫眼电影爬取(二):requests+beautifulsoup,并将数据存储到mysql数据库

    上一篇通过requests+正则爬取了猫眼电影榜单,这次通过requests+beautifulsoup再爬取一次(其实这个网站更适合使用beautifulsoup库爬取) 1.先分析网页源码 可以看 ...

  4. 猫眼电影爬取(一):requests+正则,并将数据存储到mysql数据库

    前面讲了如何通过pymysql操作数据库,这次写一个爬虫来提取信息,并将数据存储到mysql数据库 1.爬取目标 爬取猫眼电影TOP100榜单 要提取的信息包括:电影排名.电影名称.上映时间.分数 2 ...

  5. python多任务——协程的使用

    使用yield完成多任务 import time def test1(): while True: print("--1--") time.sleep(0.5) yield Non ...

  6. Python爬虫入门教程:豆瓣Top电影爬取

        基本开发环境 Python 3.6 Pycharm 相关模块的使用 requests parsel csv 安装Python并添加到环境变量,pip安装需要的相关模块即可. 爬虫基本思路 一. ...

  7. python的多线程、多进程、协程用代码详解

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:刘早起早起 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  8. 小爬爬4.协程基本用法&&多任务异步协程爬虫示例(大数据量)

    1.测试学习 (2)单线程: from time import sleep import time def request(url): print('正在请求:',url) sleep() print ...

  9. 多任务3(协程)--yield完成多任务交替执行

    协程是并发,单线程,一次执行一个 来回切换 代码: import time def task_1(): while True: print("-----1-----") time. ...

随机推荐

  1. [红日安全]Web安全Day3 - CSRF实战攻防

    本文由红日安全成员: Once 编写,如有不当,还望斧正. 大家好,我们是红日安全-Web安全攻防小组.此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目起了一个名字 ...

  2. java内存区域----运行时数据区

    Java虚拟机的内存区域也叫做java运行时数据区,共分为五个部分:程序计数器,方法区,本地方法栈,虚拟机栈和堆.方法区和堆是线程之间所共有的,程序计数器,本地方法栈,虚拟机栈是线程私有的.其中虚拟机 ...

  3. IP 转发分组的流程

    IP 转发分组的流程 数据路由:路由器在不同网段转发数据包: 网络畅通的条件:数据包能去能回: 从源网络发出时,沿途的每一个路由器必须知道到目标网络下一跳给哪个接口: 从目标网络返回时,沿途的每一个路 ...

  4. 从头认识js-函数表达式

    定义函数的方式有两种: 1.函数声明(特征:函数声明提升,在执行代码之前会先读取函数声明,这就意味着可以把函数声明放在调用它的语句之后) 2.函数表达式(函数表达式与其他表达式一样,使用之前必须先声明 ...

  5. React Native Debug原理浅析

    第一次在segmentfault写博客,很紧张~~~公司项目上ReactNative,之前也是没有接触过,所以也是一边学习一边做项目了,最近腾出手来更新总结了一下RN的Debug的一个小知识点,不是说 ...

  6. cocoapods相关的知识点

    目录 1.安装和卸载cocoapods 安装 卸载 2.常规问题解决思路 50%报错问题可以通过 pod install或者pod update解决 指定swift编译版本 由于墙的原因,可能会ins ...

  7. Java Opencv 实现锐化

    § Laplacian() void cv::Laplacian    (    InputArray     src,                                       O ...

  8. 机器学习 - LSTM应用之sequence generation

    概述 LSTM在机器学习上面的应用是非常广泛的,从股票分析,机器翻译 到 语义分析等等各个方面都有它的用武之地,经过前面的对于LSTM结构的分析,这一节主要介绍一些LSTM的一个小应用,那就是sequ ...

  9. 探究Spring Boot中的接收参数问题与客户端发送请求传递数据

    结合此篇参考Spring框架学习笔记(9)--API接口设计相关知识及具体编码实现 在使用Spring Boot进行接收参数的时候,发现了许多问题,之前一直都很忙,最近才稍微有空研究一下此问题. 网上 ...

  10. vue基础响应式数据

    1.vue 采用 v……vm……m,模式,v---->el,vm---->new Vue(实例),m---->data 数据,让前端从操作大量的dom元素中解放出来. 2.vue响应 ...