pyinstaller+selenium+chrome+chromedriver打包exe

1. 需求

win10x86环境集成selenium+chrome+chromeDriver打包输出exe

2. 环境初始化

# 相关版本
python=3.7.8
pyinstaller=5.5
selenium=4.5.0
selenium-wire=5.0.0 
ps: 
	selenium-wire可选不用安装-selenium扩展库(用于监听浏览器请求响应方便输出结果=请求头、响应头等)
	selenium也可通过日志方式获取到相关请求信息

# 安装
pip install pyinstaller 
pip install selenium
pip install selenium-wire
# 加速源(可选) -i https://pypi.tuna.tsinghua.edu.cn/simple

3. 相关代码

import sys
# from seleniumwire import webdriver as wb
from selenium import webdriver as wb
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    
    def get_login_info():
        """
        登录获取后续登录界面所需授权信息
        :return:
        """
        # 1. 浏览器参数初始化
        chrome_driver = r"resources/chromedriver_v106.exe"  # 浏览器驱动
        chrome_app = r"resources/chrome.exe"  # 浏览器
        chrome_driver = ExeUtils.get_resources(chrome_driver)
        chrome_app = ExeUtils.get_resources(chrome_app)
        capabilities = DesiredCapabilities.CHROME  # 用于监听selenium请求事件(日志信息=请求+响应)
        capabilities["goog:loggingPrefs"] = {"performance": "ALL"}
        s = Service(chrome_driver)
        chrome_options = wb.ChromeOptions()
        chrome_options.add_experimental_option("excludeSwitches", ['enable-automation'])  # 反检测
        chrome_options.add_argument("--no-sandbox")  # 最高权限运行
        chrome_options.add_argument("--headless")  # 无页面运行
        chrome_options.add_argument("--disable-gpu")  # 禁用gpu
        chrome_options.add_argument("disable-cache")  # 禁用缓存
        chrome_options.add_argument("--disable-extensions")  # 禁用扩展插件
        chrome_options.binary_location = chrome_app  # 添加浏览器
        # chrome_options.add_argument("--proxy-server=http://ip:port")  # 设置代理
        # chrome_options.add_argument("--start-maxmized")  # 窗口最大化
        b = wb.Chrome(service=s, options=chrome_options,desired_capabilities=capabilities)
        try:
            login_url = "xxxx"
            b.get(login_url)
            # 2. 【登录页面】
            # 2.1 账号密码
            b.find_element(by=By.XPATH, value='//*[@id="username"]').send_keys(username)  # xpath方式定位元素标签后输入内容
            b.find_element(by=By.XPATH, value='//*[@id="password"]').send_keys(password)
            # 2.2 省份
            province_element = b.find_element(by=By.XPATH, value='//*[@id="dk_container_system"]/a')
            province_element.click()  # 点击事件
            time.sleep(1)
            selected_province = b.find_element(by=By.XPATH, value='//*[@id="dk_container_system"]/div/ul/li[16]')
            selected_province.click()
            # print("selectedProvince:", province_element.text)
            # 2.3 点击登录
            b.find_element(by=By.XPATH, value='//*[@id="passwordBox"]/section[6]/input[4]').click()
            # print("loginSuccess")
            self.logger.info("SeleniumLoginSuccess")
            time.sleep(15)
            # 3. 【首页】-302多次跳转后的页面
            # 3.1 切换到最后跳转的页面
            page_num = b.window_handles  # 当前页
            b.switch_to.window(page_num[-1])  # 切换到新窗口
            b.refresh()  # 刷新页面->屏蔽弹出的公告栏
            time.sleep(5)
            b.get_screenshot_as_file(f"{screen_shot}/index.png")
            time.sleep(5)
            # 3.2 【我的数据列表】-页面局部刷新跳转到工单数据列表页
            b.switch_to.frame("iframe_home")  # iframe-xpath定位
            b.find_element(by=By.XPATH, value='//*[@id="CLAIM"]/div[1]/div[2]/span/span/button').click()
            b.switch_to.default_content()  # 跳转到之前页面
            time.sleep(5)
            b.get_screenshot_as_file(f"{screen_shot}/claimList.png")  # 保存截屏图片
            time.sleep(5)
            # 3.3 获取用户登录授权信息-Cookies&CSRF
            # 3.3.1 使用selenium事件监听-日志巡检获取
            logs = b.get_log("performance")
            for entry in logs:
                # "Network.request":请求信息;"Network.response":响应信息;
                log = json.loads(entry["message"])["message"]
                if "Network.request" not in log["method"]:
                    continue
                if not log.get("xx"):
                    continue
                tmp_headers = log.get("xx").get("headers")
                if not tmp_headers:
                    continue
                if "Cookies" not in tmp_headers or "CSRF" not in tmp_headers:
                    continue
                cookie_val = tmp_headers.get("Cookies")
                csrf_val = tmp_headers.get("CSRF")
                if "SESSIONID" not in cookie_val and "oneapm" not in cookie_val and not csrf_val:
                    continue
                headers = {"Cookies": cookie_val, "CSRF": csrf_val}
                break
            # 3.3.2 使用selenium-wire获取所需授权信息(wb导入对象也需要更换)
            # for request in b.requests:
            #     if request.response:
            #         if request.url == "xxxx":
            #             headers["CSRF"] = request.headers.get("CSRF")
            #             headers["Cookies"] = request.headers.get("Cookies")
            #             break
        except Exception as e:
            self.logger.error(f"getLoginInfoError:{e}", exc_info=True)
        self.login_info = headers
        self.logger.info(f"getLoginInfo:{login_info}")
        b.close()  
        
  class ExeUtils:
    """exe生成相关工具类"""
    @staticmethod
    def get_resources(path):
        """
        获取实际的资源访问路径(本地||临时)
        根据打包生成的临时目录访问资源
        或者直接运行脚本获取本地访问资源
        :param path:
        :return:
        """
        if getattr(sys, 'frozen', False):
            base_path = sys._MEIPASS
        else:
            base_path = os.path.abspath(".")
        return os.path.join(base_path, path)

4. 生成exe

# 目录结构
----spider  # 项目目录
----spider/resources  # 资源目录
----spider/resources/chrome.exe  # 浏览器(需要把浏览器chrome.exe同级目录的所有文件均包含而不只是exe)
----spider/resources/chromedriver.exe # 浏览器驱动
----spider/spider.py  # 程序入口文件

# 命令
# 切换到虚拟环境(项目运行环境)
cd spider 
pyinstaller -Fw  --add-data="resources;resources" --clean spider.py
	-F:单文件模式;资源整合到exe
	-w:无命令行窗口
	--add-data: 资源文件
	--clean: 清楚缓存
	-n: exe程序名
	--add-binary: 可执行程序资源(单独打包整合其他exe)
# 也可以通过先生成*.spec文件后生成exe
pyi-makespec -F spider.py
修改*.spec
pyinstaller -F *.spec


# 相关输出
"""
...
121277 INFO: checking EXE
121278 INFO: Building EXE because EXE-00.toc is non existent
121278 INFO: Building EXE from EXE-00.toc
121278 INFO: Copying bootloader EXE to F:\work\workProject\spider\dist\spider.exe.notanexecutable
121298 INFO: Copying icon to EXE
121300 INFO: Copying icons from ['e:\\study\\python\\python_env\\env_spider\\lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-windowe
d.ico']
121301 INFO: Writing RT_GROUP_ICON 0 resource with 104 bytes
121301 INFO: Writing RT_ICON 1 resource with 3752 bytes
121302 INFO: Writing RT_ICON 2 resource with 2216 bytes
121302 INFO: Writing RT_ICON 3 resource with 1384 bytes
121303 INFO: Writing RT_ICON 4 resource with 38188 bytes
121315 INFO: Embedding manifest in EXE
121316 INFO: Updating manifest in F:\work\workProject\spider\dist\spider.exe.notanexecutable
121317 INFO: Updating resource type 24 name 1 language 0
121328 INFO: Appending PKG archive to EXE
121617 INFO: Fixing EXE headers
124514 INFO: Building EXE from EXE-00.toc completed successfully.
"""

5. 其他问题

# selenium弹窗问题
from selenium.webdriver.common.service import xxx # 通过导包进到service.py修改源码
	
    def start(self):
        """
        Starts the Service.

        :Exceptions:
         - WebDriverException : Raised either when it can't start the service
           or when it can't connect to the service
        """
        try:
            cmd = [self.path]
            cmd.extend(self.command_line_args())
            self.process = subprocess.Popen(cmd, env=self.env,
                                            close_fds=system() != 'Windows',
                                            stdout=self.log_file,
                                            stderr=self.log_file,
                                            stdin=PIPE,
                                            # 打包成exe修改了源码creationflags=134217728
                                            # creationflags=self.creationflags,
                                            creationflags=134217728,
                                            )
        except TypeError:
            raise

6. 相关文档

[1] pyinstaller官网:https://pyinstaller.org/en/stable/usage.html

posted @ 2022-10-18 15:20  爱编程_喵  阅读(3691)  评论(0)    收藏  举报
jQuery火箭图标返回顶部代码

jQuery火箭图标返回顶部代码

滚动滑动条后,查看右下角查看效果。很炫哦!!

适用浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗.