python爬取bilibili,下载视频

一. 内容简介

python爬取bilibili,下载视频

二. 软件环境

2.1vsCode

2.2Anaconda

version: conda 22.9.0

2.3代码

链接:https://pan.baidu.com/s/1WuXTso_iltLlnrLffi1kYQ?pwd=1234

三.主要流程

3.1 下载单个视频

代码

import requests
import os
from lxml import etree
import re

def videoDownload1(url_):
    # 设置用户代理,cookie
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
        'Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"
    }

    # 发送请求,得到响应对象
    response_ = requests.get(url_, headers=headers_)

    str_data = response_.text  # 视频主页的html代码,类型是字符串

    # 使用xpath解析html代码,,得到想要的url
    html_obj = etree.HTML(str_data)  # 转换格式类型

    # 获取视频的名称
    res_ = html_obj.xpath('//title/text()')[0]
    # 视频名称的获取
    title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]
    # 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了
    title_ = title_.replace('/', '')
    title_ = title_.replace(' ', '')
    title_ = title_.replace('&', '')
    title_ = title_.replace(':', '')

    # 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串
    url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]

    # 纯视频的url
    video_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 纯音频的url
    audio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 设置跳转字段的headers
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
        'Referer': url_
    }

    # 获取纯视频的数据
    response_video = requests.get(video_url, headers=headers_, stream=True)
    bytes_video = response_video.content
    # 获取纯音频的数据
    response_audio = requests.get(audio_url, headers=headers_, stream=True)
    bytes_audio = response_audio.content

    # 获取文件大小, 单位为KB
    video_size = int(int(response_video.headers['content-length']) / 1024)
    audio_size = int(int(response_audio.headers['content-length']) / 1024)

    # 保存纯视频的文件
    title_1 = title_ + '!'  # 名称进行修改,避免重名
    title_1 = title_1.replace(':', '_')
    
    with open(f'{title_1}.mp4', 'wb') as f:
        f.write(bytes_video)
        # print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')

    with open(f'{title_1}.mp3', 'wb') as f:
        f.write(bytes_audio)
        # print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')

        # 利用第三方工具ffmpeg 合成视频, 需要执行终端命令
    ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"
    # os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')


    folder_path = f"./video/{title_}"  # 替换为你想要创建的文件夹路径

    if not os.path.exists(folder_path):
        os.mkdir(folder_path)
        # print(f"The folder '{folder_path}' already exists.")


    command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{title_}/{title_}.mp4 -loglevel quiet'

    os.system(command)


    # 显示合成文件的大小

    print(f'{title_}  下载完成')

    # 移除纯视频文件,
    os.remove(f'{title_1}.mp4')
    # 移除纯音频文件,
    os.remove(f'{title_1}.mp3')

3.2 下载选集视频

选集视频的播放链接很好找,就是后面的p=几啥的,拼一下就可以拿到整个的播放链接了
代码

import requests
import os
from lxml import etree
import re

# 获取网页源码
def getUrls2(url):
    # 发送请求,得到响应对象
        # 设置用户代理,cookie
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
        'Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"
    }
    response_ = requests.get(url, headers=headers)

    str_data = response_.text  # 视频主页的html代码,类型是字符串

    # 使用xpath解析html代码,,得到想要的url
    html_obj = etree.HTML(str_data)  # 转换格式类型
    urls = []
    # 获取了li的数量,
    lis = html_obj.xpath("//ul[@class='list-box']/li")
    question_mark_index = url.find('?')

    # 如果找到了 '?',就截取该位置之前的子串
    if question_mark_index != -1:
        cleaned_url = url[:question_mark_index]
    else:
        cleaned_url = url
    # print(cleaned_url)
    # 拼接api
    for i in range(1,len(lis)+1):
        # print(i)
        strs = cleaned_url + "?p=" + str(i)
        urls.append(strs)

    # print(content)
    return urls
import requests
import os
from lxml import etree
import re

