整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

用html代码编写的免费软件下载和安装教程

一个好的编辑器我们可以方便的开发项目,编写代码,配置和管理我们的项目。所以我们开始编写html代码之前需要搭建开发环境。

基于html项目的开发和代码编写现在网上有很多编辑器,也有免费的,也有收费的编辑器。基于在Windows系统环境下开发和编写html代码最简单的编辑器就是Windows自带的记事本,我们可以使用记事本编辑html代码。

使用记事本编写html的步骤是首先新建一个文本文档,按照html的语法规则编写相关的代码和保存文件,然后把文件的后缀名改为.html,使用电脑上的浏览器打开就可以查看我们代码的运行结果。

虽然记事本也能编写html代码,但是效率不高也不方便,所以我们使用专业的编辑器来开发项目,编写代码和管理项目。

常用html代码编写的免费软件有HBuilderX,vs code,Sublime Text 等等。

HBuilderX官网下载地址:

https://www.dcloud.io/hbuilderx.html

vs code的官网下载地址:

https://code.visualstudio.com/

Sublime Text官网下载地址:

http://www.sublimetext.com/

我们以后的教程都使用HBuilderX,所以下面为了同学们的学习方便,对HBuilderX的下载和安装做详细的教程。


一,下载

首先访问HBuilderX的官网网址:

https://www.dcloud.io/hbuilderx.html

打开上面的HBuilderX下载网址后点击页面上download,在弹出的对话框里选择适合自己电脑的HBuilderX版本下载。

在Windows10环境下下载后的文件是一个压缩的.zip文件。



二,安装

鼠标右击下载下来的压缩文件进行解压。

解压完成后是一个名为HBuilderX的文件夹。

解压完成后鼠标双击HBuilderX文件夹:

双击运行名为HBuilderX.exe的应用程序文件即可启动HBuilderX编辑器:

因为HBuilderX是一个绿色软件所以没有桌面快捷方式和开始菜单快速启动程序,我们可以右击HBuilderX.exe文件创建桌面快捷方式。



小百科:

绿色软件指一类小型软件,多数为免费软件,最大特点是软件无需安装便可使用,可存放于闪存中,移除后也不会将任何记录留在本机计算机上。通俗点讲绿色软件就是指不用安装,下载直接可以使用的软件。绿色软件不会在注册表中留下注册表键值,所以相对一般的软件来说,绿色软件对系统的影响几乎没有,所以是很好的一种软件类型。



三,新建项目

HBuilderX编辑器初次启动时的默认界面是下图所示:

按照下图所示可以创建一个新的名为demo1空白项目:

名为demo1的空白项目创建成功后的界面如下图所示:

接下来在刚我们新建的demo1项目下创建名为helloworld的html文件

鼠标右击创建的demo1项目选择新建在选择.html文件:

在弹出的对话框里填入html文件的名称:

编写一段代码:

运行:

在浏览器上观察效果:




好了,到这里html的开发环境搭建和HBuilderX的安装教程结束了。

下面再给大家教一下怎样修改HBuilderX的主题风格,HBuilderX自身提供了修改软件主题的功能,使用者可以自身需求和喜好修改HBuilderX的风格。在喜欢自己喜欢的环境下做开发也是令人羡慕的一件事。

按照一下步骤可以修改HBuilderX的主题,默认主题是绿柔,我们可以改成雅黑,雅蓝或者自定义主题:

雅黑主题:

雅蓝主题:


好了本节全部内容全部结束了,希望我准备的内容对你有所帮助

你的支持是我的最大动力,若觉得我的教程还可以对你有帮助为我点赞加关注!谢谢!

迎搜索我的公众号:小道黑客


每天分享更多黑客技能,工具及体系化视频教程


这里最近参与CIS大会,看到一款自动化渗透工具 Ary,特点是汇聚了各种可以调用的工具。


介绍



工具地址 https://github.com/TeraSecTeam/ary

POC收集 https://github.com/TeraSecTeam/poc-collection

Ary是一个集各种渗透工具于一体的工具,不过看起来还是一个开发中的版本,试用了一遍,感觉还不错。

注意需要使用centos,好像ubuntu会报一些错误。


文件结构介绍


├── ary #二进制文件

├── configs #配置文件夹

├── input

├── log #日志记录

├── output #输出目录

├── pocs #poc文件夹,可以用自己的POC或者网上的poc

├── README.md 使用说明

└── streams #执行流所在文件夹,自己定义组合


核心功能介绍



信息收集

  1. 空间搜索引擎收集
  2. 爬虫类工具收集
  3. 爬虫类+存储类收集

工具联动

  1. 爬虫类+扫描类工具(Poc验证)
  2. 存储类+扫描类(Poc验证)
  3. 工具联动自定义+自动化


安装



1.安装所有的工具引擎,执行命令后,将会自动下载第三方的渗透工具,如xray。也可以预先不下载,在执行命令的时候如果缺少某个第三方工具会自动下载。

./ary --vulnscan --engine all --update -v

