Pyinstaller打包Selenium脚本为exe后异常问题求助
咱们一步步拆解你遇到的这些问题,逐个击破:
1. 核心报错:Can't find profile directory(无头模式下的Firefox配置问题)
你看到的resource://gre/modules/XULStore.jsm, line 66: Error: Can't find profile directory是无头模式下Firefox的常见坑——默认无头启动时没有正确初始化用户配置文件。解决方法很简单,给FirefoxOptions添加几个参数强制指定临时profile:
import tempfile # 需要先导入这个模块 options = Options() options.headless = True # 添加这两行解决profile目录缺失问题 options.add_argument("--no-remote") options.add_argument("--profile") options.add_argument(tempfile.mkdtemp())
2. exe无输出 & 弹出geckodriver窗口
用PyInstaller打包时,默认是--windowed(无控制台)模式,所以你在CMD里运行看不到任何输出,还会弹出geckodriver的黑窗口。打包时要切换到控制台模式,同时给Firefox加静默参数:
# 打包命令加上--console参数 pyinstaller --console --onefile your_script.py
另外给options补充两个参数,彻底避免弹窗:
options.add_argument("--disable-gpu") options.add_argument("--silent")
3. token.txt不生成:工作目录踩坑
exe运行时的当前工作目录不一定是你存放exe的文件夹——比如管理员权限运行时,默认目录可能是C:\Windows\System32,导致文件写在了你找不到的地方。解决方法是用脚本的绝对路径来保存文件:
import os # 获取当前脚本/ exe所在的绝对目录 script_dir = os.path.dirname(os.path.abspath(__file__)) # 拼接token.txt的绝对路径 token_path = os.path.join(script_dir, "token.txt") # 后续写入文件时用这个路径 with open(token_path, "w", encoding="utf-8") as f: for key, value in sorted(counted.items(), key=lambda item: item[1]): stri = f"{key}: {value}\n" f.write(stri)
4. 隔一次启动失败:残留进程搞鬼
你的脚本最后没有调用driver.quit(),导致geckodriver进程一直残留,下次启动时端口被占用或者资源冲突,就会出现Failed to execute script Etherscrape错误。一定要在脚本结束前强制关闭driver:
# 所有操作完成后,或者用try-finally确保无论出错都关闭 driver.quit()
5. 防火墙权限问题
非管理员运行时弹出防火墙请求,是因为geckodriver需要建立网络连接访问etherscan.io。你可以直接在Windows防火墙里给geckodriver.exe添加允许规则,或者打包时把geckodriver和exe绑定在一起(用PyInstaller的--add-binary参数),避免单独的geckodriver触发防火墙提示。
修改后的完整脚本
from selenium import webdriver from selenium.webdriver.firefox.options import Options from collections import defaultdict import os import tempfile counted = defaultdict(int) tokenliste = [] options = Options() options.headless = True # 解决无头模式profile缺失问题 options.add_argument("--no-remote") options.add_argument("--profile") options.add_argument(tempfile.mkdtemp()) # 静默运行,避免弹窗 options.add_argument("--disable-gpu") options.add_argument("--silent") driver = webdriver.Firefox(options=options) # 注意:新版Selenium已弃用firefox_options,改用options try: for x in range(1,10): my_url = f"https://etherscan.io/tokentxns?ps=100&p={x}" # 用f-string更简洁易读 driver.get(my_url) for i in range(1,100): xpath = f"/html/body/div[1]/main/div[2]/div/div/div[2]/table/tbody/tr[{i}]/td[9]/a" try: p_element = driver.find_element_by_xpath(xpath) tokenliste.append(p_element.text) except Exception as e: # 加个异常处理,避免某一行元素找不到导致整个脚本崩溃 print(f"第{x}页第{i}行元素找不到: {e}") continue for x in tokenliste: counted[x] += 1 print(counted) # 用绝对路径保存token.txt,确保能找到文件 script_dir = os.path.dirname(os.path.abspath(__file__)) token_path = os.path.join(script_dir, "token.txt") with open(token_path, "w", encoding="utf-8") as f: for key, value in sorted(counted.items(), key=lambda item: item[1]): stri = f"{key}: {value}\n" f.write(stri) finally: # 无论脚本是否出错,都确保关闭driver,避免残留进程 driver.quit()
打包命令建议
如果geckodriver不在系统PATH里,打包时要指定它的路径:
pyinstaller --console --onefile --add-binary "geckodriver.exe;." your_script.py
内容的提问来源于stack exchange,提问作者Codec42

