【问题标题】:How to save and load cookies using Python + Selenium WebDriver如何使用 Python + Selenium WebDriver 保存和加载 cookie
【发布时间】:2013-02-10 02:16:04
【问题描述】:

如何将 Python 的 Selenium WebDriver 中的所有 cookie 保存到 .txt 文件中,然后再加载它们?

文档并没有对 getCookies 函数进行太多说明。

【问题讨论】:

    标签: python python-2.7 selenium webdriver


    【解决方案1】:

    您可以使用 pickle 将当前 cookie 保存为 Python 对象。例如:

    import pickle
    import selenium.webdriver
    
    driver = selenium.webdriver.Firefox()
    driver.get("http://www.google.com")
    pickle.dump( driver.get_cookies() , open("cookies.pkl","wb"))
    

    稍后再添加它们:

    import pickle
    import selenium.webdriver
    
    driver = selenium.webdriver.Firefox()
    driver.get("http://www.google.com")
    cookies = pickle.load(open("cookies.pkl", "rb"))
    for cookie in cookies:
        driver.add_cookie(cookie)
    

    【讨论】:

    • 我收到“pickle 协议必须是
    • 这会做同样的事情吗? cookieFile = open("cookies.pkl", "w") dump = pickle.dumps(driver.get_cookies()) cookieFile.write(dump)
    • 嗨 Aaron,我对示例进行了一些修改 - 基本上是添加到文件打开部分的 'b' 标志。你可以试试吗?
    • 同样的错误,我对泡菜不熟悉,所以我不确定它是什么。 "raise ValueError("pickle 协议必须是
    • 我对此有疑问。它工作正常,但是当我再次尝试drive.add_cookie t 时,我收到一条错误消息,提示“到期”密钥无效。我在 Mac OS 上使用 chromedriver
    【解决方案2】:

    当您需要从会话到会话的 cookie 时,还有另一种方法可以做到这一点。使用 Chrome 选项 user-data-dir 以将文件夹用作配置文件。我跑:

    # You need to: from selenium.webdriver.chrome.options import Options
    chrome_options = Options()
    chrome_options.add_argument("user-data-dir=selenium") 
    driver = webdriver.Chrome(chrome_options=chrome_options)
    driver.get("www.google.com")
    

    在这里,您可以进行检查人机交互的登录。我这样做,然后每次我用那个文件夹启动 Webdriver 时我现在需要的 cookie 都在那里。您还可以手动安装扩展并在每个会话中使用它们。

    我第二次运行,所有的cookies都在那里:

    # You need to: from selenium.webdriver.chrome.options import Options    
    chrome_options = Options()
    chrome_options.add_argument("user-data-dir=selenium") 
    driver = webdriver.Chrome(chrome_options=chrome_options)
    driver.get("www.google.com") # Now you can see the cookies, the settings, extensions, etc., and the logins done in the previous session are present here. 
    

    优点是你可以使用多个不同设置和cookies的文件夹,扩展程序无需加载、卸载cookies、安装和卸载扩展程序、更改设置、通过代码更改登录名,因此没有办法拥有逻辑程序中断等。

    此外,这比通过代码完成所有操作要快。

    【讨论】:

    • 这对我来说是处理 Google 登录时的最佳解决方案。在某些时候,我的开发使用被标记为可疑活动。
    • @p1g1n 在使用此解决方案之前或之后被标记
    • 抱歉,在使用解决方案之前已被标记。现在我保持登录状态,因此没有可疑活动。
    • chrome_options = Options() 给我name 'Options' is not defined ... ?
    • @Dan 你需要:from selenium.webdriver.chrome.options import Options
    【解决方案3】:

    请记住,您只能为当前域添加 cookie。

    如果您想为您的 Google 帐户添加 cookie,请执行此操作

    browser.get('http://google.com')
    for cookie in cookies:
        browser.add_cookie(cookie)
    

    【讨论】:

    • 这应该在他们的文档中:(
    • @MauricioCortazar 它没有说明我所指的域要求
    • @Tjorriemorrie 那是基本的人,cookie 只存储在域中,甚至不允许子域
    • 此评论似乎与使用来自根域的 cookie 的多个域相关。例如,google.com 可以是根域,而 Google 拥有的另一个域或子域可以使用相同的 cookie。由于这个(和其他原因),我更喜欢@Eduard Florinescu 的解决方案,因为它不需要在加载 cookie 之前使用 browser.get,它们已经从数据目录中。在加载 cookie 文件(根据此评论)之前,这里似乎需要额外的 browser.get,但没有对其进行测试。
    【解决方案4】:

    只需对代码written by Roel Van de Paar 稍作修改,所有功劳归于他。我在 Windows 中使用它,它在设置和添加 cookie 时运行良好:

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    chrome_options = Options()
    chrome_options.add_argument("--user-data-dir=chrome-data")
    driver = webdriver.Chrome('chromedriver.exe',options=chrome_options)
    driver.get('https://web.whatsapp.com')  # Already authenticated
    time.sleep(30)
    

    【讨论】:

    • 为我工作,虽然我必须在user-data-dir 上设置特定路径(我使用os.getcwd())。
    【解决方案5】:

    基于the answer by Eduard Florinescu,但添加了更新的代码和缺少的导入:

    $ cat work-auth.py
    #!/usr/bin/python3
    
    # Setup:
    # sudo apt-get install chromium-chromedriver
    # sudo -H python3 -m pip install selenium
    
    import time
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    chrome_options = Options()
    chrome_options.add_argument("--user-data-dir=chrome-data")
    driver = webdriver.Chrome('/usr/bin/chromedriver',options=chrome_options)
    chrome_options.add_argument("user-data-dir=chrome-data")
    driver.get('https://www.somedomainthatrequireslogin.com')
    time.sleep(30)  # Time to enter credentials
    driver.quit()
    
    $ cat work.py
    #!/usr/bin/python3
    
    import time
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    chrome_options = Options()
    chrome_options.add_argument("--user-data-dir=chrome-data")
    driver = webdriver.Chrome('/usr/bin/chromedriver',options=chrome_options)
    driver.get('https://www.somedomainthatrequireslogin.com')  # Already authenticated
    time.sleep(10)
    driver.quit()
    

    【讨论】:

    • 泡菜的东西对我不起作用。 (这是我第二次尝试使用它。)所以我使用了你的方法,起初对我也不起作用。我必须进行的更改:由于github.com/theintern/intern/issues/878 中记录的问题,我必须输入 chrome_options.add_argument('no-sandbox') 并且我必须在我的 Windows 10 环境中使 user-data-dir 成为完整路径。跨度>
    • 不适用于在 cookie 中存储身份验证数据的网站
    • 你本可以改进他们的答案,它基本上工作正常
    【解决方案6】:

    这是我在 Windows 中使用的代码。它有效。

    for item in COOKIES.split(';'):
        name,value = item.split('=', 1)
        name=name.replace(' ', '').replace('\r', '').replace('\n', '')
        value = value.replace(' ', '').replace('\r', '').replace('\n', '')
        cookie_dict={
                'name':name,
                'value':value,
                "domain": "",  # Google Chrome
                "expires": "",
                'path': '/',
                'httpOnly': False,
                'HostOnly': False,
                'Secure': False
            }
        self.driver_.add_cookie(cookie_dict)
    

    【讨论】:

      【解决方案7】:

      试试这个方法:

      import pickle
      from selenium import webdriver
      driver = webdriver.Chrome(executable_path="chromedriver.exe")
      URL = "SITE URL"
      driver.get(URL)
      sleep(10)
      if os.path.exists('cookies.pkl'):
          cookies = pickle.load(open("cookies.pkl", "rb"))
          for cookie in cookies:
              driver.add_cookie(cookie)
          driver.refresh()
          sleep(5)
      # check if still need login
      # if yes:
      # write login code
      # when login success save cookies using
      pickle.dump(driver.get_cookies(), open("cookies.pkl", "wb"))
      

      【讨论】:

        【解决方案8】:

        理想情况下,最好不要一开始就复制目录,但这非常困难,请参阅

        还有


        这是为 Firefox 保存配置文件目录的解决方案(类似于 Chrome 中的user-data-dir(用户数据目录))(它涉及手动复制目录。我一直无法找到其他方法):

        已在 Linux 上测试。


        短版:

        • 保存配置文件
        driver.execute_script("window.close()")
        time.sleep(0.5)
        currentProfilePath = driver.capabilities["moz:profile"]
        profileStoragePath = "/tmp/abc"
        shutil.copytree(currentProfilePath, profileStoragePath,
                        ignore_dangling_symlinks=True
                        )
        
        • 加载配置文件
        driver = Firefox(executable_path="geckodriver-v0.28.0-linux64",
                         firefox_profile=FirefoxProfile(profileStoragePath)
                        )
        

        长版(通过演示和大量解释——见代码中的 cmets)

        代码使用localStorage 进行演示,但它也适用于cookie。

        #initial imports
        
        from selenium.webdriver import Firefox, FirefoxProfile
        
        import shutil
        import os.path
        import time
        
        # Create a new profile
        
        driver = Firefox(executable_path="geckodriver-v0.28.0-linux64",
                          # * I'm using this particular version. If yours is
                          # named "geckodriver" and placed in system PATH
                          # then this is not necessary
                        )
        
        # Navigate to an arbitrary page and set some local storage
        driver.get("https://DuckDuckGo.com")
        assert driver.execute_script(r"""{
                const tmp = localStorage.a; localStorage.a="1";
                return [tmp, localStorage.a]
            }""") == [None, "1"]
        
        # Make sure that the browser writes the data to profile directory.
        # Choose one of the below methods
        if 0:
            # Wait for some time for Firefox to flush the local storage to disk.
            # It's a long time. I tried 3 seconds and it doesn't work.
            time.sleep(10)
        
        elif 1:
            # Alternatively:
            driver.execute_script("window.close()")
            # NOTE: It might not work if there are multiple windows!
        
            # Wait for a bit for the browser to clean up
            # (shutil.copytree might throw some weird error if the source directory changes while copying)
            time.sleep(0.5)
        
        else:
            pass
            # I haven't been able to find any other, more elegant way.
            #`close()` and `quit()` both delete the profile directory
        
        
        # Copy the profile directory (must be done BEFORE driver.quit()!)
        currentProfilePath = driver.capabilities["moz:profile"]
        assert os.path.isdir(currentProfilePath)
        profileStoragePath = "/tmp/abc"
        try:
            shutil.rmtree(profileStoragePath)
        except FileNotFoundError:
            pass
        
        shutil.copytree(currentProfilePath, profileStoragePath,
                        ignore_dangling_symlinks=True # There's a lock file in the
                                                      # profile directory that symlinks
                                                      # to some IP address + port
                       )
        
        driver.quit()
        assert not os.path.isdir(currentProfilePath)
        # Selenium cleans up properly if driver.quit() is called,
        # but not necessarily if the object is destructed
        
        
        # Now reopen it with the old profile
        
        driver=Firefox(executable_path="geckodriver-v0.28.0-linux64",
                       firefox_profile=FirefoxProfile(profileStoragePath)
                      )
        
        # Note that the profile directory is **copied** -- see FirefoxProfile documentation
        assert driver.profile.path!=profileStoragePath
        assert driver.capabilities["moz:profile"]!=profileStoragePath
        
        # Confusingly...
        assert driver.profile.path!=driver.capabilities["moz:profile"]
        # And only the latter is updated.
        # To save it again, use the same method as previously mentioned
        
        # Check the data is still there
        
        driver.get("https://DuckDuckGo.com")
        
        data = driver.execute_script(r"""return localStorage.a""")
        assert data=="1", data
        
        driver.quit()
        
        assert not os.path.isdir(driver.capabilities["moz:profile"])
        assert not os.path.isdir(driver.profile.path)
        

        什么不起作用:

        • 初始化Firefox(capabilities={"moz:profile": "/path/to/directory"}) -- 驱动程序将无法连接。
        • options=Options(); options.add_argument("profile"); options.add_argument("/path/to/directory"); Firefox(options=options) -- 同上。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多