You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium+Mudopy下载MP3后ChromeDriver卡在Hollywood bet页面求助

问题:ChromeDriver未正常退出,触发无关页面导致代码卡住

我用mudopy + Selenium实现了从YouTube抓取视频、转MP3并下载的功能,歌曲能成功下载,但ChromeDriver无法正常退出,反而自动打开了未请求的Hollywood bet页面并卡住,导致后续代码无法运行。

原始代码

def download(song, artist = None, play_after_downloading = True):
    """Downloads the video to given directory"""
    
    try:
        file=open("down_path.txt")
        down_path=file.read()
        down_path=down_path.strip()
        file.close()
        
    except:
        down_path = os.getcwd()

    print("It will not take more than 1 minute if your download speed is good")
    if artist:
        song=song+ ' by ' +artist
    video=song
    '''
    chrome_options = webdriver.ChromeOptions()
    chrome_options.binary_location = os.environ.get("GOOGLE_CHROME_BIN")
    chrome_options.add_argument("--headless")
    chrome_options.add_argument("--disable-dev-shm-usage")
    chrome_options.add_argument("--no-sandbox")
    driver = webdriver.Chrome(executable_path=os.environ.get("CHROMEDRIVER_PATH"), options=chrome_options)
    
'''
    chromeOptions=Options()
    chromeOptions.add_experimental_option("prefs",{"download.default_directory":down_path})
    chromeOptions.add_argument("--headless")
    chromeOptions.add_argument('--ignore-certificate-errors-spki-list')
    chromeOptions.add_argument('--ignore-ssl-errors')
    #chromeOptions.add_argument("--disable-dev-shm-usage")
    #chromeOptions.add_argument("--no-sandbox")
    #chromeOptions.add_argument("--disable-javascript")
    #service = Service(executable_path=ChromeDriverManager().install())

    #driver = webdriver.Chrome(service=service)
    #driver = webdriver.Chrome(executable_path=os.environ.get("CHROMEDRIVER_PATH"), options=chromeOptions)
    driver = webdriver.Chrome(ChromeDriverManager(path=os.getcwd()).install(),options=chromeOptions)
    wait=WebDriverWait(driver,3)
    presence = EC.presence_of_element_located   
    visible = EC.visibility_of_element_located
    driver.get("https://www.youtube.com/results?search_query=" + str(video))
    ads =True
    wait.until(visible((By.ID, "video-title")))
    try:
        driver.find_element(By.XPATH,"//span[contains(@class,'style-scope ytd-badge-supported-renderer') and text()='Ad']")
    except Exception as e:
        ads=False
    if ads:    
        vid = driver.find_element(By.ID,"video-title")
        vid.click()
    else:
        vid = driver.find_element(By.ID,"video-title")
        vid.click()
    #driver.find_element(By.ID,"video-title").click()
    print(driver.current_url)
    url=driver.current_url
    driver.get("https://ytmp3.cc/en13/")
    driver.maximize_window()   
    driver.find_element(By.XPATH,"//*[@id='mp3']").click()
    driver.find_element(By.XPATH,"//*[@id='input']").send_keys(url)
    driver.find_element(By.XPATH,"//*[@id='submit']").click()
    time.sleep(6)
    driver.find_element(By.XPATH,"//*[@id='buttons' or @id='download']/span").click()
    #driver.find_element(By.XPATH,'//*[@id="download_list"]/div[1]').click()
    print("Downloading")
    time.sleep(10)
    driver.close()
    old_lst = os.listdir(down_path)
    while True:
            new_lst = os.listdir(down_path)
                
            if new_lst != old_lst:
                song = set(new_lst) - set(old_lst)
                song = str(song)
                song = song.replace("{","")
                song = song.replace("}","")
                song = song.strip("'")
                #song = song.replace(" ","")                
                
                
                if Path(song).suffix == '.mp3':
                    driver.quit()
                    if play_after_downloading:
                        print("Song downloaded to :"+down_path)
                        #print("playing")
                        #os.startfile(down_path+"/"+song)
                        print(song)
                       
                    return song
                    break
    #print(song)    
    print("Hello from the creator of Mudopy,Smit Parmar and Ankit Raj Mahapatra.Do report bug if any")
    print("set download path")
    print("mudopy.download_path(r'download path') #dont forget to use 'r' while set download path")
    file.close()

问题根源

  1. 恶意跳转触发:ytmp3这类免费转换站点普遍植入广告,点击下载的操作可能误触隐藏的广告链接,导致打开无关页面。
  2. Driver关闭逻辑混乱:先调用driver.close()关闭当前窗口,之后又在循环里调用driver.quit(),此时Driver实例已失效,未及时终止进程导致残留。
  3. 等待方式不可靠:依赖time.sleep()固定等待时间,容易错过元素加载或提前触发操作,增加误触广告的概率。
  4. 元素定位不精准:下载按钮的XPATH范围太宽,可能定位到广告元素而非真正的下载按钮。

修复方案

1. 增强Chrome配置拦截跳转与广告

更新ChromeOptions,添加弹窗拦截、新页面阻止等参数:

