最新!使用Python爬取蓝奏云文件下载直链并下载,支持批量爬取,已封装为函数,可直接使用(含注释、库的使用解释)

  • Post author:
  • Post category:python




程序说明

本程序不借助第三方网站来获取蓝奏云直链,那样没意思,且程序流程已经过分块化处理(多函数),方便理解和阅读。程序使用了requests、re、lxml库,来请求、解析数据。具有一定学习价值,对Python爬虫技术的熟悉度有益

程序总计170行(含空格、换行);5个自创函数 ; 调用三个库 ;


写于 2021/8/20 可应对蓝奏云最新反爬



lan_download Python 库最后一次更新位于 2022/07/17


本文章完全原创,未经许可,不允转载!!!



原作者链接:https://blog.csdn.net/qq_45429426



原作者名称:漫游感知





已经打包为 Python 库 可通过Pip下载

pip install lan-download==0.1.29


使用方法(更多请查阅 README)

import lan_download

lan_download.__save_param = {'save_dir': 'youy path'}      # 定义文件保存目录(注意!请在start_download() 方法调用前定义!负责默认为 [./] )

lan_download.start_download(url='xxxx', show_info=True)     # show_info=False 时不打印任何信息



程序源码&Python版本(已过期,请通过Pip下载最新包查阅)

Python version:3.7x

#encoding:utf-8
#原作者:https://blog.csdn.net/qq_45429426
#需要提前安装库,安装方法已写,并用[]括起
import requests                         #第三方库,使用requests库来发送网络请求 [pip install requests]
from lxml import etree                  #第三方库,使用lxml提取网页中的信息,来构建下一次请求的数据  [pip install lxml]
from re import findall as re_findall    #标准库,使用re正则匹配网页中的关键信息  [无需额外安装,python自带]

def download(url):
    '''
    起始处
    :param url: 需要下载的链接 str
    :return: 调用解析或者error
    '''
    url_host = 'https://' + url.split('/')[2]        #解决个性域名的问题
    get_html_text_headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'ccept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'max-age=0',
        'cookie': 'codelen=1; pc_ad1=1',
        'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
        'sec-ch-ua-mobile': '?0',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'cross-site',
        'sec-fetch-user': '?1',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    html = requests.get(url=url, headers=get_html_text_headers)
    if html.status_code == 200:
        #检测网页请求是否成功
        ajax_headers_info_get(initial_url=url, url_host=url_host, html=html.text)
    else:
        return print('无法请求此链接,可能链接不存在或网络错误')

def ajax_headers_info_get(initial_url,url_host,html):
    '''
    解析关键头信息, /fu?。。。。。
    :param html: 网页源码
    :param initial_url : 原链接
    :param url_host : 链接中的host,解决个性域名问题
    :return: 头信息之一
    '''
    handled_html = etree.HTML(html)
    param_fu_info = handled_html.xpath('/html/body/div[3]/div[2]/div[4]/iframe/@src')[0]      #获取重要参数
    file_title = handled_html.xpath('/html/body/div[3]/div[1]/text()')[0]                     #获取文件名称,用于最后的保存环节
    ajax_request_url = url_host + param_fu_info                                               #构建第一次转折的请求链接
    Qporm = str(param_fu_info).replace('/fu?','') + ':'
    ajax_form_info_get(initial_url=initial_url,url=ajax_request_url,Qporm=Qporm,title=file_title)
    return True

def ajax_form_info_get(initial_url,url,Qporm,title):
    '''
    接近尾声,获取请求ajax的headers and form
    :param initial_url:初始链接,防止盗链
    :param url:请求链接fu的URL
    :param Qporm:请求时的表单,fu中提取
    :return:ajax headers and form
    '''
    get_ajax_form_headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'ccept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'max-age=0',
        'cookie': 'codelen=1; pc_ad1=1',
        'referer': str(initial_url),
        'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
        'sec-ch-ua-mobile': '?0',
        'sec-fetch-dest': 'iframe',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'same-origin',
        'sec-fetch-user': '?1',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    fu_response_html = requests.get(url=url, headers=get_ajax_form_headers, params=Qporm)
    handled_fu_html = str(fu_response_html.text)
    form_ajaxdata = re_findall("var ajaxdata = (.*?);", handled_fu_html)[0]
    try:
        kernel_form_postdown = re_findall("var pdownload = (.*?);", handled_fu_html)[0]
        # 狡猾,var后值会变化,导致匹配不到值,故我们try,因为他的变化量只有这两个
    except IndexError:
        kernel_form_postdown = re_findall('var postdown = (.*?);', handled_fu_html)[0]

    data = {
        'action': 'downprocess',
        'signs': form_ajaxdata,
        'sign': kernel_form_postdown,
        'ves': '1',
        'websign': None,
        'websignkey': 'wwi3'
    }
    headers_param = ['https://' + initial_url.split('/')[2],url]        #0--> 头中origin参数 ; 1---> 头中referer参数
    return get_file_url(headers_param=headers_param,data=data,title=title)

def get_file_url(headers_param,data,title):
    '''
    提取文件直链,并专递给下载函数
    :param headers_param: 构建ajax请求头的必要动态参数
    :param data: 请求ajax需要使用的表单数据
    :param title: 第一个函数就已经获取的文件名称,传递给下载函数作为文件名称
    :return: 使用下载函数下载文件
    '''
    ajax_url = headers_param[0] + '/' + 'ajaxm.php'
    ajax_headers = {
        'accept': 'application/json, text/javascript, */*',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'content-length': '152',
        'content-type': 'application/x-www-form-urlencoded',
        'cookie': 'codelen=1; pc_ad1=1',
        'origin': headers_param[0],
        'referer': headers_param[1],
        'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
        'sec-ch-ua-mobile': '?0',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest'
    }
    file_url_html = requests.post(url=ajax_url,data=data,headers=ajax_headers)
    file_url_html_json = file_url_html.json()
    file_url = str(file_url_html_json["dom"]+ '/' + 'file' + '/' + file_url_html_json["url"]).replace(r'\/','/')     #解析ajax请求返回的json数据,并转为文件的下载直链
    print(file_url)                               #打印文件直链
    download_file(file_url=file_url,title=title)

def download_file(file_url,title):
    '''
    下载文件的关键函数
    :param file_url: 文件直链
    :param title: 文件名称
    :return: 提醒某某文件下载完成
    '''
    download_file_headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'max-age=0',
        'cookie': 'down_ip=1',
        'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
        'sec-ch-ua-mobile': '?0',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'none',
        'sec-fetch-user': '?1',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    request_file_data = requests.get(url=file_url,headers=download_file_headers)
    file_data = request_file_data.content                #请求并获取文件二进制数据
    with open('./' + title,'wb') as save_file:
        #保存文件数据
        save_file.write(file_data)
        save_file.close()
    return print('{}  文件保存完成'.format(title))

if __name__ == '__main__':
    #支持批量爬取并下载
    goal_url = input('请输入一条蓝奏云文件链接(链接不要含密码,输入ls则从[./all_url.txt]批量下载):')
    if goal_url == 'ls':
        try:
            with open('./all_url.txt','r') as all_url:
                url_list = all_url.read().replace('\n','').split(',')
                all_url.close()
                print(url_list)
            for goal_url in url_list:
                download(url=goal_url)
        except FileNotFoundError:
            print('请创建all_list.txt文件,每条链接间用英文半角逗号[ , ]隔开!!!')
    else:
        download(url=goal_url)

此文章写于2021/8/20


点这里,看笔者往期蓝奏云直链爬虫


支持作者


在这里插入图片描述

在这里插入图片描述



版权声明:本文为qq_45429426原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。