def videoDownload3(url_,i,name):
    # 设置用户代理,cookie
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
        'Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"
    }

    # 发送请求,得到响应对象
    response_ = requests.get(url_, headers=headers_)

    str_data = response_.text  # 视频主页的html代码,类型是字符串

    # 使用xpath解析html代码,,得到想要的url
    html_obj = etree.HTML(str_data)  # 转换格式类型

    # 获取视频的名称
    res_ = html_obj.xpath('//title/text()')[0]
    # 视频名称的获取
    title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]
    
    fileName = name
    # 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了
    title_ = title_.replace('/', '')
    title_ = title_.replace(' ', '')
    title_ = title_.replace('&', '')
    title_ = title_.replace(':', '')
    title_ = title_.replace('-', '')
    title_ = title_.replace('—', '')
    # 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串
    url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]

    # 纯视频的url
    video_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 纯音频的url
    audio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 设置跳转字段的headers
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
        'Referer': url_
    }

    # 获取纯视频的数据
    response_video = requests.get(video_url, headers=headers_, stream=True)
    bytes_video = response_video.content
    # 获取纯音频的数据
    response_audio = requests.get(audio_url, headers=headers_, stream=True)
    bytes_audio = response_audio.content

    # 获取文件大小, 单位为KB
    video_size = int(int(response_video.headers['content-length']) / 1024)
    audio_size = int(int(response_audio.headers['content-length']) / 1024)

    # 保存纯视频的文件
    title_1 = title_ + '!'  # 名称进行修改,避免重名
    title_1 = title_1.replace(':', '')
    with open(f'{title_1}.mp4', 'wb') as f:
        f.write(bytes_video)
        # print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')

    with open(f'{title_1}.mp3', 'wb') as f:
        f.write(bytes_audio)
        # print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')

        # 利用第三方工具ffmpeg 合成视频, 需要执行终端命令
    ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"
    # os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')

    folder_path = f"./video/{fileName}"  # 替换为你想要创建的文件夹路径
    if not os.path.exists(folder_path):
        os.mkdir(folder_path)
        # print(f"The folder '{folder_path}' already exists.")

    command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{fileName}/{i}.{title_1}.mp4 -loglevel quiet'

    file_path = f"./video/{fileName}/{i}.{title_}.mp4"
    if os.path.exists(file_path):
        pass
    else:
        os.system(command)

    # 显示合成文件的大小

    print(f'{i}.{title_}  下载完成')

    # 移除纯视频文件,
    os.remove(f'{title_1}.mp4')
    # 移除纯音频文件,
    os.remove(f'{title_1}.mp3')

3.3 下载合集视频

合集的里面数据的访问api
在这里插入图片描述
合集里面的数据,就是从这个里面拿到播放id,给json中的处理拿出来,拼接视频播放链接
在这里插入图片描述

代码

# 获取网页源码
def getUrls3(url):
    # 发送请求,得到响应对象
        # 设置用户代理,cookie
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
        'Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"
    }
    # 使用正则表达式提取数字
    pattern = r'\d+'
    numbers = re.findall(pattern, url)
    mid = numbers[0]
    season_id = numbers[1]
    page_num = 1
    url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={page_num}&page_size=30"
    response = requests.get(url)

    if response.status_code == 200:
        json_data = response.json()
        # print(json_data["data"]["page"]["total"])
        total = int(json_data["data"]["page"]["total"])
        page_size = int(json_data["data"]["page"]["page_size"])
        page = int(total / page_size) + 1
        name = json_data["data"]["meta"]["name"]
        # print(total,page)
    
    urls = []
    # 
    for i in range(1,page+1):
        # print(i) 
        url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={i}&page_size=30"
        response = requests.get(url)
        if response.status_code == 200:
            json_data = response.json()
            archives = json_data["data"]["archives"]
            num = 0
            for j in archives:
                bvid = archives[num]["bvid"]
                videoUrl = f"https://www.bilibili.com/video/{bvid}/"
                num = num + 1
                urls.append(videoUrl)
    return urls,name

import requests
import os
from lxml import etree
import re

