当前位置:  首页>> 技术小册>> Python自动化办公实战

19 | HTTP库:如何批量下载在线内容,解放鼠标(下)

在上一章节中,我们初步探索了利用Python中的HTTP库(如requests)来实现在线内容的下载,并简要介绍了如何通过编写简单的脚本来自动化这一过程,从而初步解放了我们的鼠标。本章节将在此基础上进一步深入,探讨更高级、更复杂的批量下载策略,包括但不限于多线程/异步下载、处理重定向、下载进度显示、错误处理及重试机制等,以期实现更高效、更稳定的在线内容批量下载解决方案。

一、多线程/异步下载

在批量下载大量文件时,单线程模式往往会因为网络延迟或服务器限制而效率低下。采用多线程或异步IO技术可以显著提高下载速度,因为它们允许多个任务同时执行,充分利用了网络带宽和CPU资源。

1.1 多线程下载

Python的threading模块提供了创建多线程的基本框架。我们可以为每个下载任务分配一个线程,从而并行执行。

  1. import requests
  2. from threading import Thread
  3. import os
  4. def download_file(url, filename):
  5. response = requests.get(url, stream=True)
  6. if response.status_code == 200:
  7. with open(filename, 'wb') as f:
  8. for chunk in response.iter_content(chunk_size=8192):
  9. if chunk:
  10. f.write(chunk)
  11. def download_multiple(urls, filenames):
  12. threads = []
  13. for url, filename in zip(urls, filenames):
  14. t = Thread(target=download_file, args=(url, filename))
  15. t.start()
  16. threads.append(t)
  17. for t in threads:
  18. t.join()
  19. # 示例使用
  20. urls = ['http://example.com/file1.zip', 'http://example.com/file2.jpg']
  21. filenames = ['file1.zip', 'file2.jpg']
  22. download_multiple(urls, filenames)
1.2 异步下载(使用asyncio

Python 3.5及以上版本引入了asyncio库,支持编写单线程的并发代码。通过aiohttp库,我们可以实现异步的HTTP请求。

  1. import aiohttp
  2. import asyncio
  3. async def download_file(session, url, filename):
  4. async with session.get(url) as response:
  5. if response.status == 200:
  6. with open(filename, 'wb') as f:
  7. while chunk := await response.content.read(8192):
  8. f.write(chunk)
  9. async def download_multiple(urls, filenames):
  10. async with aiohttp.ClientSession() as session:
  11. tasks = [download_file(session, url, filename) for url, filename in zip(urls, filenames)]
  12. await asyncio.gather(*tasks)
  13. # 示例使用
  14. urls = ['http://example.com/file1.zip', 'http://example.com/file2.jpg']
  15. filenames = ['file1.zip', 'file2.jpg']
  16. asyncio.run(download_multiple(urls, filenames))

二、处理重定向

在下载过程中,经常会遇到URL重定向的情况。requests库默认会处理HTTP重定向,但有时候我们可能需要自定义重定向的行为,比如限制重定向次数,或者在重定向发生时记录日志。

  1. import requests
  2. def download_with_redirects(url, max_redirects=5):
  3. try:
  4. response = requests.get(url, allow_redirects=True, max_redirects=max_redirects)
  5. response.raise_for_status() # 如果响应状态码不是200,将抛出HTTPError异常
  6. # 后续处理...
  7. except requests.exceptions.TooManyRedirects:
  8. print(f"Too many redirects ({max_redirects}) for URL: {url}")
  9. except requests.exceptions.RequestException as e:
  10. print(f"Error downloading {url}: {e}")
  11. # 示例使用
  12. download_with_redirects('http://example.com/redirected')

三、下载进度显示

对于大型文件的下载,提供进度条反馈可以显著提升用户体验。requests库本身不直接支持进度显示,但我们可以通过监听下载过程中的数据块来实现。

  1. import requests
  2. from tqdm import tqdm
  3. def download_with_progress(url, filename):
  4. response = requests.get(url, stream=True)
  5. total_size_in_bytes = int(response.headers.get('content-length', 0))
  6. block_size = 1024 # 1 Kilobyte
  7. progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)
  8. with open(filename, 'wb') as file:
  9. for data in response.iter_content(block_size):
  10. progress_bar.update(len(data))
  11. if data:
  12. file.write(data)
  13. progress_bar.close()
  14. # 示例使用
  15. download_with_progress('http://example.com/largefile.zip', 'largefile.zip')

四、错误处理及重试机制

网络请求常因多种原因失败,如网络不稳定、服务器超时等。实现自动重试机制可以增强程序的健壮性。

  1. import requests
  2. from requests.adapters import HTTPAdapter
  3. from requests.packages.urllib3.util.retry import Retry
  4. def requests_retry_session(
  5. retries=3,
  6. backoff_factor=0.3,
  7. status_forcelist=(500, 502, 504),
  8. session=None,
  9. ):
  10. session = session or requests.Session()
  11. retry = Retry(
  12. total=retries,
  13. read=retries,
  14. connect=retries,
  15. backoff_factor=backoff_factor,
  16. status_forcelist=status_forcelist,
  17. )
  18. adapter = HTTPAdapter(max_retries=retry)
  19. session.mount('http://', adapter)
  20. session.mount('https://', adapter)
  21. return session
  22. # 示例使用
  23. session = requests_retry_session(retries=5, backoff_factor=0.5)
  24. response = session.get('http://example.com/file.zip')
  25. response.raise_for_status()
  26. # 后续处理...

五、总结

通过本章节的学习,我们不仅掌握了如何利用Python的HTTP库进行批量下载的基本方法,还深入探讨了多线程/异步下载、处理重定向、显示下载进度以及实现错误处理和重试机制的高级技巧。这些技能将极大地提升我们处理在线内容下载任务的能力,使我们能够更高效地自动化办公流程,进一步解放双手,专注于更有价值的工作。在未来的实践中,建议结合具体场景和需求,灵活运用这些技术,不断优化和完善批量下载解决方案。


该分类下的相关小册推荐: