【python学习笔记】:实现网页视频自动下载并保存

如何使用python爬虫实现网页视频自动下载并保存:

  • 使用python爬取页面,然后自动下载视频,但是这样会有一个问题,我并不是需要所有视频,有些是垃圾视频不需要下载,python似乎还没法做到识别我对哪些视频是有价值的,所以这一步人工绕不开,我选择直接把目标视频的详情页直接右键另存为本地html文件,随后再用python批量处理这些本地的html文件。

  • 解析html文件取出视频的标题和下载url,按格式存为本地json

  • 读取json,循环下载整个list的视频,并按配置给视频命名

目标功能点

  • 递归读取html列表

  • 研究html内格式、解密url

  • 保存解析产物为json

  • 读取json下载保存视频

功能点代码    

这一步可以将每一个html文件的路径从Downloads文件夹取出来。

def get_all_path():    global train_path, all_path, labels    train_path, all_path, labels = "./Downloads", [], []    # 递归获取文件夹内文件列表    def get_label_and_wav(path, file):        dirs = os.listdir(path)        for a in dirs:            # print(a)            # # 是否为文件夹            # print(os.path.isfile(path + "/" + a))            if os.path.isfile(path + "/" + a):                all_path.append(dirs)                if file != "":                    labels.append(file)            else:                get_label_and_wav(str(path) + "/" + str(a), a)            # 循环遍历这个文件夹        return all_path, labels    # 第一步、加载文件,获取文件路径以及标签    [all_path, labels] = get_label_and_wav(train_path, "")    loop_parse_html(paths=all_path[0])

循环html文件列表

有一个小坑是python生成json会自动使用单引号,不符合json标准,需要做下ensure_ascii配置,见注释​​​​​​​

# 循环html路径列表,解析每一个链接和标题存入jsondef loop_parse_html(paths):    global res_json    res_json = []    for index in range(len(paths)):        v = paths[index]        v_len = len(v)        # 当前后缀四位        v_end = v[v_len - 4:len(v)]        # 跳过非html结尾文件        if v_end == "html":            parse_html(position=index, path=f"{train_path}/{paths[index]}")            sleep(0.1)    # 这里将ensure_ascii配置为false,不然会强制存为单引号格式的json,不符合标准,也会导致中文是编码显示    res_json = json.dumps(res_json, ensure_ascii=False)    # 创建一个本地json文件存入结果    file = open('urls.json', 'w')    file.write(str(res_json))    file.close()
 
 

重点,解析单个html文件

实际上这里也可以直接用request库从网络爬取,区别不大,只是一个取本地一个取请求,本质结果都是返回一个html文件传入xpath返回结构化的html对象而已,也就是下面的html_tree,由于我的场景特殊需要筛选,才用这种本地html的形式。

另外通过分析html内容,发现下载链接是一个js生成的a标签的前部分,也就是类似于下方,关键的href链接是被编码过的,也需要处理下。

<a href="http://21312jhg312@#$@#$@#$">
 
 

编码就是前端的enencodeURIComponent,查了下python里可以使用unquote库来解码

from urllib.parse import unquote  # url解码库,类似于js里的decodeURIComponent

注:xpath是一个流行的html解析库,不过在此处也需要特殊处理,留意代码注释的标签闭合问题,通过自己创建一个html解析器来解决xpath对未闭合标签不识别的问题。

# 解析单个htmldef parse_html(position, path):    position = position + 1    print(f'开始第{position}次解析:{path}')    # 因为现在html存在未闭合的标签,如title标签,xpath解析会报错,因为闭合不完整    # 所以这里自己创建一个html解析器parser    parser = etree.HTMLParser(encoding="utf-8")    # 使用etree解析返回一个html结构对象    html_tree = etree.parse(path, parser=parser)    # 文本形式可直接打印的html,此处暂时不用,用xpath结构化解析    # result = etree.tostring(html_tree, pretty_print=True, encoding="utf-8").decode("utf-8")    # print(result)    print(f'解析下载链接')    # 通过解析获取目标视频链接a标签,实际是一个a标签被加密了    aim_video_url = html_tree.xpath('// *[ @ class = "demo-class"] / script / text()')[0]    # 再次处理链接格式    # 找到a标签首位,截取出来    a_start = aim_video_url.find('("')    a_end = aim_video_url.find('")')    aim_video_url = aim_video_url[a_start + 2:a_end]    # 解码a标签    aim_video_url = unquote(aim_video_url)    # 取出a标签的href属性就是下载链接了,这里是字符串就用截取了,不用xpath解析    href_start = aim_video_url.find('https')    href_end = aim_video_url.find('>')    aim_video_url = aim_video_url[href_start:href_end]    print(f"链接解析完成:{aim_video_url}")    print(f'解析标题')    # 目标标题    aim_title = html_tree.xpath('/html//title/text()')[0]    # 处理下标题格式,去掉无用的字符、空格、回车换行等    aim_title = aim_title.replace(" ", "")    aim_title = aim_title.replace("\n", "")    useless_str_start = aim_title.find("powerbyxxx")    aim_title = aim_title[0:useless_str_start]    print(f"标题解析完成:{aim_title}\n")    write_json_file(title=aim_title, link=aim_video_url)

存入全局的json变量,在最开始的循环html列表结束后,json变量会被写入本地json文件​​​​​​​

# 将标题和下载链接按键值对存入json文件,供下载脚本读取def write_json_file(title, link):    temp = {
   
           "title": f"{title}",        "link": f"{link}"    }    res_json.append(temp)

进入下载保存流程

这一块其实比较简单

读取json本地配置​​​​​​​

def get_video(index):    if index > len(json_res) - 1:        print(f'下载完毕,一共下载了{index}次')        quit(200)    else:        print(f'开始第{index + 1}次下载')        save_video(index)

def main():    with open('urls.json', encoding='utf-8') as res:        print('开始读取json配置')        # 把json配置读出来保存到全局变量        global json_res        json_res = json.load(res)        get_video(index=0)

循环下载,组合文件名将视频存入指定目录

这里做了一个简单的请求时间随机发起​​​​​​​

def save_video(index):    url = json_res[index].get("link")    title = json_res[index].get("title")    video_content = requests.get(url).content    with open('./output/' + title + '.mp4', 'wb') as f:        f.write(video_content)    print(f"第{index + 1}次下载完成\n")    ran = random.randint(0, 10)+random.randint(0, 10)/10+random.randint(0, 10)/100    # 随机休息1-10秒两位小数的时间    print(f'休息{ran}秒~')    # sleep(ran)    get_video(index + 1)

到这一步就全部完成

猜你喜欢

转载自blog.csdn.net/Jiangziyadizi/article/details/128842076