def videoDownload2(url_,i):
    # 设置用户代理,cookie
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
        'Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"
    }

    # 发送请求,得到响应对象
    response_ = requests.get(url_, headers=headers_)

    str_data = response_.text  # 视频主页的html代码,类型是字符串

    # 使用xpath解析html代码,,得到想要的url
    html_obj = etree.HTML(str_data)  # 转换格式类型

    # 获取视频的名称
    res_ = html_obj.xpath('//title/text()')[0]
    # 视频名称的获取
    title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]
    
    fileName = html_obj.xpath('//h1[@class="video-title"]/text()')[0]
    
    # 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了
    title_ = title_.replace('/', '')
    title_ = title_.replace(' ', '')
    title_ = title_.replace('&', '')
    title_ = title_.replace(':', '')

    # 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串
    url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]

    # 纯视频的url
    video_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 纯音频的url
    audio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 设置跳转字段的headers
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
        'Referer': url_
    }

    # 获取纯视频的数据
    response_video = requests.get(video_url, headers=headers_, stream=True)
    bytes_video = response_video.content
    # 获取纯音频的数据
    response_audio = requests.get(audio_url, headers=headers_, stream=True)
    bytes_audio = response_audio.content

    # 获取文件大小, 单位为KB
    video_size = int(int(response_video.headers['content-length']) / 1024)
    audio_size = int(int(response_audio.headers['content-length']) / 1024)

    # 保存纯视频的文件
    title_1 = title_ + '!'  # 名称进行修改,避免重名
    title_1 = title_1.replace(':', '_')
    with open(f'{title_1}.mp4', 'wb') as f:
        f.write(bytes_video)
        # print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')

    with open(f'{title_1}.mp3', 'wb') as f:
        f.write(bytes_audio)
        # print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')

        # 利用第三方工具ffmpeg 合成视频, 需要执行终端命令
    ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"
    # os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')

    folder_path = f"./video/{fileName}"  # 替换为你想要创建的文件夹路径
    if not os.path.exists(folder_path):
        os.mkdir(folder_path)
        # print(f"The folder '{folder_path}' already exists.")

    command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{fileName}/{i}.{title_}.mp4 -loglevel quiet'

    file_path = f"./video/{fileName}/{i}.{title_}.mp4"
    if os.path.exists(file_path):
        pass
    else:
        os.system(command)

    # 显示合成文件的大小

    print(f'{i}.{title_}  下载完成')

    # 移除纯视频文件,
    os.remove(f'{title_1}.mp4')
    # 移除纯音频文件,
    os.remove(f'{title_1}.mp3')

3.4 多线程

代码

import concurrent.futures
import requests

# 定义一个下载函数
def download_video(URL):
    url, index, name = URL.split(" ", 2)
    videoDownload3(url,index,name)

def THREAD(URLS):
    # 创建线程池,指定线程数量
    max_workers = 10  # 这里设置线程数量,根据需要进行调整
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交下载任务给线程池处理
        futures = [executor.submit(download_video, URL) for URL in URLS]

        # 等待所有任务完成
        for future in concurrent.futures.as_completed(futures):
            try:
                future.result()  # 获取任务的结果(这里不需要结果)
            except Exception as e:
                print(f"An error occurred: {e}")


3.5 结果

url_model = "https://space.bilibili.com/471303350/channel/collectiondetail?sid=1278346 3"
value = url_model.split(' ')
url = value[0]
model = value[1]

if model == "1":
    videoDownload1(url)
    print("下载完成")
if model == "2":
    # 接口分析
    # 点进去的话接口
    # https://www.bilibili.com/video/BV1qW4y1a7fU/?spm_id_from=333.337.search-card.all.click
    # 点击视频的话就这样
    # https://www.bilibili.com/video/BV1qW4y1a7fU?p=1
    # https://www.bilibili.com/video/BV1qW4y1a7fU?p=2&vd_source=de2dcd0f37ff916ec3f8fb83c6366123
    # 可以发现不同的集的接口格式应该是这样的,p = 几就是第几集
    # https://www.bilibili.com/video/BV1qW4y1a7fU?p=1

    # 查看有多少集
    # 一种是视频选集那块会写有多少个
    # 获取源码
    urls = getUrls2(url)
    i = 1
    for index,url in enumerate(urls):
        videoDownload2(url,index)

    print("下载完成")
