完整程式碼
import pyperclip
import os
from playwright.sync_api import sync_playwright
mode = 2 #1.生成網站下載連結清單 #2.檢查並生成下載失敗檔案連結供重新下載
count= 2 #count=1且有下載失敗的檔案則會開啟瀏覽器取得檔案名稱清單,count=2直接讀取重新下載.txt中的清單
url = 'https://www.bilibili.com/video/BV1Y84y1L7Nn?p=1'
movie_count = 200
url = url.replace("p=1", "p=")
dl_list = r"J:\B站設定檔\清單列表.txt"
failed_list_file_path = r"J:\B站設定檔\下載失敗列表.txt"
if mode == 2:
re_url = url.replace('=1', '=')
path = r"J:\河洛戲"
full_path = r"J:\B站設定檔\下載失敗列表.txt"
def get_file_names_dl_url_list(url):
file_names = []
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url)
# 取清單主題title
collection_title = page.wait_for_selector('#viewbox_report > h1').text_content()
print(collection_title)
collection_title = collection_title + ' '
element = page.wait_for_selector(
'#multi_page > div.cur-list > ul > li:nth-child(1) > a > div > div.link-content > span.part')
print(f'找到元素****{element.text_content()}')
page.wait_for_timeout(1000)
elements = page.query_selector_all('#multi_page > div.cur-list > ul > li > a')
for element in elements:
file_names.append(collection_title + element.get_attribute('title'))
# 假设文件名列表为 file_names,链接为 re_url
links = {}
for i, file_name in enumerate(file_names):
link = re_url + str(i + 1) # 构建链接
links[file_name] = link # 将文件名和链接添加到字典中
# 将 links 字典写入文件
with open(dl_list, "w", encoding="utf-8") as f:
for file_name, link in links.items():
f.write(f"{file_name}:{link}\n") #寫入清單標題
print('檔名與網址清單已寫入完成')
page.wait_for_timeout(2000)
browser.close()
if not browser.is_connected():
print("浏览器已经关闭")
else:
print("浏览器仍然打开")
return file_names, collection_title
def list_files_under_1kb(directory):
files_under_1kb = []
for root, dirs, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
if os.path.isfile(file_path):
size_kb = os.path.getsize(file_path) / 1024 # 转换为KB
if size_kb < 1:
# 检查文件名是否需要加上 (1)
base_name, extension = os.path.splitext(file)
new_file = base_name + " (1)" + extension
new_file_path = os.path.join(root, new_file)
count = 1
# 如果加上 (1) 的文件存在,则继续检查 (2), (3) ...
while os.path.exists(new_file_path) and os.path.getsize(new_file_path) / 1024 < 1:
count += 1
new_file = base_name + f" ({count})" + extension
new_file_path = os.path.join(root, new_file)
# 如果加上 (1) 的文件不存在或者大小大于等于 1KB,则将原文件加入列表
if not os.path.exists(new_file_path):
files_under_1kb.append(os.path.basename(file_path))
return files_under_1kb
def find_matching_indexes(re_dl_names, file_names):
matching_indexes = []
for dl_name in re_dl_names:
index = None
for i, name in enumerate(file_names):
if dl_name in name:
index = i
break
matching_indexes.append(index)
return matching_indexes
# 找出下載失敗檔案列表
re_dl_names = list_files_under_1kb(path)
re_dl_names = [name.replace('.mp4', '') for name in re_dl_names]
print(f'共{len(re_dl_names)}個下載失敗檔案')
print(f'下載失敗檔案為{re_dl_names}')
# 检查文件路径是否存在
if os.path.exists(failed_list_file_path):
print(f"文件路径 '{failed_list_file_path}' 存在。")
# 检查文件是否存在
if os.path.isfile(failed_list_file_path):
print(f"文件 '{failed_list_file_path}' 存在且是一个文件。")
else:
print(f"文件 '{failed_list_file_path}' 存在但不是一个文件。")
else:
print(f"文件路径 '{failed_list_file_path}' 不存在。")
print(f"re_dl_names: {re_dl_names}")
print(f"count: {count}")
if len(re_dl_names) > 0 and count == 2:
print('開始寫入失敗下載清單')
with open(failed_list_file_path, "w", encoding="utf-8") as failed_list_file:
failed_list_file.write("999")
for re_dl_name in re_dl_names:
print(f"Writing: {re_dl_name}")
failed_list_file.write("999") # 写入文件并添加换行符
if len(re_dl_names) > 0 and count == 1: #只須執行一次調用瀏覽器取得檔案名稱與下載連結列表並寫入J:\B站設定檔\清單列表.txt.
# 調用瀏覽器取得檔案名稱清單
file_names_list, collection_title = get_file_names_dl_url_list(url)
error_list = [re_dl_name.replace(collection_title, '') for re_dl_name in re_dl_names]
print(error_list)
# 取出失敗清單網址
print('取出失敗清單網址')
# 定义清单文件路径和下载失败列表文件路径
# 读取下载失败的文件名列表
with open(failed_list_file_path, "w", encoding="utf-8") as failed_list_file:
# 检查下载失败列表文件是否为空
if os.path.getsize(failed_list_file_path) == 0:
print(f"下载失败列表文件为空,應該已無下載失敗檔案\n檔案總數量為{movie_count}")
exit()
# 逐个读取re_dl_names中的每个元素
for dl_name in re_dl_names:
# 逐行读取清单文件的每一行
with open(dl_list, "r", encoding="utf-8") as dl_list_file:
for line in dl_list_file:
# 检查该行是否包含re_dl_names中的元素
if dl_name in line:
# 如果是,将该行写入下载失败列表文件
failed_list_file.write(line)
# 尋找目標網址 讀取failed_list_file_path(下載失敗列表.txt)
print('尋找下載失敗網址')
# 读取下载失败列表文件中的每一行
copied_text = '' # 初始化一个空字符串,用于存储已复制的文本
with open(failed_list_file_path, "r", encoding="utf-8") as failed_list_file:
for line in failed_list_file:
# 使用 split() 方法分割每一行,指定分割的次数为 1,避免将冒号解释为分隔符
url = line.split(":", 1)[-1].strip()
# 将网址复制到剪贴板中
pyperclip.copy(url)
copied_text += url + '\n' # 将当前 URL 添加到已复制的文本后面,并添加换行符
print("已复制到剪贴板:", url)
# 最后将整个文本再复制到剪贴板
pyperclip.copy(copied_text)
主要問題在這小段程式碼.文字不會被寫入到下載失敗列表.txt
但是如果先打字在下載失敗列表.txt中文字會被清空.
if len(re_dl_names) > 0 and count == 2:
print('開始寫入失敗下載清單')
with open(failed_list_file_path, "w", encoding="utf-8") as failed_list_file:
failed_list_file.write("999")
for re_dl_name in re_dl_names:
print(f"Writing: {re_dl_name}")
failed_list_file.write("999") # 写入文件并添加换行符
failed_list_file_path = r"J:\B站設定檔\下載失敗列表.txt"
這個下載失敗列表.txt始終都是空的
我甚至直接先打幾行字在下載失敗列表.txt
但是執行後依然變成空的
原本程式碼應該是failed_list_file.write(re_dl_name)
但是發現沒寫入任何東西到txt中
所以我就故意改成寫入"999"但是文件依然是空的
但是我用這小段程式碼去測試.發現123會被正確寫入到下載失敗列表.txt
代表寫入權限沒問題.
所以找了好幾個小時都找不到原因
求大神幫忙
failed_list_file_path = r"J:\B站設定檔\下載失敗列表.txt"
re_dl_names = ['1','2','3']
with open(failed_list_file_path, "w", encoding="utf-8") as failed_list_file:
for re_dl_name in re_dl_names:
failed_list_file.write(re_dl_name+'\n')
re_dl_names: 這個在進樓主trace到有問題的那段前印出來的內容為何呢?
打幾行字在列表後執行完為空 <-- 指的是整個程式跑完後,還是僅執行認為有問題的該段?
你的這一段
# 取出失敗清單網址
print('取出失敗清單網址')
# 定义清单文件路径和下载失败列表文件路径
# 读取下载失败的文件名列表
with open(failed_list_file_path, "w", encoding="utf-8") as failed_list_file:
是要讀取檔案, 但是你用了 "w", 會把檔案清空, 這邊應該要改成 "r"。
ChatGPT的回答如下:
您的程式碼在處理寫入「下載失敗列表.txt」檔案的邏輯上似乎有些混亂,特別是在多次打開並寫入同一文件時。這可能導致預期外的文件內容被覆蓋或不被正確寫入。
首先,您在條件 if len(re_dl_names) > 0 and count == 2 下,試圖寫入 failed_list_file_path 文件,但您在這裡寫入的是固定內容"999",而不是實際的下載失敗連結或文件名。這顯然不符合您想要將失敗連結寫入文件的目的。
其次,您多次使用 "w" 模式打開 failed_list_file_path 進行寫入,每次使用 "w" 模式打開文件時都會清空該文件原有的內容。如果您在程序的不同部分分別寫入文件,應該使用 "a" 模式(追加模式),這樣新寫入的內容會被添加到文件的末尾,而不是覆蓋原有內容。然而,基於您的描述和程式碼,看起來您應該在最終確定所有需要寫入的內容後,一次性地打開文件並寫入,而不是分多次寫入。
以下是對您程式碼的建議修正版本,主要專注於整理和修正文件寫入邏輯:
import os
from playwright.sync_api import sync_playwright
# 假設這些函數已經在您的程式碼中正確定義
def list_files_under_1kb(directory):
# 這裡應實現您的邏輯
pass
def get_file_names_dl_url_list(url):
# 這裡應實現您的邏輯
pass
# 原始變量定義
path = r"J:\河洛戲"
failed_list_file_path = r"J:\B站設定檔\下載失敗列表.txt"
re_dl_names = list_files_under_1kb(path) # 獲取下載失敗的文件列表
re_dl_names = [name.replace('.mp4', '') for name in re_dl_names]
# 假設您已經有了一個包含所有失敗下載鏈接的列表
failed_links = [] # 這個列表應該從您的邏輯中生成
# 確定有失敗的下載後再進行寫入操作
if len(re_dl_names) > 0:
with open(failed_list_file_path, "w", encoding="utf-8") as failed_list_file:
for link in failed_links:
failed_list_file.write(f"{link}\n")
# 請確保替換上面的 failed_links 列表填入正確的失敗下載鏈接
這段程式碼假設您已經能夠生成一個包含所有失敗下載鏈接的 failed_links 列表。您需要根據實際的下載邏輯來填充這個列表,然後將其寫入到指定的文件中。這樣,您就能夠一次性地將所有需要的信息寫入文件,而不是分多次打開和寫入,這會降低出錯的風險並使程式碼更加清晰。