DRM环境下Selenium+Pyinstaller打包exe后PDF下载损坏求助
Pyinstaller打包Selenium程序后PDF下载损坏的问题排查与解决方案
问题描述
我开发了一款使用Selenium爬取网站信息并自动下载PDF附件的Python程序,在VS Code中运行完全正常,但通过Pyinstaller打包为exe可执行文件后,下载的PDF文件损坏无法打开。企业环境下所有文档会自动应用DRM保护,已尝试Pyinstaller的--hidden-import选项,问题仍未解决。
测试情况
- Case 1:通过Pyinstaller生成的exe启动Chrome并自动下载PDF,文件损坏无法打开;
- Case 2:通过exe启动Chrome后手动下载PDF,文件同样损坏无法打开;
- Case 3:手动打开Chrome访问网站下载同一PDF,文件可正常打开,说明原始PDF文件无问题。
核心代码(浏览器初始化部分)
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.alert import Alert from selenium.webdriver.common.action_chains import ActionChains import chromedriver_autoinstaller #type: ignore from webdriver_manager.chrome import ChromeDriverManager from bs4 import BeautifulSoup import openpyxl, pandas, requests, threading, datetime, xlwings # 외부 라이브러리 import os, time, shutil, getpass # 기본 라이브러리 from concurrent import futures import sys, os current_dir = "D:\\Python" directory = current_dir.replace("\\","/",10) + "/" chrome_down_path = current_dir+"\\Downloads" down_path = directory+"Downloads/" PartNumber = "JANTXV1N4616UR-1" url = 'https://www.doeeet.com/home' chrome_ver = chromedriver_autoinstaller.get_chrome_version().split(".")[0] #type:ignore driver_path = f'./{chrome_ver}/chromedriver.exe' if os.path.exists(driver_path): print(f"chrom driver is insatlled: {driver_path}") else: print(f"install the chrome driver(ver: {chrome_ver})") chromedriver_autoinstaller.install(True) chrome_options = Options() profile = { #"plugins.plugins_list": [{"enabled": False, "name": "Chrome PDF Viewer"}], # Disable Chrome's PDF Viewer "download.default_directory": chrome_down_path, #r"C:\Users\yunji.lim\Desktop\Data\Downloads", "download.prompt_for_download": False, #To auto download the file "download.directory_upgrade":True, "plugins.always_open_pdf_externally": True, "download.extensions_to_open": "applications/pdf" } chrome_options.add_experimental_option("prefs",profile) chrome_options.add_experimental_option("detach",True) browser = webdriver.Chrome(driver_path, options=chrome_options) browser.maximize_window() browser.implicitly_wait(5) browser.get(url) try : WebDriverWait(browser,5).until( EC.presence_of_element_located((By.XPATH,'//*[@id="ngrv_"]/a')) ) finally : element = browser.find_element(By.XPATH,'//*[@id="ngrv_"]/a') element.send_keys("\n") element = browser.find_element(By.XPATH,'//*[@id="_58_login"]') element.clear() element.send_keys(user_id) element = browser.find_element(By.XPATH,'//*[@id="_58_password"]') element.send_keys(user_pw) element.send_keys("\n") try : # 검색 가능한 상태까지 Wait (wait time : max 15sec) WebDriverWait(browser,15).until( EC.presence_of_element_located((By.NAME,'q')) ) except : pass finally : # 검색 가능한 상태에 도달 하면 Part Number 검색 수행 element = browser.find_element(By.NAME,'q') element.send_keys(PartNumber) element.send_keys("\n") try : # Part Number 검색 결과가 로드 될 때 까지 대기 (wait time : max 15sec) WebDriverWait(browser,25).until( EC.presence_of_element_located((By.LINK_TEXT, PartNumber)) ) except : pass finally : # 클릭 가능한 상태에 도달하면 검색 결과 클릭 search_res = browser.find_elements(By.LINK_TEXT, PartNumber)
可行解决方案
1. 统一Chrome用户配置文件
Pyinstaller打包的exe启动的Chrome使用临时隔离配置,和手动打开的Chrome环境不一致,企业DRM可能依赖本地配置的认证信息。解决方法:
# 在ChromeOptions中添加现有用户配置路径 chrome_options.add_argument(r"--user-data-dir=C:\Users\你的用户名\AppData\Local\Google\Chrome\User Data") chrome_options.add_argument(r"--profile-directory=Default")
注意:启动exe前需关闭所有手动打开的Chrome窗口,避免配置文件被占用。
2. 修复PDF下载偏好配置
移除冲突的配置项,确保下载路径权限充足:
# 调整profile配置 profile = { "download.default_directory": chrome_down_path, "download.prompt_for_download": False, "download.directory_upgrade": True, "plugins.always_open_pdf_externally": True } # 提前创建下载目录,避免权限不足 if not os.path.exists(chrome_down_path): os.makedirs(chrome_down_path)
3. 优化ChromeDriver加载逻辑
改用webdriver-manager管理驱动,避免打包后的路径依赖问题:
# 替换原驱动加载代码 from selenium.webdriver.chrome.service import Service service = Service(ChromeDriverManager().install()) browser = webdriver.Chrome(service=service, options=chrome_options)
4. 调整Pyinstaller打包参数
- 优先使用
--onedir打包,减少临时路径问题:pyinstaller --onedir --hidden-import=selenium --hidden-import=chromedriver_autoinstaller --hidden-import=webdriver_manager your_script.py - 若使用
--onefile,需在代码中处理运行时路径:if getattr(sys, 'frozen', False): current_dir = os.path.dirname(sys.executable) else: current_dir = os.path.dirname(os.path.abspath(__file__))
5. 隐藏Selenium自动化特征
企业DRM可能检测自动化环境,添加参数规避检测:
chrome_options.add_argument("--disable-blink-features=AutomationControlled") chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) chrome_options.add_experimental_option('useAutomationExtension', False) # 启动后移除webdriver标记 browser.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
内容的提问来源于stack exchange,提问作者tabsize4
相关产品推荐
相关产品推荐