if model == "3":
    # 接口分析
    # 视频合计每个视频接口没有规律,然后再播放页中网页没有直接的播放链接,所以就用合集页的链接来分析
    # 网页里面的每个链接都是动态加载的,需要访问json数据获取,也或者用虚拟浏览器那种等页面加载完成后访问(这种以后可能会更新,感觉这个有点麻烦),
    # 这里是用json数据做的
    # https://space.bilibili.com/107762251/channel/collectiondetail?sid=877119
    # https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=107762251&season_id=877119&sort_reverse=false&page_num=1&page_size=30
    # https://space.bilibili.com/389199842/channel/collectiondetail?sid=1275285
    # https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=389199842&season_id=1275285&sort_reverse=false&page_num=1&page_size=30
    # 这是两个接口,前面那个数字是用户,后面那个数字代表的是合集,下载的接口其实是股东

    urls,name = getUrls3(url)
    # print(len(urls))
    for index,url in enumerate(urls):
        # print(url)
        videoDownload3(url,index,name)
    # print(urls)
    # 多线程
    # for index,url in enumerate(urls):
    #     URLS.append(url + " " + str(index) + " " + name)
    #     THREAD(URLS)
    

那切里做展示,有些合集下载时候有点bug,还没找到问题,可以下载,但是保存路径有点问题,应该是和命令行冲突了,我就不改了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.6 合集视频更新

原来会出现部分合集显示下载成功,但是文件夹里面没有东西,是因为有些合集名字在命令里面没办法执行,因为一些特殊符号什么的,所以把合集名字手动指定一下下载就可以了,然后多线程加上去,代码如下
拿视频链接的

# 获取网页源码
def getUrls3(url):
    # 发送请求,得到响应对象
        # 设置用户代理,cookie
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
        'Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"
    }
    # 使用正则表达式提取数字
    pattern = r'\d+'
    numbers = re.findall(pattern, url)
    mid = numbers[0]
    season_id = numbers[1]
    page_num = 1
    url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={page_num}&page_size=30"
    response = requests.get(url)

    if response.status_code == 200:
        json_data = response.json()
        # print(json_data["data"]["page"]["total"])
        total = int(json_data["data"]["page"]["total"])
        page_size = int(json_data["data"]["page"]["page_size"])
        page = int(total / page_size) + 1
        name = json_data["data"]["meta"]["name"]
        # print(total,page)
    
    urls = []
    # 
    for i in range(1,page+1):
        # print(i) 
        url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={i}&page_size=30"
        response = requests.get(url)
        if response.status_code == 200:
            json_data = response.json()
            archives = json_data["data"]["archives"]
            num = 0
            for j in archives:
                bvid = archives[num]["bvid"]
                videoUrl = f"https://www.bilibili.com/video/{bvid}/"
                num = num + 1
                urls.append(videoUrl)
    return urls,name

下载视频的

import requests
import os
from lxml import etree
import re

