使用Selenium WebDriver在Firefox下载PDF后进程卡住的问题排查
问题:Selenium访问PMC PDF链接后程序卡住无法退出
我尝试用Python的Selenium WebDriver从PubMed Central下载PDF,代码能成功下载PDF,但程序卡在browser.get(href)这一行,无法自动退出,请问可能的原因是什么?
原代码
import os from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.firefox.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC ncbi_url = "https://www.ncbi.nlm.nih.gov/" download_dir = "pdf_downloaded" if not os.path.exists(download_dir): os.mkdir(download_dir) options = Options() options.set_preference('permissions.default.stylesheet', 2) options.set_preference('permissions.default.image', 2) options.set_preference('browser.download.folderList', 2) options.set_preference('browser.download.dir', os.path.abspath(download_dir)) options.set_preference('browser.download.manager.showWhenStarting', False) options.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/pdf') options.set_preference('pdfjs.disabled', True) browser = webdriver.Firefox(options=options) ############################################################################### def download_pmc_pdf(pmcid_key): pmc_url = ncbi_url + "pmc/articles/" + pmcid_key + "/" browser.get(pmc_url) try: wait = WebDriverWait(browser, 10) pdf_links = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.pmc-sidebar__formats li a'))) # Iterate over all links and navigate to the link containing '.pdf' in the href attribute for link in pdf_links: href = link.get_attribute('href') if '.pdf' in href: browser.get(href) break # exit the loop as we have found the PDF link print("line beofre browser.quit()") browser.quit() # quit the browser outside the loop except Exception as e: print(e) ############################################################################### pmcid = "2788555" download_pmc_pdf(pmcid) browser.quit()
可能的原因
页面加载等待逻辑冲突
调用browser.get(href)访问PDF链接时,Selenium默认会等待页面完全加载完成才执行后续代码。但你设置了pdfjs.disabled=True,浏览器不会在页面内渲染PDF,而是直接触发下载操作——这个操作没有“完成页面加载”的状态,导致Selenium一直卡在等待页面加载的环节,无法继续执行退出代码。重复调用
browser.quit()
代码在download_pmc_pdf函数内部已经调用了browser.quit(),函数执行完毕后外部又调用了一次。这虽不是卡住的直接原因,但会导致程序正常退出时报错,属于冗余代码。
解决办法
方法1:设置页面加载超时
给浏览器设置页面加载超时时间,超时后程序会抛出异常但可继续执行退出逻辑:
# 初始化浏览器后添加这行代码 browser.set_page_load_timeout(10) # 10秒超时,可根据情况调整
方法2:改用JavaScript触发下载(推荐)
避免使用browser.get(),用JS打开新窗口触发下载,跳过Selenium的页面加载等待逻辑:
# 替换原代码中的browser.get(href)部分 if '.pdf' in href: # 用JS打开新窗口触发下载 browser.execute_script("window.open(arguments[0]);", href) # 切换到新窗口并关闭 handles = browser.window_handles browser.switch_to.window(handles[-1]) browser.close() browser.switch_to.window(handles[0]) break
方法3:清理冗余的退出代码
只保留一处browser.quit(),比如放在函数的finally块中,确保无论是否报错都能退出浏览器:
def download_pmc_pdf(pmcid_key): pmc_url = ncbi_url + "pmc/articles/" + pmcid_key + "/" try: browser.get(pmc_url) # ... 中间逻辑不变 ... except Exception as e: print(f"出错:{e}") finally: browser.quit() # 统一在这里退出
修改后的完整代码
import os from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.firefox.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC ncbi_url = "https://www.ncbi.nlm.nih.gov/" download_dir = "pdf_downloaded" if not os.path.exists(download_dir): os.mkdir(download_dir) options = Options() options.set_preference('permissions.default.stylesheet', 2) options.set_preference('permissions.default.image', 2) options.set_preference('browser.download.folderList', 2) options.set_preference('browser.download.dir', os.path.abspath(download_dir)) options.set_preference('browser.download.manager.showWhenStarting', False) options.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/pdf') options.set_preference('pdfjs.disabled', True) browser = webdriver.Firefox(options=options) browser.set_page_load_timeout(10) # 添加页面加载超时 def download_pmc_pdf(pmcid_key): pmc_url = ncbi_url + "pmc/articles/" + pmcid_key + "/" try: browser.get(pmc_url) wait = WebDriverWait(browser, 10) pdf_links = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.pmc-sidebar__formats li a'))) for link in pdf_links: href = link.get_attribute('href') if '.pdf' in href: # 用JS触发下载,避免等待页面加载 browser.execute_script("window.open(arguments[0]);", href) handles = browser.window_handles browser.switch_to.window(handles[-1]) browser.close() browser.switch_to.window(handles[0]) break print("准备退出浏览器") except Exception as e: print(f"错误信息:{e}") finally: browser.quit() pmcid = "2788555" download_pmc_pdf(pmcid)
内容的提问来源于stack exchange,提问作者Wasim Aftab
相关产品推荐
相关产品推荐

