談談Selenium中的日誌

松勤吳老師發表於2023-03-16

談談Selenium中的日誌

  • 來源於一位同學,“老師為啥firefox執行後會有日誌檔案,chrome沒有呢?”

比對

  • 你開啟chrome瀏覽器

    from selenium import webdriver
    driver = webdriver.Chrome()
    
  • 這樣是沒有日誌的

  • 同樣的程式碼,你開啟firefox

    from selenium import webdriver
    driver = webdriver.Firefox()
    
  • 就會有個日誌檔案geckodriver.log生成,預設在你上面程式碼所在目錄

  • 內容大致如下

    1678943199197	geckodriver	INFO	Listening on 127.0.0.1:8695
    1678943202290	mozrunner::runner	INFO	Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "--marionette" "--remote-debugging-port" "8696" "-no-remote" "-profile" "C:\\Users\\SONGQI~1\\AppData\\Local\\Temp\\rust_mozprofileNtWGR9"
    1678943202558	Marionette	INFO	Marionette enabled
    Dynamically enable window occlusion 0
    1678943202562	Marionette	INFO	Listening on port 8705
    WebDriver BiDi listening on ws://127.0.0.1:8696
    1678943202947	RemoteAgent	WARN	TLS certificate errors will be ignored for this session
    console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at C:\\Users\\SONGQI~1\\AppData\\Local\\Temp\\rust_mozprofileNtWGR9\\search.json.mozlz4", (void 0)))
    DevTools listening on ws://127.0.0.1:8696/devtools/browser/791df03a-8db6-429b-969a-32cd077b3c2f
    
    
  • 的確是這樣的,chrome和firefox2個瀏覽器在selenium中的api都是有差異的

  • 下面的程式碼可以讓你看到2者獨有的那些api

    from selenium import webdriver
    driver1 = webdriver.Chrome()
    driver2 = webdriver.Firefox()
    set_of_chrome_api = set([_ for _ in dir(driver1) if _[0]!='_'])
    set_of_firefox_api = set([_ for _ in dir(driver2) if _[0]!='_'])
    print('firefox特有的:',(set_of_chrome_api|set_of_firefox_api)-set_of_chrome_api)
    print('-------------')
    print('chrome特有的:',(set_of_chrome_api|set_of_firefox_api)-set_of_firefox_api)
    

讓chrome也有日誌

  • 首先來看下Chrome這個類的初始化引數都有哪些

    # selenium\webdriver\chrome\webdriver.py
    class WebDriver(ChromiumDriver):
        def __init__(self, executable_path=DEFAULT_EXECUTABLE_PATH, port=DEFAULT_PORT,
                     options: Options = None, service_args=None,
                     desired_capabilities=None, service_log_path=DEFAULT_SERVICE_LOG_PATH,
                     chrome_options=None, service: Service = None, keep_alive=DEFAULT_KEEP_ALIVE):
    
  • 你應該一眼就看到有日誌相關的引數了service_log_path

  • 有個預設值DEFAULT_SERVICE_LOG_PATH

  • 往上能看到定義:DEFAULT_SERVICE_LOG_PATH = None

  • 所以chrome就沒有日誌了

  • 要有就簡單了,給一個值就行了,這樣

    from selenium import webdriver
    driver = webdriver.Chrome(service_log_path='chrome.log')
    
  • 妥妥的在當前目錄下生成了一個chrome.log檔案裡面也記錄著本次操作的日誌

  • 多說幾句,預設的日誌就記錄到INFO/WARN這樣的級別

  • 如果要加DEBUG的資訊,可以這樣

    from selenium import webdriver
    driver = webdriver.Chrome(service_args=['--verbose'],
                              service_log_path='chrome.log')
    
    