def videoDownload3(url_,index,name):
    # 设置用户代理,cookie
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
        'Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"
    }

    # 发送请求,得到响应对象
    response_ = requests.get(url_, headers=headers_)

    str_data = response_.text  # 视频主页的html代码,类型是字符串

    # 使用xpath解析html代码,,得到想要的url
    html_obj = etree.HTML(str_data)  # 转换格式类型

    # 获取视频的名称
    res_ = html_obj.xpath('//title/text()')[0]
    # 视频名称的获取
    title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]
    # 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了
    title_ = title_.replace('/', '')
    title_ = title_.replace(' ', '')
    title_ = title_.replace('&', '')
    title_ = title_.replace(':', '')

    # 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串
    url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]

    # 纯视频的url
    video_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 纯音频的url
    audio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 设置跳转字段的headers
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
        'Referer': url_
    }

    # 获取纯视频的数据
    response_video = requests.get(video_url, headers=headers_, stream=True)
    bytes_video = response_video.content
    # 获取纯音频的数据
    response_audio = requests.get(audio_url, headers=headers_, stream=True)
    bytes_audio = response_audio.content

    # 获取文件大小, 单位为KB
    video_size = int(int(response_video.headers['content-length']) / 1024)
    audio_size = int(int(response_audio.headers['content-length']) / 1024)

    # 保存纯视频的文件
    title_1 = title_ + '!'  # 名称进行修改,避免重名
    title_1 = title_1.replace(':', '_')
    
    with open(f'{title_1}.mp4', 'wb') as f:
        f.write(bytes_video)
        # print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')

    with open(f'{title_1}.mp3', 'wb') as f:
        f.write(bytes_audio)
        # print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')

        # 利用第三方工具ffmpeg 合成视频, 需要执行终端命令
    ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"
    # os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')


    folder_path = f"./video/{name}"  # 替换为你想要创建的文件夹路径

    if not os.path.exists(folder_path):
        os.mkdir(folder_path)
        # print(f"The folder '{folder_path}' already exists.")


    command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{name}/{index}.{title_}.mp4 -loglevel quiet'

    os.system(command)


    # 显示合成文件的大小

    print(f'{title_}  下载完成')

    # 移除纯视频文件,
    os.remove(f'{title_1}.mp4')
    # 移除纯音频文件,
    os.remove(f'{title_1}.mp3')


多线程

import concurrent.futures
import requests

# 定义一个下载函数
def download_video(URL):
    url, index, name = URL.split(" ", 2)
    videoDownload3(url,index,name)

def THREAD(URLS):
    # 创建线程池,指定线程数量
    max_workers = 10  # 这里设置线程数量,根据需要进行调整
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交下载任务给线程池处理
        futures = [executor.submit(download_video, URL) for URL in URLS]

        # 等待所有任务完成
        for future in concurrent.futures.as_completed(futures):
            try:
                future.result()  # 获取任务的结果(这里不需要结果)
            except Exception as e:
                print(f"An error occurred: {e}")

执行


url_model = "https://space.bilibili.com/389199842/channel/collectiondetail?sid=1275285 3"
value = url_model.split(' ')
url = value[0]
model = value[1]

if model == "1":
    videoDownload1(url)
    print("下载完成")
if model == "2":
    # 接口分析
    # 点进去的话接口
    # https://www.bilibili.com/video/BV1qW4y1a7fU/?spm_id_from=333.337.search-card.all.click
    # 点击视频的话就这样
    # https://www.bilibili.com/video/BV1qW4y1a7fU?p=1
    # https://www.bilibili.com/video/BV1qW4y1a7fU?p=2&vd_source=de2dcd0f37ff916ec3f8fb83c6366123
    # 可以发现不同的集的接口格式应该是这样的,p = 几就是第几集
    # https://www.bilibili.com/video/BV1qW4y1a7fU?p=1

    # 查看有多少集
    # 一种是视频选集那块会写有多少个
    # 获取源码
    urls = getUrls2(url)
    i = 1
    for index,url in enumerate(urls):
        videoDownload2(url,index)

    print("下载完成")
if model == "3":
    # 接口分析
    # 视频合计每个视频接口没有规律,然后再播放页中网页没有直接的播放链接,所以就用合集页的链接来分析
    # 网页里面的每个链接都是动态加载的,需要访问json数据获取,也或者用虚拟浏览器那种等页面加载完成后访问(这种以后可能会更新,感觉这个有点麻烦),
    # 这里是用json数据做的
    # https://space.bilibili.com/107762251/channel/collectiondetail?sid=877119
    # https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=107762251&season_id=877119&sort_reverse=false&page_num=1&page_size=30
    # https://space.bilibili.com/389199842/channel/collectiondetail?sid=1275285
    # https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=389199842&season_id=1275285&sort_reverse=false&page_num=1&page_size=30
    # 这是两个接口,前面那个数字是用户,后面那个数字代表的是合集,下载的接口其实是股东

    urls,name = getUrls3(url)
    name = "qml项目"
    URLS = []
    # print(len(urls))
    for index,url in enumerate(urls):
        # print(url)
        URLS.append(url + " " + str(index+1) + " " + name)
    THREAD(URLS)
    print("全部下载完成!!!")
    # print(urls)
    # for index,url in enumerate(urls):
    #     URLS.append(url + " " + str(index) + " " + name)
    #     THREAD(URLS)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

四.参考

http://t.csdn.cn/6Pt7v 想下载B站视频却不知如何下手?一文教你爬B站!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/99973.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何使用ArcGIS Earth制作地图动画视频

通常情况下,我们所看到的地图都是静态展示,对于信息的传递,视频比图片肯定会更加丰富,所以制作地图动画视频更加有利于信息的传递,这里我们讲解一下ArcGIS Earth 2.0如何制作地图动画视频,希望能对你有所帮…

pytest---添加自定义命令行参数(pytest_addoption )

前言 在目前互联网公司中,都会存在多个测试环境,那么当我们编写的自动化想要在多套测试环境下进行运行时,如何使用?大多数人想到的可能是通过将我们自动化代码中的地址修改成不同环境,但是这时候就会增加一些工作量&am…

MySQL以及版本介绍

一、MySQL的介绍 MySQL数据库管理系统由瑞典的DataKonsultAB公司研发,该公司被Sun公司收购,现在Sun公司又被Oracle公司收购,因此MySQL目前属于 Oracle 旗下产品。 MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用…

DEAP库文档教程五----计算统计

本小结将重点围绕模型在计算统计方面的问题,进行详细的论述 1、Computing Statistics 通常情况下,我们想要在优化过程中编辑数据。Statistic模块可以在任何设计好的目标上改变一些本不可改变的数据。为了达到这个目的,需要使用与工具箱中完…

企业数字化转型的关键技术有哪些?_光点科技

随着科技的不断进步和信息技术的快速发展,企业数字化转型已经成为保持竞争力和适应市场变化的关键举措。在这个数字化时代,企业需要借助先进的技术来优化业务流程、提升效率,以及更好地满足客户需求。以下是企业数字化转型过程中的关键技术。…

Modbus转Profinet网关在大型自动化仓储项目应用案例

在自动化仓储项目中,Modbus是一种常见的通信协议,用于连接各种设备,例如传感器、PLC和人机界面。然而,Modbus协议只支持串行通信,并且数据传输速度较慢。为了提高通信效率和整体系统性能,许多大型仓储项目选…

Docker环境搭建Prometheus实验环境

环境: OS:Centos7 Docker: 20.10.9 - Community Centos部署Docker 【Kubernetes】Centos中安装Docker和Minikube_云服务器安装docker和minikube_DivingKitten的博客-CSDN博客 一、拉取Prometheus镜像 ## 拉取镜像 docker pull prom/prometheus ## 启动p…

02_块元素和行内元素的使用

一、HTML块元素和行内元素的使用 1、块元素: div标签 定义和用法&#xff1a; 标签块元素,表示一块内容,div标签可以把文档分割为独立的、不同的部分可以使用css设置宽高默认是占用一整快 例如: <html><body><!-- 块元素:div标签 --><div style"he…

C++面试题(陆)-数据库(一)

目录 数据库 1.1SQL 1.1.1 介绍一下数据库分页 1.1.2 介绍一下SQL中的聚合函数 1.1.3 表跟表是怎么关联的&#xff1f; 1.1.4 说一说你对外连接的了解 1.1.6 SQL中怎么将行转成列&#xff1f; 1.1.7 谈谈你对SQL注入的理解 1.1.8 将一张表的部分数据更新到另一张表&am…

STM32 RTC实验

RTC时钟简介 STM32F103的实时时钟&#xff08;RTC&#xff09;是一个独立的定时器。 STM32的RTC模块拥有一组连续计数的计数器&#xff0c;在相对应的软件配置下&#xff0c;可提供时钟日历的功能。 修改计数器的值可以重新设置系统的当前时间和日期。 RTC模块和时钟配置系统…

