查看: 111|回复: 3

Python批量下载与自动压缩实现:多线程、加密打包与定时任务

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在日常工作中,频繁处理文件批量下载和自动压缩打包是常见的重复劳动。本文将分享一套基于 Python 的完整自动化方案,涵盖从 URL 列表、网页图片到 GitHub 目录的下载,以及压缩整个文件夹、筛选特定类型文件、甚至带密码加密打包的功能,最后提供一条龙流水线和定时任务调度,帮助开发者和运维人员提升效率。所有代码均可直接运行,注释清晰,适合根据实际需求定制。

一、批量下载模块设计

首先封装一个通用的 BatchDownloader 类,支持多线程并发下载、断点续传和失败重试。核心参数包括保存目录和最大线程数。
  1. import requests
  2. import os
  3. from concurrent.futures import ThreadPoolExecutor, as_completed
  4. import time
  5. class BatchDownloader:
  6.     """批量下载器"""
  7.     def __init__(self, save_dir="downloads", max_workers=5):
  8.         self.save_dir = save_dir
  9.         self.max_workers = max_workers
  10.         os.makedirs(save_dir, exist_ok=True)
  11.     def download_one(self, url, filename=None):
  12.         """下载单个文件,支持断点续传"""
  13.         try:
  14.             if not filename:
  15.                 filename = url.split("/")[-1] or "index.html"
  16.             filepath = os.path.join(self.save_dir, filename)
  17.             headers = {}
  18.             if os.path.exists(filepath):
  19.                 headers["Range"] = f"bytes={os.path.getsize(filepath)}-"
  20.             resp = requests.get(url, headers=headers, timeout=30, stream=True)
  21.             resp.raise_for_status()
  22.             mode = "ab" if os.path.exists(filepath) else "wb"
  23.             with open(filepath, mode) as f:
  24.                 for chunk in resp.iter_content(chunk_size=8192):
  25.                     if chunk:
  26.                         f.write(chunk)
  27.             size = os.path.getsize(filepath)
  28.             print(f"✅ {filename} ({size/1024:.1f}KB)")
  29.             return filepath
  30.         except Exception as e:
  31.             print(f"❌ {filename or url}: {e}")
  32.             return None
  33.     def download_many(self, urls, filenames=None):
  34.         """多线程批量下载"""
  35.         if filenames is None:
  36.             filenames = [None] * len(urls)
  37.         start = time.time()
  38.         success = 0
  39.         with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
  40.             futures = {
  41.                 executor.submit(self.download_one, url, name): url
  42.                 for url, name in zip(urls, filenames)
  43.             }
  44.             for future in as_completed(futures):
  45.                 if future.result():
  46.                     success += 1
  47.         elapsed = time.time() - start
  48.         print(f"\n下载完成:{success}/{len(urls)} 成功,耗时 {elapsed:.1f}s")
  49.         return [f.result() for f in futures]
复制代码

使用方法:
  1. downloader = BatchDownloader("教程附件", max_workers=10)
  2. with open("urls.txt", "r") as f:
  3.     urls = [line.strip() for line in f if line.strip()]
  4. downloader.download_many(urls)
复制代码

1.2 批量下载网页中的图片
借助 BeautifulSoup 解析 HTML,提取所有 img 标签的 src 属性,并过滤常见图片格式。
  1. import requests
  2. from bs4 import BeautifulSoup
  3. from urllib.parse import urljoin
  4. def download_images(page_url, save_dir="images"):
  5.     os.makedirs(save_dir, exist_ok=True)
  6.     resp = requests.get(page_url)
  7.     soup = BeautifulSoup(resp.text, "html.parser")
  8.     img_tags = soup.find_all("img")
  9.     img_urls = []
  10.     for img in img_tags:
  11.         src = img.get("src")
  12.         if src:
  13.             full_url = urljoin(page_url, src)
  14.             if any(ext in full_url.lower() for ext in [".jpg", ".jpeg", ".png", ".gif", ".webp"]):
  15.                 img_urls.append(full_url)
  16.     print(f"找到 {len(img_urls)} 张图片")
  17.     downloader = BatchDownloader(save_dir)
  18.     downloader.download_many(img_urls)
  19. # 使用示例
  20. download_images("https://example.com/article/1")
复制代码

1.3 下载 GitHub 仓库中的指定目录(无需克隆整个仓库)
通过 GitHub API 获取目录内容,只下载文件,不克隆仓库。
  1. def download_github_dir(repo, dir_path, save_dir="github_files"):
  2.     api_url = f"https://api.github.com/repos/{repo}/contents/{dir_path}"
  3.     resp = requests.get(api_url)
  4.     files = resp.json()
  5.     urls, names = [], []
  6.     for f in files:
  7.         if f["type"] == "file":
  8.             urls.append(f["download_url"])
  9.             names.append(f["name"])
  10.     downloader = BatchDownloader(save_dir)
  11.     downloader.download_many(urls, names)
  12. # 下载 Spring Boot 的 starters 目录
  13. download_github_dir("spring-projects/spring-boot", "starters")
复制代码

二、自动压缩打包
下载完成后,常需压缩归档。这里提供三种场景:

2.1 压缩整个文件夹
使用 shutil.make_archive 直接打包,命名自动带上日期。
  1. import shutil
  2. from datetime import datetime
  3. def zip_folder(folder_path, output_name=None):
  4.     if not output_name:
  5.         folder_name = os.path.basename(folder_path)
  6.         today = datetime.now().strftime("%Y%m%d")
  7.         output_name = f"{folder_name}_{today}"
  8.     shutil.make_archive(output_name, "zip", folder_path)
  9.     size = os.path.getsize(output_name + ".zip") / 1024 / 1024
  10.     print(f"已压缩: {output_name}.zip ({size:.1f}MB)")
  11.     return f"{output_name}.zip"
  12. zip_folder("downloads", "课件包_20260630")
复制代码

2.2 只压缩特定类型文件
利用 zipfile 模块,遍历目录筛选扩展名。
  1. import zipfile
  2. def zip_selected_files(directory, extensions, output_name="selected"):
  3.     with zipfile.ZipFile(f"{output_name}.zip", "w", zipfile.ZIP_DEFLATED) as zf:
  4.         for root, _, files in os.walk(directory):
  5.             for f in files:
  6.                 if any(f.endswith(ext) for ext in extensions):
  7.                     filepath = os.path.join(root, f)
  8.                     arcname = os.path.relpath(filepath, directory)
  9.                     zf.write(filepath, arcname)
  10.                     print(f"已添加: {arcname}")
  11.     print(f"压缩完成: {output_name}.zip")
  12. # 压缩 PDF 和 Word 文件
  13. zip_selected_files("课件", [".pdf", ".docx"], "课件PDF版")
复制代码

2.3 带密码加密压缩
需安装 pyminizip 库(pip install pyminizip),可设置密码并指定压缩等级。
  1. import pyminizip
  2. def zip_with_password(folder_path, password, output_name="protected"):
  3.     pyminizip.compress_dir(folder_path, f"{output_name}.zip", password, 5)
  4.     print(f"已加密压缩: {output_name}.zip")
  5. zip_with_password("机密文件", "mypassword123", "机密文件_加密")
复制代码

三、自动删除源文件(可选)
压缩后如需清理原始文件,可以调用以下函数:
  1. import shutil
  2. def clean_source(source_path):
  3.     if os.path.isfile(source_path):
  4.         os.remove(source_path)
  5.         print(f"已删除: {source_path}")
  6.     elif os.path.isdir(source_path):
  7.         shutil.rmtree(source_path)
  8.         print(f"已删除目录: {source_path}")
复制代码

四、完整流水线:下载 → 压缩 → 清理
整合所有步骤,传入 URL 列表文件即可自动完成全流程。
  1. def download_and_pack(urls_file, output_name="打包文件"):
  2.     base_dir = "temp_download"
  3.     with open(urls_file, "r") as f:
  4.         urls = [line.strip() for line in f if line.strip()]
  5.     print(f"共 {len(urls)} 个文件待下载")
  6.     downloader = BatchDownloader(base_dir, max_workers=10)
  7.     results = downloader.download_many(urls)
  8.     success_count = sum(1 for r in results if r)
  9.     print(f"成功下载: {success_count}/{len(results)}")
  10.     if success_count > 0:
  11.         zip_file = zip_folder(base_dir, output_name)
  12.         shutil.rmtree(base_dir)
  13.         print("临时文件已清理")
  14.         return zip_file
  15. # 执行
  16. download_and_pack("urls.txt", "课程资料包_202607")
复制代码

五、定时任务自动执行
利用 schedule 库让脚本在每天指定时间运行,适合持续集成场景。
  1. import schedule
  2. import time
  3. from datetime import datetime
  4. def daily_download_task():
  5.     print(f"开始定时下载任务: {datetime.now()}")
  6.     resp = requests.get("https://api.example.com/today/files")
  7.     files = resp.json()
  8.     urls = [f["url"] for f in files]
  9.     names = [f["name"] for f in files]
  10.     downloader = BatchDownloader("每日更新")
  11.     downloader.download_many(urls, names)
  12.     zip_folder("每日更新", f"更新包_{datetime.now().strftime('%Y%m%d')}")
  13.     print("任务完成")
  14. schedule.every().day.at("08:00").do(daily_download_task)
  15. while True:
  16.     schedule.run_pending()
  17.     time.sleep(60)
复制代码

六、下载工具对比与场景建议
| 方式 | 速度 | 适用场景 |
|------|------|----------|
| requests 单线程 | 慢 | 少量文件 |
| 多线程下载(本文方案) | 快 | 批量文件(推荐) |
| wget 命令 | 中 | Linux 服务器 |
| aria2c | 极快 | 大文件、多文件 |

本文提供的脚本可直接用于课件下载、爬虫数据打包、加密文件分发、每日备份等场景,只需调整参数即可适应不同需求。开发者可以在此基础上扩展文件类型过滤、重试机制、日志记录等高级功能。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python批量下载与自动压缩实现:多线程、加密打包与定时任务

这个方案很实用,尤其是多线程下载和断点续传的部分,正好解决了我最近批量下载大文件时频繁中断的问题。想问一下,如果URL列表里包含了一些需要登录认证的链接,BatchDownloader类有没有预留传入cookie或header的接口?另外加密打包的部分是用zipfile配合密码实现的吗?期待后续的内容。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python批量下载与自动压缩实现:多线程、加密打包与定时任务

感谢楼主分享这么实用的工具!批量下载加上断点续传和失败重试,在日常工作中确实能省下不少重复劳动。代码结构也清晰,直接就能跑起来,挺方便的。 另外,我看标题里还提到了“加密打包”和“定时任务”,这部分内容好像没有在正文里展示出来?如果方便的话,希望能补上压缩加密和自动调度的实现细节,这样整个流水线就完整了。再次感谢分享!
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python批量下载与自动压缩实现:多线程、加密打包与定时任务

感谢分享!批量下载器类设计得很不错,多线程和断点续传功能非常实用,代码注释也很清晰,方便直接拿来用。请问能不能再增加一个进度条显示,方便实时查看下载进度?另外,后面提到的加密打包和定时任务部分还没贴完,期待楼主继续更新~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-6 12:35 , Processed in 0.035035 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部