python selenium+firefox 使用已打开的火狐浏览器进行操作(不需要每次都重新打开火狐)

使用selenium操作时,每次使用webdriver.Firefox()都要重新弹出火狐窗口,效率非常低,所以我一直在查,selenium能不能在已打开的浏览器上操作,发现该模块没有这个功能,那说明只能自己来了,百度了很久,只觉得这位老哥@wwwqjpcom的有帮助,那就在他研究的基础上改进下吧!原网址https://blog.csdn.net/wwwqjpcom/article/details/51232302

他的python思路是:

1.先手动打开geckodriver.exe

2.运行本体的类WebDriver,设定好url跟选定firefox,启动浏览器,然后把id跟url保存在data文件内

3.然后在另外一个py文件内获取data内的id跟url,启动自己写的myWebDriver上对已启动浏览器操作,这样就不需要再开启一个浏览器这么费劲了!!


经过测试,完全可以!

但是太特么费劲,居然还得手动运行geckodriver,还得分2个程序,不符合python的优雅性,所以我想着能不能把原selenium代码琢磨透,写出更优美的呢!!

日他奶奶个锤子,实力不够!看代码看得头晕,例如说RemoteConnection这是什么方法?是在这个文件的吗,怎么找不到,原来是从另外的文件导入的,那么再到那个文件去看,又看到一个函数,这个文件也没有啊!奶奶个锤子,又是别的文件导入,头发都挠得快没了,就像一条河,很多支流汇入,然后这些支流也有很多小溪,源头也有很多,最后都汇进了这条大河,方便是方便,好看是好看,但是回查会很痛苦,想搞懂一个方法的用途,真的很折腾,得全部吃透才行。如果pycharm能有什么功能快速回查、或者显示其方法的用途(例子会更好),这样就能很高效率的弄懂他人所写的模块了!

==================================================

回到正题,在专研简化的过程中,session_url跟session_id确实如原博主所说,这就是selenium的关键,只要在启动的程序中替换了webdriver随机产生的id跟url,就不需要重新开启一个浏览器了,而geckodriver.exe就是关键,想要通过selenium启动firefox,就得靠这个程序。

默认的webdriver.Firefox()运行时,先是启动gecko,打开火狐浏览器,代码运行结束后,gecko也跟着关闭。我试着把代码延时,在另外的py文件中运行原博主的myfirefox,发现可以在该浏览器操作,所以想要有这个效果,那么gecko就得持续开着!


所以此时思路有2个,一是修改firefox()代码,让gecko不关闭,但是追踪了下,原来gecko的启动在另外的文件,如果要修改,会非常麻烦,而且怕影响其他程序,所以只能采取第二种了

那就是整个selenium最核心的webdriver了——webdriver.remote.webdriver.WebDriver(),也就是原博主使用的那个,用它来启动浏览器,而且还得持续开着geckodriver.exe,然后用myfirefox在启动了的火狐浏览器操作。

说几点要注意的:

1.运行程序中没有geckodrive,myfirefox会报错

2.有了geckodriver,但是没有火狐没启动,或者不是对应的ID、url,还是报错

3.用webdriver启动的浏览器,第一个窗口不能关!!!!关了就出错,可能第一个窗口就是对应的ID


好了,那么现在再梳理梳理,具体操作如下

·   当geckodriver.exe没运行,那就先启动,然后调用WebDriver(),     启动浏览器,然后把ID跟URL保存在data文件内

·   那么geckodriver.exe运行,而火狐不在,那么能用WebDriver() 吗?或者是myFirefox? 都不行,会显示错误Message: Session is already started !! 那么Firefox() 呢?肯定行!但有个卵蛋用,不能在它上面操作啊!

      所以解决方法就是把已经存在的geckodriver.exe结束程序,然后运行第一步!

·   除了上面的情况,还有可能已经打开的火狐跟geckodriver不是对应的,或者手抖把第一个窗口给关了,那么使用myFirefox 都会报错,所以我使用了try,一旦不行,那么就结束程序,重新打开浏览器

要点

1  使用初始webdriver启动火狐浏览器

2  使用原博主自编的myfirefox 在原浏览器操作

3  pickle 保存字典

4  使用win32api模块 打开程序

使用psutil模块检测后台程序,关闭程序

import os,pickle, psutil,win32api,logging
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver import myFirefox

