iT邦幫忙

0

python求助.我找了好幾個小時都找不到問題出在哪裡.求大神幫忙!

  • 分享至 

  • xImage

完整程式碼

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')
froce iT邦大師 1 級 ‧ 2024-03-13 15:25:54 檢舉
這狀況看起來像是重複寫入,看你code裡重複使用這個變數的狀況很嚴重,建議改寫一下,把結果先丟在一個list中,最後一次輸出就好。
fdfanmo iT邦新手 5 級 ‧ 2024-03-13 20:30:05 檢舉
謝謝froce大師.今天我一個朋友來有幫我看.他的說法跟你一樣.我把整個程式碼重新整理過應該可以找出問題.謝謝幫忙喔!
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
gordon_tw
iT邦新手 4 級 ‧ 2024-03-13 13:55:52
最佳解答

re_dl_names: 這個在進樓主trace到有問題的那段前印出來的內容為何呢?

打幾行字在列表後執行完為空 <-- 指的是整個程式跑完後,還是僅執行認為有問題的該段?

fdfanmo iT邦新手 5 級 ‧ 2024-03-13 20:31:58 檢舉

謝謝幫忙.今天我一個朋友來有幫我看.他說應該是後面的部分又把他覆蓋掉了.我把整個程式碼重新整理過應該可以找出問題.謝謝幫忙喔!

1
海綿寶寶
iT邦大神 1 級 ‧ 2024-03-14 08:03:02

參考看看Gemini
不確定還有沒有效

fdfanmo iT邦新手 5 級 ‧ 2024-03-15 08:21:44 檢舉

謝謝幫忙回答.問題我已經找到了.再次感謝幫忙.

0
meebox
iT邦新手 3 級 ‧ 2024-03-14 09:16:47

你的這一段

    # 取出失敗清單網址
    print('取出失敗清單網址')
    # 定义清单文件路径和下载失败列表文件路径
    # 读取下载失败的文件名列表
    with open(failed_list_file_path, "w", encoding="utf-8") as failed_list_file:

是要讀取檔案, 但是你用了 "w", 會把檔案清空, 這邊應該要改成 "r"。

fdfanmo iT邦新手 5 級 ‧ 2024-03-15 08:21:26 檢舉

謝謝幫忙回答.問題我已經找到了.再次感謝幫忙.

0
alan0219
iT邦新手 5 級 ‧ 2024-03-14 15:01:55

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 列表。您需要根據實際的下載邏輯來填充這個列表,然後將其寫入到指定的文件中。這樣,您就能夠一次性地將所有需要的信息寫入文件,而不是分多次打開和寫入,這會降低出錯的風險並使程式碼更加清晰。

fdfanmo iT邦新手 5 級 ‧ 2024-03-15 08:22:07 檢舉

謝謝幫忙回答.問題我已經找到了.再次感謝幫忙.

我要發表回答

立即登入回答