uniapp项目实战系列(4):服务的异步请求,请求服务的二次封装

目录 系列往期文章&#xff08;点击跳转&#xff09;uniapp项目实战系列(1)&#xff1a;导入数据库&#xff0c;启动后端服务&#xff0c;开启代码托管&#xff08;点击跳转&#xff09;uniapp项目实战系列(2)&#xff1a;新建项目&#xff0c;项目搭建&#xff0c;微信开发工具…

七、高并发内存池--Page Cache

七、高并发内存池–Page Cache 7.1 PageCache的工作原理 PageCache是以span的大小(以页为单位)和下标一一对应为映射关系的哈希桶&#xff0c;下标是几就说明这个哈希桶下挂的span的大小就是几页的&#xff0c;是绝对映射的关系。因为PageCache也是全局只有唯一一个的&#x…

线上批量查询物流导出到表格的操作指南

现在的生活中&#xff0c;我们经常需要查询包裹物流信息。如果一次性需要查询多个快递单号的物流信息&#xff0c;手动一个一个查询会非常麻烦。今天&#xff0c;我将向大家分享一个简单实用的方法&#xff0c;可以批量查询物流并导出到表格&#xff0c;方便随时查看。 首先&am…

js 正则表达式 验证 :页面中一个输入框,可输入1个或多个vid/pid,使用英文逗号隔开...

就是意思一个输入框里面&#xff0c;按VID/PID格式输入,VID和PID最大长度是4,最多50组 1、页面代码 <el-form ref"ruleForm" :model"tempSet" :rules"rules" label-position"right"> <!-- 最多 50组&#xff0c;每组9个字符…

【USRP】集成化仪器系列1 :信号源,基于labview实现

USRP 信号源 1、设备IP地址&#xff1a;默认为192.168.10.2&#xff0c;请勿 修改&#xff0c;运行阶段无法修改。 2、天线输出端口是TX1&#xff0c;请勿修改。 3、通道&#xff1a;0 对应RF A、1 对应 RF B&#xff0c;运行 阶段无法修改。 4、中心频率&#xff1a;当需要…

LinuxUbuntu安装OpenWAF

Linux&Ubuntu安装OpenWAF 官方GitHub地址 介绍 OpenWAF&#xff08;Web Application Firewall&#xff09;是一个开源的Web应用防火墙&#xff0c;用于保护Web应用程序免受各种网络攻击。它通过与Web服务器集成&#xff0c;监控和过滤对Web应用程序的流量&#xff0c;识…

JDK源码解析-LinkedList

1. LinkedList类 1.1 LinkedList类定义&数据结构 定义 LinkedList是一种可以在任何位置进行高效地插入和移除操作的有序序列&#xff0c;它是基于双向链表实现的。 数据结构 基础知识补充 单向链表&#xff1a; element&#xff1a;用来存放元素 next&#xff1a;用来…

Redis 7 第六讲 主从模式(replica)

🌹🌹🌹 此篇开始进入高级篇范围(❤艸`❤) 理论 即主从复制,master以写为主,Slave以读为主。当master数据变化的时候,自动将新的数据异步同步到其它slave数据库。 使用场景 读写分离 容灾备份数据备份水平扩容主从架构 演示案例 注:masterauth、replicaof主…

FTP文件传输服务器

目录 一、FTP协议两种工作模式 二、FTP数据两种传输模式 三、FTP用户分类 四、VSFTP配置案例 4.1匿名开放模式 4.2本地用户模式 4.3虚拟用户模式 五、实验总结 一、FTP协议两种工作模式 主动模式&#xff1a; 1、客户端主动向ftp服务器发送控制连接&#xff0c;三次握手控制连接…

go锁-互斥锁

go锁-互斥锁 sema初始值是0&#xff0c;waitershift等待协程的数量 正常枷锁&#xff1a; 尝试CAS直接加锁&#xff0c;通过原子包给lockerd 为枷锁 若无法直接获取&#xff0c;进行多次自旋尝试&#xff0c;未获取到的锁的g &#xff0c;多次执行空语句&#xff0c;多次尝试…