讓firefox沒有日誌,沒那麼簡單

  • 循著剛才的思路,讓firefox沒有日誌似乎就很簡單了

  • 依葫蘆畫瓢,找到Firefox的定義

    # selenium\webdriver\firefox\webdriver.py
    # 注意,此處的路徑跟上面的chrome的並不一樣
    class WebDriver(RemoteWebDriver):
        def __init__(self, firefox_profile=None, firefox_binary=None,
                     capabilities=None, proxy=None,
                     executable_path=DEFAULT_EXECUTABLE_PATH, options=None,
                     service_log_path=DEFAULT_SERVICE_LOG_PATH,
                     service_args=None, service=None, desired_capabilities=None,
                     log_path=DEFAULT_LOG_PATH, keep_alive=True):
    
  • 看到了引數service_log_path,一樣也有預設值DEFAULT_SERVICE_LOG_PATH

  • 找到定義處,DEFAULT_SERVICE_LOG_PATH = "geckodriver.log"

  • 改為None試試

    from selenium import webdriver
    driver = webdriver.Firefox(service_log_path=None)
    
  • 效果有,但又有點不對

  • 控制檯冒出了很多資訊

    demo_log.py:2: DeprecationWarning: service_log_path has been deprecated, please pass in a Service object
      driver = webdriver.Firefox(service_log_path=None)
    1678944678241	geckodriver	INFO	Listening on 127.0.0.1:10729
    1678944681310	mozrunner::runner	INFO	Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "--marionette" "--remote-debugging-port" "10730" "-no-remote" "-profile" "C:\\Users\\SONGQI~1\\AppData\\Local\\Temp\\rust_mozprofileeEN3y9"
    Dynamically enable window occlusion 0
    1678944681583	Marionette	INFO	Marionette enabled
    1678944681587	Marionette	INFO	Listening on port 10743
    WebDriver BiDi listening on ws://127.0.0.1:10730
    1678944681883	RemoteAgent	WARN	TLS certificate errors will be ignored for this session
    console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at C:\\Users\\SONGQI~1\\AppData\\Local\\Temp\\rust_mozprofileeEN3y9\\search.json.mozlz4", (void 0)))
    DevTools listening on ws://127.0.0.1:10730/devtools/browser/a4f3a501-e642-4540-8998-ae1ea0b3abc5
    
  • 仔細一看,跟之前在geckodriver.log中列印的類似

  • 還多了一句

    DeprecationWarning: service_log_path has been deprecated, please pass in a Service object
    
  • 原來service_log_path被棄用了,需要傳遞一個Service物件

  • 怎麼傳遞Service物件呢?找到其定義,注意路徑

  • 有多個Service在selenium這個庫中,你要的是firefox下的

    #  selenium\webdriver\firefox\service.py
    class Service(service.Service):
        """Object that manages the starting and stopping of the
        GeckoDriver."""
    
        def __init__(self, executable_path: str = DEFAULT_EXECUTABLE_PATH,
                     port: int = 0, service_args: List[str] = None,
                     log_path: str = "geckodriver.log", env: dict = None):
    
  • 可以看到,這裡有個引數log_path,其預設值是"geckodriver.log"

  • 那我們就可以這樣修改了

    from selenium import webdriver
    from selenium.webdriver.firefox.service import Service
    # 聽你的,傳遞一個Service物件
    # Service(log_path='') 就是一個
    driver = webdriver.Firefox(service=Service(log_path=''))
    
  • 至此DeprecationWarning: service_log_path has been deprecated, please pass in a Service object的這段沒了

  • 不過下面的1678945260755 geckodriver INFO Listening on 127.0.0.1:11634,這樣的仍然存在的

  • 而這部分實際是geckodriver這個驅動的列印資訊

    C:\Users\xxx>geckodriver
    1678945567307   geckodriver     INFO    Listening on 127.0.0.1:4444
    
  • 如果要去掉,就是讓geckodriver這個程式靜默

  • 沒有找到太好的辦法,geckodriver的幫助如下

    C:\Users\xxx>geckodriver --help
    geckodriver 0.30.0 (d372710b98a6 2021-09-16 10:29 +0300)
    WebDriver implementation for Firefox
    
    USAGE:
        geckodriver [FLAGS] [OPTIONS]
    
    FLAGS:
            --connect-existing    Connect to an existing Firefox instance
        -h, --help                Prints this message
            --jsdebugger          Attach browser toolbox debugger for Firefox
        -v                        Log level verbosity (-v for debug and -vv for trace level)
        -V, --version             Prints version and copying information
    
    OPTIONS:
            --android-storage <ANDROID_STORAGE>    Selects storage location to be used for test data (deprecated). [possible
                                                   values: auto, app, internal, sdcard]
        -b, --binary <BINARY>                      Path to the Firefox binary
            --log <LEVEL>                          Set Gecko log level [possible values: fatal, error, warn, info, config,
                                                   debug, trace]
            --marionette-host <HOST>               Host to use to connect to Gecko [default: 127.0.0.1]
            --marionette-port <PORT>               Port to use to connect to Gecko [default: system-allocated port]
            --host <HOST>                          Host IP to use for WebDriver server [default: 127.0.0.1]
        -p, --port <PORT>                          Port to use for WebDriver server [default: 4444]
            --websocket-port <PORT>                Port to use to connect to WebDriver BiDi [default: 9222]
    
  • --log 這個引數可以讓它控制輸出級別

  • 最終我們可以這樣寫

    from selenium import webdriver
    from selenium.webdriver.firefox.service import Service
    
    driver = webdriver.Firefox(service=Service(log_path='',
                        service_args=['--log','fatal']))  # 你不能 ['--log fatal'] 會報錯
    
    
  • 然,即便如此,控制檯一樣有列印

    Dynamically enable window occlusion 0
    WebDriver BiDi listening on ws://127.0.0.1:12166
    console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at C:\\Users\\SONGQI~1\\AppData\\Local\\Temp\\rust_mozprofiledrxhm5\\search.json.mozlz4", (void 0)))
    DevTools listening on ws://127.0.0.1:12166/devtools/browser/22a37523-84bc-4bd6-a5e9-79c30825d1e8
    
  • 啊~~~~~~~~~無語了,不弄了,放棄了,乾點有意義的事情吧,有點無趣

相關文章