Selenium源碼分析之chromedriver的設(shè)置

ide:pycharm铝噩;
language:python衡蚂;
selenium:3.141.0

啟動(dòng)pycharm,并創(chuàng)建名為seleniumHQ的工程骏庸,創(chuàng)建一個(gè)py文件毛甲,輸入如下代碼:

if __name__ == '__main__':
    from selenium.webdriver.chrome.webdriver import WebDriver
    path="/Users/apple/Seleniumdriver/chromedriver"
    driver = WebDriver(executable_path=path)
    driver.get("https://www.baidu.com")
    driver.close()
    driver.quit()

進(jìn)入WebDriver類源碼

class WebDriver(RemoteWebDriver):
    """
    Controls the ChromeDriver and allows you to drive the browser.

    You will need to download the ChromeDriver executable from
    http://chromedriver.storage.googleapis.com/index.html
    """

    def __init__(self, executable_path="chromedriver", port=0,
                 options=None, service_args=None,
                 desired_capabilities=None, service_log_path=None,
                 chrome_options=None, keep_alive=True):
        """
        Creates a new instance of the chrome driver.

        Starts the service and then creates new instance of chrome driver.

        :Args:
         - executable_path - path to the executable. If the default is used it assumes the executable is in the $PATH
         - port - port you would like the service to run, if left as 0, a free port will be found.
         - options - this takes an instance of ChromeOptions
         - service_args - List of args to pass to the driver service
         - desired_capabilities - Dictionary object with non-browser specific
           capabilities only, such as "proxy" or "loggingPref".
         - service_log_path - Where to log information from the driver.
         - chrome_options - Deprecated argument for options
         - keep_alive - Whether to configure ChromeRemoteConnection to use HTTP keep-alive.
        """
        if chrome_options:
            warnings.warn('use options instead of chrome_options',
                          DeprecationWarning, stacklevel=2)
            options = chrome_options

        if options is None:
            # desired_capabilities stays as passed in
            if desired_capabilities is None:
                desired_capabilities = self.create_options().to_capabilities()
        else:
            if desired_capabilities is None:
                desired_capabilities = options.to_capabilities()
            else:
                desired_capabilities.update(options.to_capabilities())

        self.service = Service(
            executable_path,
            port=port,
            service_args=service_args,
            log_path=service_log_path)
        self.service.start()

        try:
            RemoteWebDriver.__init__(
                self,
                command_executor=ChromeRemoteConnection(
                    remote_server_addr=self.service.service_url,
                    keep_alive=keep_alive),
                desired_capabilities=desired_capabilities)
        except Exception:
            self.quit()
            raise
        self._is_remote = False

其構(gòu)造函數(shù)入?yún)xecutable_path默認(rèn)為“chromedriver”,在其init方法中具被,創(chuàng)建了一個(gè)Service類實(shí)例service玻募,executable_path作為了Service類init方法的入?yún)ⅰxecutable_path在WebDriver源碼中僅僅出現(xiàn)在該處一姿,說(shuō)明WebDriver在處理executable_path的過(guò)程中七咧,僅僅只起到傳遞值的作用。實(shí)際處理executable_path并不在WebDriver叮叹。
進(jìn)入Service類源碼艾栋,

class Service(service.Service):
    """
    Object that manages the starting and stopping of the ChromeDriver
    """

    def __init__(self, executable_path, port=0, service_args=None,
                 log_path=None, env=None):
        """
        Creates a new instance of the Service

        :Args:
         - executable_path : Path to the ChromeDriver
         - port : Port the service is running on
         - service_args : List of args to pass to the chromedriver service
         - log_path : Path for the chromedriver service to log to"""

        self.service_args = service_args or []
        if log_path:
            self.service_args.append('--log-path=%s' % log_path)

        service.Service.__init__(self, executable_path, port=port, env=env,
                                 start_error_message="Please see https://sites.google.com/a/chromium.org/chromedriver/home")

init方法中將executable_path傳遞給了其父類的init方法,整個(gè)Service類init方法中僅將executable_path傳遞給了父類的init方法蛉顽,未做其他處理蝗砾。
進(jìn)入Service的父類Service源碼,

