在某次課程中,有需多檔案需要手動新增目錄、下載,此腳本將根據提供的網址與儲存目錄,完整下載伺服器上的所有資源

已經下載的同名檔案將被忽略 此腳本無法判斷檔案是否有更新,請將目錄完全刪除再重新運行腳本

Demo Images Demo1 Demo2

先安裝好第三方依賴,再設定 url 與 output_path 變數

pip install tqdm

腳本

 1# 下載由 Python http-server 架設的完整檔案目錄
 2# 需手動設定 url 與 output_path 變數
 3# Author: XinShou
 4
 5from tqdm import tqdm  # pip install tqdm
 6from urllib.request import urlretrieve, urlopen
 7from urllib.parse import unquote
 8from urllib.error import URLError, HTTPError
 9from queue import Queue
10import os
11import re
12
13url = "http://10.17.15.250:12345/"
14output_path = "./AIS3教材/"
15
16
17def fetch_url_content(target_url):
18    try:
19        with urlopen(target_url) as response:
20            return response.read().decode('utf-8')
21    except (URLError, HTTPError) as e:
22        print(f"Error fetching {target_url}: {e}")
23        return None
24
25
26def process_download_queue():
27    downloadQueue = Queue()
28    initial_content = fetch_url_content(url)
29    if initial_content:
30        for link in re.findall(r'<a href="([^"]+)">', initial_content):
31            downloadQueue.put(link)
32
33    while not downloadQueue.empty():
34        current = downloadQueue.get()
35
36        if current.endswith('/'):
37            directory_content = fetch_url_content(url + current)
38            if directory_content:
39                os.makedirs(os.path.dirname(os.path.join(output_path, current)), exist_ok=True)
40                for link in re.findall(r'<a href="([^"]+)">', directory_content):
41                    downloadQueue.put(current + link)
42        else:
43            download_file(current)
44
45
46def download_file(relative_path):
47    full_path = os.path.join(output_path, unquote(relative_path))
48    if not os.path.exists(full_path):
49        with tqdm(unit='B', unit_scale=True, unit_divisor=1024, miniters=1, desc=unquote(relative_path)) as t:
50            urlretrieve(url + relative_path, full_path, reporthook=progress_hook(t))
51    else:
52        print("Already Exist, Skipped!")
53
54
55def progress_hook(t):
56    last_b = [0]
57
58    def update_to(b=1, bsize=1, tsize=None):
59        if tsize is not None:
60            t.total = tsize
61        t.update((b - last_b[0]) * bsize)
62        last_b[0] = b
63
64    return update_to
65
66
67if __name__ == "__main__":
68    process_download_queue()