写好了Python selenium脚本,到其他机器上运行,还得要在其他机器上也装一套Python的环境,尤其在你用了一些第三方库的时候,甚至还要顾及操作系统是32位还是64位,是不是很坑,如果能打成一个exe就好了,不论32位还是64位,只要拷过去,安装合适版本的浏览器就行了。今天博主就带你将你的py脚本打包成一个exe
1. 环境
-
首先准备下环境,一台32位虚拟机(64位的py2exe不允许将程序打包成1个exe文件),装有你脚本执行需要的Python版本以及所有的三方库(确保在这台机器上能够执行你的脚本),安装跟你Python版本对应的py2exe包。
-
想要打包的py脚本,下面是一个简单的打开chrome并访问灰蓝博客的例子 blog.py
:
from selenium import webdriver
import time
driver = webdriver.Chrome(executable_path='chromedriver.exe')
driver.get('http://blog.csdn.net/huilan_same')
time.sleep(5)
driver.quit()
现在我们就把这个小脚本打成一个exe
2. setup
我们创建另一个打包脚本 setup.py
from distutils.core import setup
import py2exe, sys
sys.argv.append('py2exe')
options = {"py2exe": {
"compressed": 1,
"optimize": 2,
"bundle_files": 1,
}}
setup(
console=[{'script': "blog.py", "icon_resources": [(1, "robot.ico")]}],
options=options,
zipfile=None
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
我给程序加了图标,图标文件robot.ico也放在同一目录下,然后我们执行这个脚本,能够看到cmd中一系列的打包操作后创建了两个文件夹build和dist,其中,真正对我们有用的只是 dist
中的 blog.exe
文件(与py脚本同名),还会有一个 w9xpopen.exe
,这个是用于win9x系统使用的,没有意义。
注:这里博主不再详细讲解py2exe的用法,关于脚本内容感兴趣可以自行百度相关知识
取出 blog.exe
,同目录下放 chromedriver.exe
(注意版本),双击执行即可
这下,不用每次都搞环境了。
3. 执行firefox
上面我故意选了chrome作为例子,而非firefox,是由于firefox比较特殊,像上面一样只是把
driver = webdriver.Chrome(executable_path='chromedriver.exe')
改成
driver = webdriver.Firefox()
的话,打包成功但执行时会报如下错误:
少打了 webdriver_pref.json
文件,曾在stackoverflow上看到过一种解决办法是修改打包参数并把resource文件都copy过来,这种打出来之后会是一个臃肿的文件夹,后来博主便不用这种办法了。
那怎么办,看报错是少了一个json文件,那么能否把这个json文件直接写进我们的脚本里呢,所以博主便去看源码,发现主要是FirefoxProfile
类的 __init__()
用到了,既然如此,我们便继承过来并重写了此方法即可:
同时,我们还发现另一个引用 webdriver.xpi
,此文件在selenium2中相当于firefox的驱动,在启动firefox时会以插件的形式导入。所以add_extension()
方法也需要重写。
最后,代码如下:
from selenium import webdriver
import time
import copy
import json
import tempfile
import shutil
import os
WEBDRIVER_PREFERENCES = """
{
"frozen": {
"app.update.auto": false,
"app.update.enabled": false,
"browser.displayedE10SNotice": 4,
"browser.download.manager.showWhenStarting": false,
"browser.EULA.override": true,
"browser.EULA.3.accepted": true,
"browser.link.open_external": 2,
"browser.link.open_newwindow": 2,
"browser.offline": false,
"browser.reader.detectedFirstArticle": true,
"browser.safebrowsing.enabled": false,
"browser.safebrowsing.malware.enabled": false,
"browser.search.update": false,
"browser.selfsupport.url" : "",
"browser.sessionstore.resume_from_crash": false,
"browser.shell.checkDefaultBrowser": false,
"browser.tabs.warnOnClose": false,
"browser.tabs.warnOnOpen": false,
"datareporting.healthreport.service.enabled": false,
"datareporting.healthreport.uploadEnabled": false,
"datareporting.healthreport.service.firstRun": false,
"datareporting.healthreport.logging.consoleEnabled": false,
"datareporting.policy.dataSubmissionEnabled": false,
"datareporting.policy.dataSubmissionPolicyAccepted": false,
"devtools.errorconsole.enabled": true,
"dom.disable_open_during_load": false,
"extensions.autoDisableScopes": 10,
"extensions.blocklist.enabled": false,
"extensions.checkCompatibility.nightly": false,
"extensions.logging.enabled": true,
"extensions.update.enabled": false,
"extensions.update.notifyUser": false,
"javascript.enabled": true,
"network.manage-offline-status": false,
"network.http.phishy-userpass-length": 255,
"offline-apps.allow_by_default": true,
"prompts.tab_modal.enabled": false,
"security.csp.enable": false,
"security.fileuri.origin_policy": 3,
"security.fileuri.strict_origin_policy": false,
"security.warn_entering_secure": false,
"security.warn_entering_secure.show_once": false,
"security.warn_entering_weak": false,
"security.warn_entering_weak.show_once": false,
"security.warn_leaving_secure": false,
"security.warn_leaving_secure.show_once": false,
"security.warn_submit_insecure": false,
"security.warn_viewing_mixed": false,
"security.warn_viewing_mixed.show_once": false,
"signon.rememberSignons": false,
"toolkit.networkmanager.disable": true,
"toolkit.telemetry.prompted": 2,
"toolkit.telemetry.enabled": false,
"toolkit.telemetry.rejected": true,
"xpinstall.signatures.required": false,
"xpinstall.whitelist.required": false
},
"mutable": {
"browser.dom.window.dump.enabled": true,
"browser.laterrun.enabled": false,
"browser.newtab.url": "about:blank",
"browser.newtabpage.enabled": false,
"browser.startup.page": 0,
"browser.startup.homepage": "about:blank",
"browser.usedOnWindows10.introURL": "about:blank",
"dom.max_chrome_script_run_time": 30,
"dom.max_script_run_time": 30,
"dom.report_all_js_exceptions": true,
"javascript.options.showInConsole": true,
"network.http.max-connections-per-server": 10,
"startup.homepage_welcome_url": "about:blank",
"startup.homepage_welcome_url.additional": "about:blank",
"webdriver_accept_untrusted_certs": true,
"webdriver_assume_untrusted_issuer": true
}
}
"""
class FirefoxProfile(webdriver.FirefoxProfile):
""" Rewrite FirefoxProfile, to avoid 'No such file ... webdriver.xpi/pref.json' exception"""
def __init__(self, profile_directory=None):
if not FirefoxProfile.DEFAULT_PREFERENCES:
FirefoxProfile.DEFAULT_PREFERENCES = json.loads(WEBDRIVER_PREFERENCES)
self.default_preferences = copy.deepcopy(
FirefoxProfile.DEFAULT_PREFERENCES['mutable'])
self.native_events_enabled = True
self.profile_dir = profile_directory
self.tempfolder = None
if self.profile_dir is None:
self.profile_dir = self._create_tempfolder()
else:
self.tempfolder = tempfile.mkdtemp()
newprof = os.path.join(self.tempfolder, "webdriver-py-profilecopy")
shutil.copytree(self.profile_dir, newprof,
ignore=shutil.ignore_patterns("parent.lock", "lock", ".parentlock"))
self.profile_dir = newprof
self._read_existing_userjs(os.path.join(self.profile_dir, "user.js"))
self.extensionsDir = os.path.join(self.profile_dir, "extensions")
self.userPrefs = os.path.join(self.profile_dir, "user.js")
def update_preferences(self):
for key, value in self.DEFAULT_PREFERENCES['frozen'].items():
self.default_preferences[key] = value
self._write_user_prefs(self.default_preferences)
def add_extension(self, extension=os.path.abspath('webdriver.xpi')):
self._install_extension(extension)
profile = FirefoxProfile()
driver = webdriver.Firefox(firefox_profile=profile)
driver.get('http://blog.csdn.net/huilan_same')
time.sleep(5)
driver.quit()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
我们再次打包,把 webdriver.xpi
拷贝出来到程序目录下,再次双击执行blog.exe
,bingo,可以执行了。
4. 扩展
这时你的脚本就可以在不同的win环境下跑了,如果加上yaml文件作为配置文件、excel作为数据文件、并加上日志,如果有时间还可以加上gui,就可以做一个可配置的网页自动填表程序出来了,自己动手吧。
注意:
以上所有示例均为Python2.7 + selenium 2.53版本的,chrome只要跟chromedriver版本匹配即可;如果你用的selenium3.x,对于firefox48及以上的版本,需要用到geckdriver,具体的自己看源码做相应改动吧。
更多关于python selenium的文章,请关注我的CSDN专栏:Python Selenium自动化测试详解
最后,博主最近新建了一个QQ群,用于Python Selenium的技术交流,专注于Python+Selenium的技术交流与分享,感兴趣的同学可以加群(455478219),也可直接点击下面的图片加群:
欢迎来跟博主讨论Python Selenium有关的问题。
所有评论(0)