Python爬虫实战第三例【三】(下)

news/2024/7/19 12:25:24 标签: python, 爬虫, 开发语言

零.前情提要:

没有看上一章的小伙伴,建议先去看上一章,避免有些知识点不连贯

地址:Python爬虫实战第三例【三】【上】-CSDN博客

在上一章,我们经过分析.m3u8文件和.ts文件后,成功爬取到了所有.ts文件的文件名,并且成功下载了.ts文件,但是在上一节中我们只是下载了一个.ts文件,并没有实现批次的.ts文件下载。

接下来,我们就要进行批次爬取.ts文件,并且将它们组合在一起!

准备好了吗?跟随作者一起,走进爬虫的海洋吧!

一.批次爬取.ts文件

由于我们现在爬取.ts文件的函数,一次只能爬去一个.ts文件,那我们是不是可以在函数外面放一个for循环来实现批次爬取.ts文件呢?当然可以了!!

代码如下:

python">    #将ts_list转换为带有序号的列表,方便.ts文件的重命名,用来保持顺序一致!
    ts_list = list(enumerate(ts_list))
    for ts in ts_list:
        down_video(ts)

效果图:

但是这样是有一个问题的,那就是爬取完第一个.ts文件后,程序重新构造一大串.get请求并发送,这中间消耗了大量资源,并且可以发现效率很慢!!!如果共有1000个.ts文件,我们需要爬取三十分钟!!这显然不是我们想要看到的!!

学过线程的小伙伴可能想到了,这不是单线程造成的吗?对的,所以改进的话我们只需要改成多线程就可以啦!!

为此,我们先要导入线程池

python">from multiprocessing.pool import ThreadPool

代码如下:

python">    #创建线程池
    pool = ThreadPool(100)
    #利用map函数给线程分配工作
    pool.map(down_video,enumerate(ts_list))

效果图:

 可以看到效率飞起!!效率大概提升了1000%!!!

(与个人CPU有关,CPU线程数越多效率越高)

二.重新爬取失败的文件

不过在爬取过程中,难免会有一些.ts文件因为网络波动的问题,导致超时,从而报错,这显然不是我们想看到的,为此我们该怎么办呢?

作者的想法是,创建一个检查函数,在执行完爬取.ts文件后,检查是否有文件没有被爬取!

代码如下:

python">#漏下的.ts文件列表
fil_list = []
#检查标志
file_flag = False


def down_video(item):
    #全局变量标志,用来表示是第一次爬取.ts文件,还是爬取漏下的.ts文件!
    global file_flag
    #对item进行解包,提取出ts文件和ts文件索引
    index,ts = item[0],item[1]
    #拼接文件序号
    if 0 <= index <=9:
        index = "000" + str(index)
    elif 10 <= index <= 99:
        index = "00" + str(index)
    elif 100 <= index <= 999:
        index = "0" + str(index)
    else:
        index = str(index)
    #爬取视频URL
    URL = "https://s8.fsvod1.com/20230703/J6BHjLy3/1500kb/hls/"
    #请求头
    headers = {
        "authority":"s8.fsvod1.com",
        "method":"GET",
        "path":f"/20221207/10692_4308abda/2000k/hls/{ts}",
        "scheme":"https",
        "Accept":r"*/*",
        "Accept-Encoding":"gzip,deflate,br,zstd",
        "Accept-Language":"zh-CN,zh;q=0.9",
        "Origin":"https://test3.gqyy8.com:4438",
        "Sec-Ch-Ua":'"Chromium";v="122","Not(A:Brand";v="24","Google Chrome";v="122"',
        "Sec-Ch-Ua-Mobile":"?0",
        "Sec-Ch-Ua-Platform":"Windows",
        "Sec-Fetch-Dest":"empty",
        "Sec-Fetch-Mode":"cors",
        "Sec-Fetch-Site":"cross-site",
        "User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/122.0.0.0Safari/537.36"
    }
    #拼接视频url
    URL = URL + "/" + ts
    try:
        r = requests.get(url=URL,headers=headers,timeout=10)
        with open(f"{os.getcwd()}/爬取数据/" + index + ".ts", "wb") as file:
            file.write(r.content)
    except Exception as e:
        if not file_flag:
            fil_list.append([int(index),ts])
        print(index,"写入失败,原因",e,sep="->")
        return
    if file_flag:
        fil_list.remove(item)
    print(index,"写入成功.",sep="->")

def check():
    print("开始检查")
    global file_flag
    file_flag = True
    while fil_list:
        pool = ThreadPool(100)
        results = pool.map(down_video, fil_list)
        pool.close()
        pool.join()
    print("检查完毕")


if __name__ == "__main__":
    ts_list = get_ts_txt()
    create_filedir()
    #创建线程池
    pool = ThreadPool(100)
    #利用map函数给线程分配工作
    pool.map(down_video,enumerate(ts_list))
    #检查函数
    check()

 效果图:

也是成功全部爬取啦!!

我累个逗啊!居然有2426.ts文件!!

三.合成.ts文件

其实将所有.ts文件拼凑在一起,有很多方法,在这里作者给出一种相对简单的方法

1.首先进入cmd切换到我们的“爬取数据”路径下,如下图所示:

 2.接下来输入指令:

copy /b *.ts my_video.ts

结果如下图所示:

最后,去我们的文件夹里面找“my_video.ts”即可播放啦!!

 

芜湖,可以看玲芽啦~~ 

四.全部代码

python">import requests
import os
import re
from multiprocessing.pool import ThreadPool

#漏下的.ts文件列表
fil_list = []
#检查标志
file_flag = False

def get_ts_txt():
    #4请求URL
    url = "https://s8.fsvod1.com/20230703/J6BHjLy3/1500kb/hls/index.m3u8"
    #请求头
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
    }

    reponse = requests.get(url=url,headers=headers)

    get_txt = reponse.text
    #正则匹配出.ts后缀数据
    ts_files = re.findall(r"\b\w+\.ts\b",get_txt)

    #将.ts数据写入到文件中中
    with open("get_ts.txt","w") as file:
        for i in ts_files:
            i = i + "\n"
            file.write(i)

    print("获取ts文件成功.")
    return ts_files

def create_filedir():
    path = os.getcwd() + "/爬取数据"
    if os.path.exists(path):
        print("\\爬取视频文件夹已存在,本次不创建.")
    else:
        os.mkdir(path)
        print("创建\\爬取文件夹成功.")

def down_video(item):
    #全局变量标志,用来表示是第一次爬取.ts文件,还是爬取漏下的.ts文件!
    global file_flag
    #对item进行解包,提取出ts文件和ts文件索引
    index,ts = item[0],item[1]
    #拼接文件序号
    if 0 <= index <=9:
        index = "000" + str(index)
    elif 10 <= index <= 99:
        index = "00" + str(index)
    elif 100 <= index <= 999:
        index = "0" + str(index)
    else:
        index = str(index)
    #爬取视频URL
    URL = "https://s8.fsvod1.com/20230703/J6BHjLy3/1500kb/hls/"
    #请求头
    headers = {
        "authority":"s8.fsvod1.com",
        "method":"GET",
        "path":f"/20221207/10692_4308abda/2000k/hls/{ts}",
        "scheme":"https",
        "Accept":r"*/*",
        "Accept-Encoding":"gzip,deflate,br,zstd",
        "Accept-Language":"zh-CN,zh;q=0.9",
        "Origin":"https://test3.gqyy8.com:4438",
        "Sec-Ch-Ua":'"Chromium";v="122","Not(A:Brand";v="24","Google Chrome";v="122"',
        "Sec-Ch-Ua-Mobile":"?0",
        "Sec-Ch-Ua-Platform":"Windows",
        "Sec-Fetch-Dest":"empty",
        "Sec-Fetch-Mode":"cors",
        "Sec-Fetch-Site":"cross-site",
        "User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/122.0.0.0Safari/537.36"
    }
    #拼接视频url
    URL = URL + "/" + ts
    try:
        r = requests.get(url=URL,headers=headers,timeout=10)
        with open(f"{os.getcwd()}/爬取数据/" + index + ".ts", "wb") as file:
            file.write(r.content)
    except Exception as e:
        if not file_flag:
            fil_list.append([int(index),ts])
        print(index,"写入失败,原因",e,sep="->")
        return
    if file_flag:
        fil_list.remove(item)
    print(index,"写入成功.",sep="->")