./ary --assertscan --engine all --update -v

2.chrome 的安装(爬虫需要)

配置yum谷歌的源:

vi /etc/yum.repos.d/google.repo

将下面这段粘贴进文件

[google]
name=Google-x86_64
baseurl=http://dl.google.com/linux/rpm/stable/x86_64
enabled=1
gpgcheck=0
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub

配置完之后,执行以下bash命令,安装google-chrome

yum update

yum install google-chrome-stable

google-chrome --version


配置文件



默认加载配置为带有settings.ini的文件configs/example.settings.ini文件为配置示例,可以修改其内容,如加入网络搜索引擎的token


1.目录设置

可以设置各输入和输出目录


2.第三方工具来源


xray下载地址及下载输出位置


3.信息收集来源


包含rad,crawlergo,gospider等信息收集工具



4.空间搜索引擎配置


主要是配置fofa,shodan,censys的token或API key



使用体验


1.网络空间搜索

支持shodan、fofa、censys等空间搜索引擎,使用相关搜索需要在配置文件configs/example.settings.ini中配置相应的token。

相关命令

./ary --netsearch --engine shodan --keyword dedecms -v --limit 10

./ary --netsearch --engine shodan --keyword "tomcat country:"US"" -v --limit 10

./ary --netsearch --engine fofa --keyword redis -v --limit 10

./ary --netsearch --engine fofa --keyword "protocol=socks4 && banner="0x5a"" -v --limit 10

./ary --netsearch --engine censys --keyword redis -v --limit 1000


如使用shodan进行搜索

配置token(需要自己注册shodan的账号,获取token)

cd configs[root@centos configs]# vim example.settings.ini

搜索dedecms框架, 限制10条

[root@centos kk]# ./ary --netsearch --engine shodan --keyword dedecms -v --limit 10


结果如下



搜索结果默认保存在sqlite中,在配置文件中配置,公开版默认配置sqlite



使用sqlite3工具 SQLiteStudio查看,可看到结果已保存到本地data.db中



采用shodan语法搜索, 搜索国家为美国的tomcat


[root@centos kk]# ./ary --netsearch --engine shodan --keyword "tomcat country:"US"" -v --limit 10


使用fofa基本语法搜索

[root@centos kk]# ./ary --netsearch --engine fofa --keyword redis -v --limit 10


根据特征搜索sock4代理,关键词为

protocol=socks4 && banner="0x5a"

./ary --netsearch --engine fofa --keyword "protocol=socks4 && banner="0x5a"" -v --limit 10

结果


评论

censys的结果不精确,没有相应的端口

推荐shodan和fofa


2.资产扫描


基于在线靶场测试http://testhtml5.vulnweb.com


基于ARL资产扫描