class myfox():
    '''目的:不需要每次都重新打开浏览器'''
    def __init__(self):
        self.file=r'C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\selenium\webdriver\firefox\params.data'
        self.gecko=r'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\Scripts\geckodriver.exe'
        self.url="http://127.0.0.1:4444"
        self.capabilities=DesiredCapabilities.FIREFOX  #实际就是选定firefox浏览器

    def creatfirefox(self):
        '''先运行geckodriver,启动浏览器,记录IDURL,返回driver'''
        win32api.ShellExecute(0, 'open', self.gecko, '', '', 0)  # 先在后台运行geckodriver
        driver = webdriver.remote.webdriver.WebDriver(command_executor=self.url,
                                                      desired_capabilities=self.capabilities,
                                                      )
        params={}
        params["session_id"] = driver.session_id
        params["server_url"] = driver.command_executor._url
        with open(self.file,'wb') as f:
            pickle.dump(params, f)
        return driver

    def work(self):
        '''先判断geckodriver启动没有,没启动就直接运行,启动了先try,不行就删除geckodriver,再次运行friefox'''
        p_name = [psutil.Process(i).name() for i in psutil.pids()]#罗列进程的程序,如果gecko没有,直接创建启动
        if 'geckodriver.exe' not in p_name:
            driver=self.creatfirefox()
        else:
            try: #已经有gecko了,试试能不能在旧的浏览器上执行myfirefox(有可能对应的浏览器已经关闭了)
                with open(self.file, 'rb') as f:
                    params = pickle.load(f)
                driver = myFirefox.myWebDriver(service_url=params["server_url"], session_id=params["session_id"])
                driver.refresh()
            except Exception as e:
                #当不能直接在旧浏览器上操作时,那就删了gecko重新再运行
                logging.error('浏览器跟geckodriver不对应!!\n%s'% e)
                [p.kill() for p in psutil.process_iter() if p.name() == 'geckodriver.exe']
                #os.system("taskkill /F /IM geckodriver.exe") 这种方法会有乱码!!
                driver = self.creatfirefox()
        return driver

driver=myfox().work()
driver.get('http://www.baidu.com/')



这是原博主的myfirefox

try:
  import http.client as http_client
  except ImportError:
  import httplib as http_client
  import socket
  from selenium.webdriver.firefox.webdriver import WebDriver as Firefox
  from selenium.webdriver.firefox.remote_connection import FirefoxRemoteConnection
  from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
  from selenium.webdriver.remote.remote_connection import RemoteConnection
  from selenium.webdriver.remote.errorhandler import ErrorHandler
  from selenium.webdriver.remote.switch_to import SwitchTo
  from selenium.webdriver.remote.mobile import Mobile
  from selenium.webdriver.remote.file_detector import FileDetector, LocalFileDetector
  from selenium.webdriver.remote.command import Command
   
  class myWebDriver(Firefox):
  def __init__(self, capabilities=None, service_url=None, session_id=None):
  if service_url is None and session_id is None:
  raise NameError
   
  if capabilities is None:
  capabilities = DesiredCapabilities.FIREFOX.copy()
   
  self.capabilities = dict(capabilities)
   
  self.w3c = True
   
  executor = FirefoxRemoteConnection(remote_server_addr=service_url)
  self.session_id=session_id
  self.command_executor = executor
  self.command_executor.w3c = self.w3c
  if type(self.command_executor) is bytes or isinstance(self.command_executor, str):
  self.command_executor = RemoteConnection(self.command_executor, keep_alive=True)
  self._is_remote = True
  self.error_handler = ErrorHandler()
  self._switch_to = SwitchTo(self)
  self._mobile = Mobile(self)
  self.file_detector = LocalFileDetector()
  def quit(self):
  """Quits the driver and close every associated window."""
  try:
  self.execute(Command.QUIT)
  except (http_client.BadStatusLine, socket.error):
  # Happens if Firefox shutsdown before we've read the response from
  # the socket.
  pass


实际操作



这时因为已经关了火狐,只留下geckodriver没关

python selenium+firefox 使用已打开的火狐浏览器进行操作(不需要每次都重新打开火狐)_第1张图片


成功打开了!!!

然后在这基础上操作

打开百度,搜索python

python selenium+firefox 使用已打开的火狐浏览器进行操作(不需要每次都重新打开火狐)_第2张图片

python selenium+firefox 使用已打开的火狐浏览器进行操作(不需要每次都重新打开火狐)_第3张图片


成功了!!收工!







你可能感兴趣的:(python selenium+firefox 使用已打开的火狐浏览器进行操作(不需要每次都重新打开火狐))