def check():
    print("开始检查")
    global file_flag
    file_flag = True
    while fil_list:
        pool = ThreadPool(100)
        results = pool.map(down_video, fil_list)
        pool.close()
        pool.join()
    print("检查完毕")

if __name__ == "__main__":
    ts_list = get_ts_txt()
    create_filedir()
    #创建线程池
    pool = ThreadPool(100)
    #利用map函数给线程分配工作
    pool.map(down_video,enumerate(ts_list))
    #检查函数
    check()

ps:复制上直接就可以爬取哦~


http://www.niftyadmin.cn/n/5408646.html

相关文章

8、Redis-Jedis、Lettuce和一个Demo

目录 一、Jedis 二、Lettuce 三、一个Demo Java集成Redis主要有3个方案&#xff1a;Jedis、Lettuce和Redisson。 其中&#xff0c;Jedis、Lettuce侧重于单例Redis&#xff0c;而Redisson侧重于分布式服务。 项目资源在文末 一、Jedis 1、创建SpringBoot项目 2、引入依赖 …

Spring启动后默认注入的ConfigurableEnvironment,可用于获取系统属性

ConfigurableEnvironment对象 Spring Boot在启动时会自动注入默认的ConfigurableEnvironment对象。ConfigurableEnvironment是Spring Framework中的接口,它代表了Spring应用程序的环境配置,包括配置属性、配置文件等信息。 在Spring Boot应用程序启动时,Spring Boot会自动创…

无人机/飞控--ArduPilot、PX4学习历程记录(1)

本篇博客用来记录个人学习记录&#xff0c;存放各种文章链接、视频链接、学习历程、实验过程和结果等等.... 最近在整无人机项目&#xff0c;接触一下从来没有接触过的飞控...(听着就头晕)&#xff0c;本人纯小白。 目录 PX4、Pixhawk、APM、ArduPilot、Dronecode Dronekit…

小迪安全32WEB 攻防-通用漏洞文件上传二次渲染.htaccess变异免杀

#知识点&#xff1a; 1、文件上传-二次渲染 2、文件上传-简单免杀变异 3、文件上传-.htaccess 妙用 4、文件上传-PHP 语言特性 #详细点&#xff1a; 1、检测层面&#xff1a;前端&#xff0c;后端等 2、检测内容&#xff1a;文件头&#xff0c;完整性&#xff0c…

在线客服系统部署ssl开启https无法自动获取提示消息解决办法

▇ 增加https无法收发消息&#xff1a; 严格按照教程修改 1./站点目录/public目录下,修改index.php define(whost,wss://kf.tpym.cn); define(wport,443); 2./站点目录/service 目录下,修改config.php // websocket 端口&#xff0c;客服系统网页会连这个端口 $websocket_…

Redis的应用场景以及常见问题(持续更新)

一、使用场景 1&#xff0c;在大型的秒杀库存扣减&#xff0c;app首页流量高峰&#xff0c;很容易将传统的关系型数据库&#xff08;mysql,oracle等&#xff09;给压垮 2&#xff0c;还有很多没必要持久化的数据&#xff0c;比如说短信验证码&#xff0c;点赞数等 3&#xff0c…

装饰器模式详解

8.9.6 装饰器模式 ​ 装饰器模式是一种结构型模式&#xff0c;主要是给一个类添加更多功能&#xff1b; 示例代码&#xff1a; #include <iostream> #include <string>// 抽象基类&#xff1a;文本修饰器 class TextDecorator { public:virtual std::string dec…

Minio容器化部署并整合SpringBoot

1、启动minio容器 docker run -p 9000:9000 -p 9090:9090 --name minio -d --restartalways -e MINIO_ACCESS_KEYminio -e MINIO_SECRET_KEYminio -v /usr/local/minio/data:/data -v /usr/local/minio/config:/root/.minio minio/minio server /data --console-addr…