class Service(object):

    def __init__(self, executable, port=0, log_file=DEVNULL, env=None, start_error_message=""):
        self.path = executable

        self.port = port
        if self.port == 0:
            self.port = utils.free_port()

        if not _HAS_NATIVE_DEVNULL and log_file == DEVNULL:
            log_file = open(os.devnull, 'wb')

        self.start_error_message = start_error_message
        self.log_file = log_file
        self.env = env or os.environ

init方法僅僅只是將executable存儲(chǔ)下來(lái)携冤,存在了self.path中悼粮,到此,executable_path的傳遞過(guò)程就結(jié)束了曾棕,但是我們?nèi)晕粗浪挥迷谑裁吹胤健?/p>

既然executable_path被存儲(chǔ)在了self.path中矮锈,path是Service的一個(gè)實(shí)例屬性,那么它只可能被Service類的方法所使用睁蕾,回顧先前的代碼,WebDriver類創(chuàng)建了Service類的實(shí)例service债朵,緊接著就調(diào)用了service.start()子眶,進(jìn)入start方法,

    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=platform.system() != 'Windows',
                                            stdout=self.log_file,
                                            stderr=self.log_file,
                                            stdin=PIPE)
        except TypeError:
            raise
        except OSError as err:
            if err.errno == errno.ENOENT:
                raise WebDriverException(
                    "'%s' executable needs to be in PATH. %s" % (
                        os.path.basename(self.path), self.start_error_message)
                )
            elif err.errno == errno.EACCES:
                raise WebDriverException(
                    "'%s' executable may have wrong permissions. %s" % (
                        os.path.basename(self.path), self.start_error_message)
                )
            else:
                raise
        except Exception as e:
            raise WebDriverException(
                "The executable %s needs to be available in the path. %s\n%s" %
                (os.path.basename(self.path), self.start_error_message, str(e)))
        count = 0
        while True:
            self.assert_process_still_running()
            if self.is_connectable():
                break
            count += 1
            time.sleep(1)
            if count == 30:
                raise WebDriverException("Can not connect to the Service %s" % self.path)

在start方法中序芦,主要都是try...except的實(shí)現(xiàn)臭杰。
其中將self.path放在了list類實(shí)例cmd中,并將cmd作為了參數(shù)傳給subprocess.Popen函數(shù)谚中。而subprocess.Popen函數(shù)即相當(dāng)于在命令行執(zhí)行了cmd命令渴杆。

所以為selenium的WebDriver init方法配置executable_path可以有兩種方法:
一:將chromedriver的路徑加入到環(huán)境變量Path中寥枝,而不用給WebDriver的構(gòu)造方法傳遞任何參數(shù),因?yàn)橐呀?jīng)有了默認(rèn)參數(shù)“chromedriver”磁奖;
二:不必配置環(huán)境變量囊拜,直接給WebDriver的init方法傳遞chromedriver的絕對(duì)地址,即WebDriver(executable_path=path)比搭;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冠跷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子身诺,更是在濱河造成了極大的恐慌蜜托,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霉赡,死亡現(xiàn)場(chǎng)離奇詭異橄务,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)穴亏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)蜂挪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人迫肖,你說(shuō)我怎么就攤上這事锅劝。” “怎么了蟆湖?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵故爵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我隅津,道長(zhǎng)诬垂,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任伦仍,我火速辦了婚禮结窘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘充蓝。我一直安慰自己隧枫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布谓苟。 她就那樣靜靜地躺著官脓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涝焙。 梳的紋絲不亂的頭發(fā)上卑笨,一...
    開(kāi)封第一講書(shū)人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音仑撞,去河邊找鬼赤兴。 笑死妖滔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桶良。 我是一名探鬼主播座舍,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼艺普!你這毒婦竟也來(lái)了簸州?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤歧譬,失蹤者是張志新(化名)和其女友劉穎岸浑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瑰步,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矢洲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缩焦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片读虏。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖袁滥,靈堂內(nèi)的尸體忽然破棺而出盖桥,到底是詐尸還是另有隱情,我是刑警寧澤题翻,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布揩徊,位于F島的核電站,受9級(jí)特大地震影響嵌赠,放射性物質(zhì)發(fā)生泄漏塑荒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一姜挺、第九天 我趴在偏房一處隱蔽的房頂上張望齿税。 院中可真熱鬧,春花似錦炊豪、人聲如沸凌箕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)陌知。三九已至,卻和暖如春掖肋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赏参。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工志笼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沿盅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓纫溃,卻偏偏與公主長(zhǎng)得像腰涧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子紊浩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容