ARL是freebuf能力中心开源的一套资产扫描系统(https://github.com/TophantTechnology/ARL),提供docker版,有前端界面,基于ARL可以方便进行资产扫描和可视化


这里采用ARL 资产侦查灯塔系统

(https://hub.docker.com/r/tophant/arl/tags?page=1&ordering=last_updated)

直接使用docker版本的ARL,登录进去后改密码


在配置文件里配置ARL


ARL token在登录后可以从cookie获取

打开F12查看cookie

PS: 在启动docker的时候可以配置固定token,


如果需要一直使用建议进行配置 之后在配置文件的[assertscan]中进行相应配置


通过ary调用ARL进行资产扫描

ARL:

./ary --assertscan --engine arl --input指定文件

./ary --assertscan --engine arl --url指定url,可指定多个url,url之间用逗号隔开

资产扫描相关命令

# 启动一个任务

# 查找子域名

./ary --assertscan --engine arl --url www.aaa.com -v --condition subdomain

./ary --assertscan --engine arl --url www.aaa.com,www.bbb.com -v --condition subdomain

# 查找子域名 指定文件

./ary --assertscan --engine arl --input targets.txt -v --condition subdomain

# 查找子域名 指定输出文件名

./ary --assertscan --engine arl --url www.aaa.com -v --condition subdomain --output arl.csv

# 查找端口

./ary --assertscan --engine arl --input targets.txt -v --condition portscan

# 获取任务结果

./ary --assertscan --engine arl -v --fetch-result --keyword 5fd321f0a4a557000fb2a574

# 获取任务结果 - 加载文件

./ary --assertscan --engine arl -v --fetch-result --input arl.csv


扫描测试

./ary --assertscan --engine arl --url http://testhtml5.vulnweb.com -v --condition subdomain

登录ARL后台,x.x.x.x:5003, 输入账号密码,可以看到在ARL中已经启动了任务

获取扫描完毕的结果

[root@centos kk]# ./ary --assertscan --engine arl -v --fetch-result --keyword 5ff67b77ac258f000ccf4de2

或者直接把文件作为输入

[root@centos kk]# ./ary --assertscan --engine arl -v --fetch-result --input output/arl_1_2021-01-07T03\:09\:43Z.txt.csv


端口扫描

./ary --assertscan --engine arl --input vulnweb.com -v --condition portscan

端口扫描仅限于top100,不太好用,不能指定端口


3.爬虫类

./ary --assertscan --engine rad --url http://testphp.vulnweb.com/ -v

./ary --assertscan --engine gospider --url http://testphp.vulnweb.com/ -v

./ary --assertscan --engine crawlergo --url http://testphp.vulnweb.com/ -v


使用rad进行爬取

[root@centos kk]# ./ary --assertscan --engine rad --url http://testphp.vulnweb.com/ -v

如果没有rad,会自动下载并开始爬取

rad配置文件rad_config.yml在当前目录生成爬取过程

保存结果在

output/rad_1_2021-01-07T06:47:23Z.txt


使用gospider进行爬取

./ary --assertscan --engine gospider --url http://testphp.vulnweb.com/ -v

如果没有gospider,会自动下载并开始爬取

结果保存在output/gospider文件夹下

2021-01-07 06:50:00,846 - [assertscan#143] - HIGHLIGHT - saved to output/gospider

gospider比rad在参数上更加详细


使用crawlgo进行爬取

如果没有crawlgo,会自动下载并开始爬取

[root@centos kk]# ./ary --assertscan --engine crawlergo --url http://testphp.vulnweb.com/ -vCrawlgo的也比较详细,但是速度较gospider和rad慢

结果保存在output文件夹下

2021-01-07 06:57:40,600 - [assertscan#165] - HIGHLIGHT - saved to output/crawlergo_1_2021-01-07T06:56:05Z.txt


4.漏洞扫描


# 对目标进行扫描

./ary --vulnscan --url http://testphp.vulnweb.com/ --engine xray -v

# 对目标进行被动扫描(rad+xray)

./ary --vulnscan --engine xray --url http://testphp.vulnweb.com/ -v --passive

# 对文件中的目标进行被动扫描

./ary --vulnscan --engine xray --input target.txt -v --passive

# 读取数据库中的数据进扫描

./ary --vulnscan --engine xray --keyword tomcat -v

./ary --vulnscan --engine xray --keyword tomcat -v --crawl


直接调用xray进行扫描

./ary --vulnscan --url http://testphp.vulnweb.com/ --engine xray -v

如果没有xray,会自动下载并开始爬取

xray的配置文件config.yaml默认在当前文件夹生成

下载完后保存在在thirdpartys文件夹下

xray结果以json格式保存在output目录下


调用xray进行被动扫描

./ary --vulnscan --engine xray --url http://testphp.vulnweb.com/ -v --passive

效果不好,可能是使用姿势不对,待进一步探索


xray+gospider分开跑

效果不错

在两个终端中运行程序:

运行xray, xray在7778端口监听,被动扫描模式

./ary --vulnscan --engine xray --port 7778 --background -v

运行gospider,将流量转发到7778端口给xray进行扫描,使用xray对go spider的内容进行扫描

./ary --assertscan --engine gospider --url http://testphp.vulnweb.com/ -v --passive --port 7778

效果如下


xray+rad分开跑

运行rad,将流量转发到7778给xray扫描,效果不错


xray+crawelgo分开跑

运行crawelgo,扫描的数量多一点,但是相对来说慢一点

5.POC使用

PoC 漏洞验证

POC可自行在POC收集 https://github.com/TeraSecTeam/poc-collection项目中寻找

./ary --pocscan --input redis.txt --poc redis -v

./ary --pocscan --url xx.xx.xx.xx --poc ./pocs/redis -v

./ary --pocscan --poc tomcat --keyword tomcat -v

./ary --pocscan --keyword redis --poc redis -v

./ary --pocscan --keyword redis --poc redis -v --limit 1 --dumppcap redis

./ary --pocscan --keyword thinkphp --poc thinkphp_rce2 -v --limit 20 --dumppcap thinkphp

# 写到数据库

./ary --pocscan --url xx.xx.xx.xx --poc redis -v --limit 2 --upload

redis POC 效果


针对单个网站打poc

[root@centos kk]# ./ary --pocscan --url 122.xx.xx.xx --poc redis -v

针对数据库中的关键词打POC

[root@centos kk]# ./ary --pocscan --keyword redis --poc redis -v


对数据包详细分析

执行流尝试使用录包功能,录包之后为pcap格式,可以用wireshark打开


6.Stream模块使用

使用这个模块可以自定义过程。


使用steam进行POC验证

自定义过程的配置在./streams/streams.yaml

./ary -v --stream --input streams.yaml --keyword "redis 未授权访问漏洞"

可以看到名称为redis 未授权访问漏洞,故在命令行中输入该关键词`--keyword "redis 未授权访问漏洞"`

将会使用shodan进行redis搜集,并且使用pocs目录下的redis.py POC进行利用尝试


效果如下


使用stream进行漏洞挖掘

也可以进行漏洞扫描,指定xray引擎,非passive方式扫描,


关键词为test testphp.vulnweb.com


./ary -v --stream --input streams.yaml --keyword "test testphp.vulnweb.com"


即可进行xray扫描


效果 如下


Trouble shooting

1、API报错


2021-01-07 02:28:23,382 - [netsearch#217] - DEBUG - fofa mail : hxxxxxl@163.com, secret : 238ebxxxxxxxxxxxxxxxxxx2440

2021-01-07 02:28:23,387 - [database#28] - DEBUG - using database : sqlite

2021-01-07 02:28:23,396 - [netsearch#249] - DEBUG - https://fofa.so/api/v1/search/all?email=hxxxxxl@163.com&key=238ebxxxxxxxxxxxxxxxxxx2440&qbase64=aXA9IjguOC144Ljgi&size=1

2021-01-07 02:28:24,597 - [netsearch#253] - ERROR - 401 Unauthorized, make sure 1.email and apikey is correct 2.FOFA coin is enough.


解决方法: 注册账号,获取token,并在配置文件中填入相应的token


2、端口被占用


解决方法

[root@centos kk]# ./ary --kill --engine xray --port 7777 -v

总结

- 快速的资产收集和工具联动操作


- 在获取某个POC和框架信息的情况下,可以快速聚合所需要的网站并且调用需要的工具进行扫描


- 适用于平时进行漏洞挖掘


- 数据库的使用可以发挥更多的想象力,其他版本在数据方面应该会更友好


- 体验下来,公开版适用于渗透测试前中期的自动化工作,辅助在测试中更快地寻找到突破点


作者:挣扎的小小

来源:https://www.freebuf.com/sectool/260698.html

、项目概述

1.项目背景

有一天,我突然想找点事做,想起一直想学但是没有学的C语言,就决定来学一下。可是怎么学呢?看书的话太无聊,报班学呢又快吃土了没钱,不如去B站看看?果然,关键字C语言搜索,出现了很多C语言的讲课视频:

B站C语言讲课视频节选


B站https://www.bilibili.com/是一个很神奇的地方,简直就是一个无所不有的宝库,几乎可以满足你一切的需求和视觉欲。不管你是想看动画、番剧 ,还是游戏、鬼畜 ,亦或科技和各类教学视频 ,只要你能想到的,基本上都可以在B站找到。对于程序猿或即将成为程序猿的人来说,B站上的编程学习资源是学不完的,可是B站没有提供下载的功能,如果想保存下载在需要的时候看,那就是一个麻烦了。我也遇到了这个问题,于是研究怎么可以实现一键下载视频,最终用Python这门神奇的语言实现了。

当然了,项目实现之后,不是想学习编程、而是想看其他类别视频的小伙伴也可以用这款工具进行下载了。


2.环境配置

这次项目不需要太多的环境配置,最主要的是有ffmpeg(一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序)并设置环境变量就可以了。ffmpeg主要是用于将下载下来的视频和音频进行合并形成完整的视频。

下载ffmpeg

可点击https://download.csdn.net/download/CUFEECR/12234789或进入官网http://ffmpeg.org/download.html进行下载,并解压到你想保存的目录。

设置环境变量:

(1)复制ffmpeg的bin路径,如xxx\ffmpeg-20190921-ba24b24-win64-shared\bin

(2)此电脑右键点击属性,进入控制面板\系统和安全\系统

(3)点击高级系统设置→进入系统属性弹窗→点击环境变量→进入环境变量弹窗→选择系统变量下的Path→点击编辑点击→进入编辑环境变量弹窗

(4)点击新建→粘贴之前复制的bin路径

(5)点击确定,逐步保存退出

动态操作示例如下:


ffmpeg 设置环境变量

除了ffmpeg,还需要安装pyinstaller库用于程序打包。可用以下命令进行安装:

pip install pyinstaller

如果遇到安装失败或下载速度较慢,可换源:

pip install pyinstaller -i https://pypi.doubanio.com/simple/

二、项目实施

1.导入需要的库

import json
import os
import re
import shutil
import ssl
import time
import requests
from concurrent.futures import ThreadPoolExecutor
from lxml import etree

导入的库包括用于爬取和解析网页的库,还包括创建线程池的库和进行其他处理的库,大多数都是Python自带的,如有未安装的库,可使用pip install xxx命令进行安装。

2.设置请求参数

# 设置请求头等参数,防止被反爬
headers = {
    'Accept': '*/*',
    'Accept-Language': 'en-US,en;q=0.5',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36'
}
params = {
    'from': 'search',
    'seid': '9698329271136034665'
}

设置请求头等参数,减少被反爬的可能。

3.基本处理

def re_video_info(text, pattern):
    '''利用正则表达式匹配出视频信息并转化成json'''
    match = re.search(pattern, text)
    return json.loads(match.group(1))


def create_folder(aid):
    '''创建文件夹'''
    if not os.path.exists(aid):
        os.mkdir(aid)


def remove_move_file(aid):
    '''删除和移动文件'''
    file_list = os.listdir('./')
    for file in file_list:
        # 移除临时文件
        if file.endswith('_video.mp4'):
            os.remove(file)
            pass
        elif file.endswith('_audio.mp4'):
            os.remove(file)
            pass
        # 保存最终的视频文件
        elif file.endswith('.mp4'):
            if os.path.exists(aid + '/' + file):
                os.remove(aid + '/' + file)
            shutil.move(file, aid)

主要包括两方面的基本处理,为正式爬取下载做准备:

  • 利用正则表达式提取信息
    通过requests库请求得到请求后的网页,属于文本,通过正则表达式提取得到关于将要下载的视频的有用信息,便于后一步处理。
  • 文件处理
    将下载视频完成后的相关文件进行处理,包括删除生成的临时的音视频分离的文件和移动最终视频文件到指定文件夹。

4.下载视频

def download_video_batch(referer_url, video_url, audio_url, video_name, index):
    '''批量下载系列视频'''
    # 更新请求头
    headers.update({"Referer": referer_url})
    # 获取文件名
    short_name = video_name.split('/')[2]
    print("%d.\t视频下载开始:%s" % (index, short_name))
    # 下载并保存视频
    video_content = requests.get(video_url, headers=headers)
    print('%d.\t%s\t视频大小:' % (index, short_name),
          round(int(video_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
    received_video = 0
    with open('%s_video.mp4' % video_name, 'ab') as output:
        headers['Range'] = 'bytes=' + str(received_video) + '-'
        response = requests.get(video_url, headers=headers)
        output.write(response.content)
    # 下载并保存音频
    audio_content = requests.get(audio_url, headers=headers)
    print('%d.\t%s\t音频大小:' % (index, short_name),
          round(int(audio_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
    received_audio = 0
    with open('%s_audio.mp4' % video_name, 'ab') as output:
        headers['Range'] = 'bytes=' + str(received_audio) + '-'
        response = requests.get(audio_url, headers=headers)
        output.write(response.content)
        received_audio += len(response.content)
    return video_name, index


def download_video_single(referer_url, video_url, audio_url, video_name):
    '''单个视频下载'''
    # 更新请求头
    headers.update({"Referer": referer_url})
    print("视频下载开始:%s" % video_name)
    # 下载并保存视频
    video_content = requests.get(video_url, headers=headers)
    print('%s\t视频大小:' % video_name, round(int(video_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
    received_video = 0
    with open('%s_video.mp4' % video_name, 'ab') as output:
        headers['Range'] = 'bytes=' + str(received_video) + '-'
        response = requests.get(video_url, headers=headers)
        output.write(response.content)
    # 下载并保存音频
    audio_content = requests.get(audio_url, headers=headers)
    print('%s\t音频大小:' % video_name, round(int(audio_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
    received_audio = 0
    with open('%s_audio.mp4' % video_name, 'ab') as output:
        headers['Range'] = 'bytes=' + str(received_audio) + '-'
        response = requests.get(audio_url, headers=headers)
        output.write(response.content)
        received_audio += len(response.content)
    print("视频下载结束:%s" % video_name)
    video_audio_merge_single(video_name)

这部分包括系列视频的批量下载和单个视频的下载,两者的大体实现原理近似,但是由于两个函数的参数有差别,因此分别实现。在具体的实现中,首先更新请求头,请求视频链接并保存视频(无声音),再请求音频链接并保存音频,在这个过程中得到相应的视频和音频文件的大小。

5.视频和音频合并成完整的视频

def video_audio_merge_batch(result):
    '''使用ffmpeg批量视频音频合并'''
    video_name = result.result()[0]
    index = result.result()[1]
    import subprocess
    video_final = video_name.replace('video', 'video_final')
    command = 'ffmpeg -i "%s_video.mp4" -i "%s_audio.mp4" -c copy "%s.mp4" -y -loglevel quiet' % (
        video_name, video_name, video_final)
    subprocess.Popen(command, shell=True)
    print("%d.\t视频下载结束:%s" % (index, video_name.split('/')[2]))


def video_audio_merge_single(video_name):
    '''使用ffmpeg单个视频音频合并'''
    print("视频合成开始:%s" % video_name)
    import subprocess
    command = 'ffmpeg -i "%s_video.mp4" -i "%s_audio.mp4" -c copy "%s.mp4" -y -loglevel quiet' % (
        video_name, video_name, video_name)
    subprocess.Popen(command, shell=True)
    print("视频合成结束:%s" % video_name)

这个过程也是批量和单个分开,大致原理差不多,都是调用subprogress模块来生成子进程,Popen类来执行shell命令,由于已经将ffmpeg加入环境变量,所以shell命令可以直接调用ffmpeg来合并音视频。

6.3种下载方式的分别实现

def batch_download():
    '''使用多线程批量下载视频'''
    # 提示输入需要下载的系列视频对应的id
    aid = input('请输入要下载的视频id(举例:链接https://www.bilibili.com/video/av91748877?p=1中id为91748877),默认为91748877\t')
    if aid:
        pass
    else:
        aid = '91748877'
    # 提示选择清晰度
    quality = input('请选择清晰度(1代表高清,2代表清晰,3代表流畅),默认高清\t')
    if quality == '2':
        pass
    elif quality == '3':
        pass
    else:
        quality = '1'
    acc_quality = int(quality) - 1
    # ssl模块,处理https请求失败问题,生成证书上下文
    ssl._create_default_https_context = ssl._create_unverified_context
    # 获取视频主题
    url = 'https://www.bilibili.com/video/av{}?p=1'.format(aid)
    html = etree.HTML(requests.get(url, params=params, headers=headers).text)
    title = html.xpath('//*[@id="viewbox_report"]/h1/span/text()')[0]
    print('您即将下载的视频系列是:', title)
    # 创建临时文件夹
    create_folder('video')
    create_folder('video_final')
    # 定义一个线程池,大小为3
    pool = ThreadPoolExecutor(3)
    # 通过api获取视频信息
    res_json = requests.get('https://api.bilibili.com/x/player/pagelist?aid={}'.format(aid)).json()
    video_name_list = res_json['data']
    print('共下载视频{}个'.format(len(video_name_list)))
    for i, video_content in enumerate(video_name_list):
        video_name = ('./video/' + video_content['part']).replace(" ", "-")
        origin_video_url = 'https://www.bilibili.com/video/av{}'.format(aid) + '?p=%d' % (i + 1)
        # 请求视频,获取信息
        res = requests.get(origin_video_url, headers=headers)
        # 解析出视频详情的json
        video_info_temp = re_video_info(res.text, '__playinfo__=(.*?)</script><script>')
        video_info = {}
        # 获取视频品质
        quality = video_info_temp['data']['accept_description'][acc_quality]
        # 获取视频时长
        video_info['duration'] = video_info_temp['data']['dash']['duration']
        # 获取视频链接
        video_url = video_info_temp['data']['dash']['video'][acc_quality]['baseUrl']
        # 获取音频链接
        audio_url = video_info_temp['data']['dash']['audio'][acc_quality]['baseUrl']
        # 计算视频时长
        video_time = int(video_info.get('duration', 0))
        video_minute = video_time // 60
        video_second = video_time % 60
        print('{}.\t当前视频清晰度为{},时长{}分{}秒'.format(i + 1, quality, video_minute, video_second))
        # 将任务加入线程池,并在任务完成后回调完成视频音频合并
        pool.submit(download_video_batch, origin_video_url, video_url, audio_url, video_name, i + 1).add_done_callback(
            video_audio_merge_batch)
    pool.shutdown(wait=True)
    time.sleep(5)
    # 整理视频信息
    if os.path.exists(title):
        shutil.rmtree(title)
    os.rename('video_final', title)
    try:
        shutil.rmtree('video')
    except:
        shutil.rmtree('video')


def multiple_download():
    '''批量下载多个独立视频'''
    # 提示输入所有aid
    aid_str = input(
        '请输入要下载的所有视频id,id之间用空格分开\n举例:有5个链接https://www.bilibili.com/video/av89592082、https://www.bilibili.com/video/av68716174、https://www.bilibili.com/video/av87216317、\nhttps://www.bilibili.com/video/av83200644和https://www.bilibili.com/video/av88252843,则输入89592082 68716174 87216317 83200644 88252843\n默认为89592082 68716174 87216317 83200644 88252843\t')
    if aid_str:
        pass
    else:
        aid_str = '89592082 68716174 87216317 83200644 88252843'
    if os.path.exists(aid_str):
        shutil.rmtree(aid_str)
    aids = aid_str.split(' ')
    # 提示选择视频质量
    quality = input('请选择清晰度(1代表高清,2代表清晰,3代表流畅),默认高清\t')
    if quality == '2':
        pass
    elif quality == '3':
        pass
    else:
        quality = '1'
    acc_quality = int(quality) - 1
    # 创建文件夹
    create_folder(aid_str)
    # 创建线程池,执行多任务
    pool = ThreadPoolExecutor(3)
    for aid in aids:
        # 将任务加入线程池
        pool.submit(single_download, aid, acc_quality)
    pool.shutdown(wait=True)
    time.sleep(5)
    # 删除临时文件,移动文件
    remove_move_file(aid_str)


def single_download(aid, acc_quality):
    '''单个视频实现下载'''
    # 请求视频链接,获取信息
    origin_video_url = 'https://www.bilibili.com/video/av' + aid
    res = requests.get(origin_video_url, headers=headers)
    html = etree.HTML(res.text)
    title = html.xpath('//*[@id="viewbox_report"]/h1/span/text()')[0]
    print('您当前正在下载:', title)
    video_info_temp = re_video_info(res.text, '__playinfo__=(.*?)</script><script>')
    video_info = {}
    # 获取视频质量
    quality = video_info_temp['data']['accept_description'][acc_quality]
    # 获取视频时长
    video_info['duration'] = video_info_temp['data']['dash']['duration']
    # 获取视频链接
    video_url = video_info_temp['data']['dash']['video'][acc_quality]['baseUrl']
    # 获取音频链接
    audio_url = video_info_temp['data']['dash']['audio'][acc_quality]['baseUrl']
    # 计算视频时长
    video_time = int(video_info.get('duration', 0))
    video_minute = video_time // 60
    video_second = video_time % 60
    print('当前视频清晰度为{},时长{}分{}秒'.format(quality, video_minute, video_second))
    # 调用函数下载保存视频
    download_video_single(origin_video_url, video_url, audio_url, title)


def single_input():
    '''单个文件下载,获取参数'''
    # 获取视频aid
    aid = input('请输入要下载的视频id(举例:链接https://www.bilibili.com/video/av89592082中id为89592082),默认为89592082\t')
    if aid:
        pass
    else:
        aid = '89592082'
        # 提示选择视频质量
    quality = input('请选择清晰度(1代表高清,2代表清晰,3代表流畅),默认高清\t')
    if quality == '2':
        pass
    elif quality == '3':
        pass
    else:
        quality = '1'
    acc_quality = int(quality) - 1
    # 调用函数进行下载
    single_download(aid, acc_quality)

在一般情形下,下载的需求包含3种情况:

(1)单个视频的下载:
只有一个视频,没有和它属于同一个系列的其他视频,如下图


单个视频下载


此时,除了右下方的相关推荐中的视频,没有其他视频,右上方只有弹幕列表、没有视频列表。为了代码的复用,将单个视频下载时提示用户输入需求的代码单独提取出来作为single_input(),下载的函数另外作为single_download(aid, acc_quality)函数实现,在该函数中:
通过视频链接如https://www.bilibili.com/video/av89592082解析网页,得到相应的字符串并转化成json,如下:


视频信息json转化


字符串json格式化可使用https://www.sojson.com/editor.html进行在线转化。
获取到视频的标题、根据输入确定的视频质量、持续时长、视频链接和音频链接,并调用download_video_single()函数下载该视频。

(2)多个视频的下载:
这里,多个视频之间是没有关系的,多个视频的下载实际上是先获取到所有的aid,并进行循环,对每个视频链接传入参数调用单个视频下载的函数即可。同时设立线程池,大小为3,既不会对资源有太大的要求,也能实现多任务、提高下载效率。

(3)系列视频的下载
此时,多个视频属于同一系列,如https://www.bilibili.com/video/av91748877是一个课程系列,如下:


系列视频


显然,此时右上方有视频列表,标明了有65个子视频,每个视频用p标识,如第2个视频就是https://www.bilibili.com/video/av91748877?p=2。对于所有视频,先获取到视频的相关信息,再加入进程池进行下载,并在任务结束之后回调函数video_audio_merge_batch()合并音视频,并进行文件整理。

7.主函数

def main():
    '''主函数,提示用户进行三种下载模式的选择'''
    download_choice = input('请输入您需要下载的类型:\n1代表下载单个视频,2代表批量下载系列视频,3代表批量下载多个不同视频,默认下载单个视频\t')
    # 批量下载系列视频
    if download_choice == '2':
        batch_download()
    # 批量下载多个单个视频
    elif download_choice == '3':
        multiple_download()
    # 下载单个视频
    else:
        single_input()


if __name__ == '__main__':
    '''调用主函数'''
    main()

主函数中实现3种下载方式对应的函数的分别调用。

三、项目分析和说明

1.结果测试

对3种方式进行测试的效果如下:

项目测试一:单个视频测试


项目测试二:系列视频测试


项目测试三:多个不同视频测试


3种下载情景的测试效果均较好,下载速度也能与一般的下载速度相媲美。
代码可点击https://download.csdn.net/download/CUFEECR/12243122https://github.com/corleytd/Python_Crawling/blob/master/bilibili_downloader_1.py进行下载。


改进说明

B站网站也一直在变化,所以对于下载可能也会有一些变化,所以将改进的地方在下面列举出来:

(1)网址参数变化
举例说明:
这段时间发现B站一个视频系列的链接变成https://www.bilibili.com/video/BV1x7411M74h?p=65,即是无规律的字符串(可能是经过某种算法编码或加密得到的),现在从链接中不能得到视频(系列)的aid,这时候可以借助浏览器工具抓包查看数据来找到该视频的aid,如下:

B站视频aid转bvid


在左侧寻找stat开头的请求,后边的参数即为aid,该请求api的完整链接为https://api.bilibili.com/x/web-interface/archive/stat?aid=91748877,所以可以直接在该链接中获取aid,也可以查看该请求的具体内容,可以看到第一个数据就是aid,我们也可以看到随机字符串就是bvid,可能是建立了aid和bvid的一一映射,找到aid就可以正常下载了。

2.软件打包

在命令行中,使路径位于代码所在路径运行

pyinstaller bilibili_downloader_1.py

打印

136 INFO: PyInstaller: 3.6
137 INFO: Python: 3.7.4
138 INFO: Platform: Windows-10-10.0.18362-SP0
140 INFO: wrote xxxx\Bili_Video_Batch_Download\bilibili_downloader_1.spec
205 INFO: UPX is not available.
209 INFO: Extending PYTHONPATH with paths
['xxxx\\Bili_Video_Batch_Download',
 'xxxx\\Bili_Video_Batch_Download']
210 INFO: checking Analysis
211 INFO: Building Analysis because Analysis-00.toc is non existent
211 INFO: Initializing module dependency graph...
218 INFO: Caching module graph hooks...
247 INFO: Analyzing base_library.zip ...
5499 INFO: Caching module dependency graph...
5673 INFO: running Analysis Analysis-00.toc
5702 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
  required by xxx\python\python37\python.exe
6231 INFO: Analyzing xxxx\Bili_Video_Batch_Download\bilibili_downloader_1.py
7237 INFO: Processing pre-safe import module hook   urllib3.packages.six.moves
10126 INFO: Processing pre-safe import module hook   six.moves
14287 INFO: Processing module hooks...
14288 INFO: Loading module hook "hook-certifi.py"...
14296 INFO: Loading module hook "hook-cryptography.py"...
14936 INFO: Loading module hook "hook-encodings.py"...
15093 INFO: Loading module hook "hook-lxml.etree.py"...
15097 INFO: Loading module hook "hook-pydoc.py"...
15099 INFO: Loading module hook "hook-xml.py"...
15330 INFO: Looking for ctypes DLLs
15334 INFO: Analyzing run-time hooks ...
15339 INFO: Including run-time hook 'pyi_rth_multiprocessing.py'
15344 INFO: Including run-time hook 'pyi_rth_certifi.py'
15355 INFO: Looking for dynamic libraries
15736 INFO: Looking for eggs
15737 INFO: Using Python library xxx\python\python37\python37.dll
15757 INFO: Found binding redirects:
[]
15776 INFO: Warnings written to xxxx\Bili_Video_Batch_Download\build\bilibili_downloader_1\war
n-bilibili_downloader_1.txt
15942 INFO: Graph cross-reference written to xxxx\Bili_Video_Batch_Download\build\bilibili_dow
nloader_1\xref-bilibili_downloader_1.html
15967 INFO: checking PYZ
15968 INFO: Building PYZ because PYZ-00.toc is non existent
15968 INFO: Building PYZ (ZlibArchive) xxxx\Bili_Video_Batch_Download\build\bilibili_downloade
r_1\PYZ-00.pyz
16944 INFO: Building PYZ (ZlibArchive) xxxx\Bili_Video_Batch_Download\build\bilibili_downloade
r_1\PYZ-00.pyz completed successfully.
16980 INFO: checking PKG
16981 INFO: Building PKG because PKG-00.toc is non existent
16981 INFO: Building PKG (CArchive) PKG-00.pkg
17030 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
17034 INFO: Bootloader xxx\python\python37\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
17034 INFO: checking EXE
17035 INFO: Building EXE because EXE-00.toc is non existent
17035 INFO: Building EXE from EXE-00.toc
17037 INFO: Appending archive to EXE xxxx\Bili_Video_Batch_Download\build\bilibili_downloader_
1\bilibili_downloader_1.exe
17046 INFO: Building EXE from EXE-00.toc completed successfully.
17053 INFO: checking COLLECT
17053 INFO: Building COLLECT because COLLECT-00.toc is non existent
17055 INFO: Building COLLECT COLLECT-00.toc

出现INFO: Building EXE from EXE-00.toc completed successfully. 即打包成功。在当前路径下找到distbuild目录下的bilibili_downloader_1目录下的bilibili_downloader_1.exe,即是打包后的软件。点击打开即可进行选择和输入,开始下载相应视频。测试示例如下:

项目打包下载测试


bilibili_downloader_1.exe的同级目录下可以看到下载保存的视频。


3.改进分析

该项目是小编进行B站视频下载的首次尝试,难免有很多不足,在实现的过程中和后期的总结中,可以看出还存在一些问题:

  • 还不能下载B站上的所有视频,目前局限于各种普通视频教程,不能下载直播视频、大会员番剧等,可以在后期进一步优化;
  • 代码过于繁琐,有不少功能类似的重复代码,可以进一步简化、提高代码的复用性;
  • 没有采取适当的措施应对B站的反爬,可能会因为请求过多而无法正常下载。
    可以在后期进行优化,使整个程序更加健壮。

4.合法性说明

  • 本项目的出发点是方便地下载B站上的学习视频,可以更好地学习各类教程,这对程序猿来说也是一种福利,但是绝不用与其他商业目的,所有读者可以参考执行思路和程序代码,但不能用于恶意和非法目的(恶意频繁下载视频、非法盈利等),如有违者请自行负责。
  • 本项目在实施的过程中可能参考了其他大佬的实现思路,如有侵犯他人利益,请联系更改或删除。
  • 本项目是B站视频批量下载系列的第一篇,有很多尚待改进的地方,后期会继续更新,欢迎各位读者交流指正,以期不断改进。

上一篇:HTML 符号
下一篇:HTML5的表单设计