【问题标题】:How to preload cookies before first request with Python3, Selenium Chrome WebDriver?如何在第一次使用 Python3、Selenium Chrome WebDriver 请求之前预加载 cookie?
【发布时间】:2020-08-03 03:33:19
【问题描述】:

是否可以使用 add_cookie() 为域添加 cookie,例如在 Selenium Chrome WebDriver 中的 stackoverflow.com,然后使用 get() 对域上的页面进行实际请求 stackoverflow .com ?

尝试时:

driver.webdriver.add_cookie({'name' : 'testcookie', 'value' : 'testvalue', 'domain' : 'stackoverflow.com'})
driver.webdriver.get('https://stackoverflow.com/')

我收到“您只能为当前域设置 cookie”。

我想说我看到并尝试了一些避免问题而不是解决问题的解决方案,例如事先访问域上的 404 页面以在 Selenium 中创建“域插槽”,然后再向其中添加 cookie,但是虽然这些解决方案允许添加他们仍然需要发出一个额外请求并在没有设置任何 cookie 的情况下与站点联系的 cookie。

这是在处理 CAPTCHA 系统和一些非常具体的 WAF 时出现的问题,这些 WAF 在看到一个没有 cookie 的请求,然后是另一个只有在完成登录过程后才应该说的 cookie 请求时,会皱起眉头。

【问题讨论】:

    标签: python-3.x selenium google-chrome cookies webdriver


    【解决方案1】:

    从 Chrome 64 开始,我们现在可以访问 Chrome DevTools 协议 v1.3,它允许通过方法 Network.setCookie 将 cookie 设置到任何域,从而无需额外的 get 调用来预先设置域。

    例如Python3

    import os.path
    import pickle
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    def save_cookies():
        print("Saving cookies in " + selenium_cookie_file)
        pickle.dump(driver.get_cookies() , open(selenium_cookie_file,"wb"))
    
    def load_cookies():
        if os.path.exists(selenium_cookie_file) and os.path.isfile(selenium_cookie_file):
            print("Loading cookies from " + selenium_cookie_file)
            cookies = pickle.load(open(selenium_cookie_file, "rb"))
    
            # Enables network tracking so we may use Network.setCookie method
            driver.execute_cdp_cmd('Network.enable', {})
    
            # Iterate through pickle dict and add all the cookies
            for cookie in cookies:
                # Fix issue Chrome exports 'expiry' key but expects 'expire' on import
                if 'expiry' in cookie:
                    cookie['expires'] = cookie['expiry']
                    del cookie['expiry']
    
                # Replace domain 'apple.com' with 'microsoft.com' cookies
                cookie['domain'] = cookie['domain'].replace('apple.com', 'microsoft.com')
    
                # Set the actual cookie
                driver.execute_cdp_cmd('Network.setCookie', cookie)
    
            # Disable network tracking
            driver.execute_cdp_cmd('Network.disable', {})
            return 1
    
        print("Cookie file " + selenium_cookie_file + " does not exist.")
        return 0
    
    def pretty_print(pdict):
        for p in pdict:
            print(str(p))
        print('',end = "\n\n")
    
    
    # Minimal settings
    selenium_cookie_file = '/home/selenium/test.txt'
    
    browser_options = Options()
    browser_options.add_argument("--headless")
    
    # Open a driver, get a page, save cookies
    driver = webdriver.Chrome(chrome_options=browser_options)
    driver.get('https://apple.com/')
    save_cookies()
    pretty_print(driver.get_cookies())
    
    
    # Rewrite driver with a new one, load and set cookies before any requests
    driver = webdriver.Chrome(chrome_options=browser_options)
    load_cookies()
    driver.get('https://microsoft.com')
    pretty_print(driver.get_cookies())
    

    您将在上面看到,我们通过一个请求从域“apple.com”获取 cookie,并在实际向“microsoft.com”发出请求之前将它们加载并设置为对域“microsoft.com”的第二个请求。

    只要您将变量 selenium_cookie_file 设置为有效的可写文件路径,代码就已经过测试并且可以正常工作。

    【讨论】:

    • 只是想说声谢谢!我一直在寻找如何在驱动程序调用之前预加载我的 cookie 的方法,这个解决方案已经奏效了!不幸的是,其他建议(例如导航到 404 或图像)对我不起作用,因为整个站点都受 MFA 保护,并且一旦站点加载就会触发 cookie,而我现在通过此解决方案设法实现了这一点。 PS:除了 selenium_cookie_file 变量必须是有效路径之外,替换域部分也必须根据每个人自己的需要进行编辑:-)
    • 不错的答案!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多