chromeOptions=Options()
chromeOptions.add_experimental_option("prefs",{"download.default_directory":down_path})
chromeOptions.add_argument("--headless=new")  # 新版无头模式更稳定
chromeOptions.add_argument('--ignore-certificate-errors-spki-list')
chromeOptions.add_argument('--ignore-ssl-errors')
chromeOptions.add_argument("--disable-popup-blocking")  # 拦截自动弹出窗口
chromeOptions.add_argument("--block-new-web-contents")  # 阻止站点自动打开新页面
chromeOptions.add_experimental_option("excludeSwitches", ["enable-automation"])  # 避免被检测为自动化工具
chromeOptions.add_experimental_option('useAutomationExtension', False)

2. 修正Driver生命周期管理

用try-finally确保无论代码执行成功还是失败,都能关闭Driver:

driver = webdriver.Chrome(ChromeDriverManager(path=os.getcwd()).install(),options=chromeOptions)
wait=WebDriverWait(driver, 10)
try:
    # 所有业务逻辑放在try块内
    driver.get("https://www.youtube.com/results?search_query=" + str(video))
    # ... 中间代码省略 ...
finally:
    driver.quit()  # 无论如何都终止Driver进程

3. 替换time.sleep为显式等待

针对关键操作使用WebDriverWait,确保元素加载完成后再执行:

# 替换原有的time.sleep(6)
wait.until(visible((By.XPATH, "//a[@id='download']")))
driver.find_element(By.XPATH, "//a[@id='download']").click()  # 精准点击下载链接

4. 优化文件检测逻辑

简化循环检测逻辑,增加超时机制防止无限循环:

old_files = set(os.listdir(down_path))
timeout = time.time() + 60  # 设置60秒超时
while time.time() < timeout:
    new_files = set(os.listdir(down_path))
    added_files = new_files - old_files
    for file in added_files:
        if Path(file).suffix == '.mp3':
            if play_after_downloading:
                print(f"Song downloaded to: {down_path}")
                print(file)
            return file
    time.sleep(1)  # 每秒检测一次

修改后的完整代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import os
from pathlib import Path
import time

def download(song, artist = None, play_after_downloading = True):
    """Downloads the video to given directory"""
    
    down_path = os.getcwd()
    try:
        with open("down_path.txt", "r") as file:
            down_path = file.read().strip()
    except:
        pass

    print("It will not take more than 1 minute if your download speed is good")
    video = f"{song} by {artist}" if artist else song

    # 配置Chrome选项
    chromeOptions=Options()
    chromeOptions.add_experimental_option("prefs",{"download.default_directory":down_path})
    chromeOptions.add_argument("--headless=new")
    chromeOptions.add_argument('--ignore-certificate-errors-spki-list')
    chromeOptions.add_argument('--ignore-ssl-errors')
    chromeOptions.add_argument("--disable-popup-blocking")
    chromeOptions.add_argument("--block-new-web-contents")
    chromeOptions.add_experimental_option("excludeSwitches", ["enable-automation"])
    chromeOptions.add_experimental_option('useAutomationExtension', False)

    driver = webdriver.Chrome(ChromeDriverManager(path=os.getcwd()).install(), options=chromeOptions)
    wait=WebDriverWait(driver, 10)
    visible = EC.visibility_of_element_located

    try:
        # 搜索YouTube视频
        driver.get(f"https://www.youtube.com/results?search_query={video}")
        wait.until(visible((By.ID, "video-title")))
        
        # 广告检测
        ads = True
        try:
            driver.find_element(By.XPATH,"//span[contains(@class,'style-scope ytd-badge-supported-renderer') and text()='Ad']")
        except:
            ads=False
        
        # 点击第一个视频
        vid = driver.find_element(By.ID,"video-title")
        vid.click()
        print(driver.current_url)
        url=driver.current_url

        # 跳转转换站并操作
        driver.get("https://ytmp3.cc/en13/")
        driver.find_element(By.XPATH,"//*[@id='mp3']").click()
        driver.find_element(By.XPATH,"//*[@id='input']").send_keys(url)
        driver.find_element(By.XPATH,"//*[@id='submit']").click()

        # 等待下载按钮并点击
        wait.until(visible((By.XPATH, "//a[@id='download']")))
        driver.find_element(By.XPATH, "//a[@id='download']").click()
        print("Downloading")

        # 检测MP3文件是否下载完成
        old_files = set(os.listdir(down_path))
        timeout = time.time() + 60  # 60秒超时
        while time.time() < timeout:
            new_files = set(os.listdir(down_path))
            added_files = new_files - old_files
            for file in added_files:
                if Path(file).suffix == '.mp3':
                    if play_after_downloading:
                        print(f"Song downloaded to: {down_path}")
                        print(file)
                    return file
            time.sleep(1)
        
        print("Download timed out")
        return None

    finally:
        # 确保Driver始终退出
        driver.quit()

    print("Hello from the creator of Mudopy,Smit Parmar and Ankit Raj Mahapatra.Do report bug if any")
    print("set download path")
    print("mudopy.download_path(r'download path') #dont forget to use 'r' while set download path")

内容的提问来源于stack exchange,提问作者Nkosi Ncube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:26:06