【问题标题】:Unable to Save and Re-load Gmail Cookies with Selenium/Splinter无法使用 Selenium/Splinter 保存和重新加载 Gmail Cookie
【发布时间】:2018-05-10 07:30:40
【问题描述】:

我的目标是登录 Gmail,序列化 cookie,退出浏览器,然后打开一个新的浏览器,加载保存的 cookie,并检查我的电子邮件,而无需输入我的登录详细信息。非常简单,我几乎可以在我尝试过的每个网站上做到这一点。但是,Gmail 每次都会强制我重新登录。

这是我的代码:

from splinter import Browser
import selenium
import pickle

def export_cookies(browser, the_name):
    yummy = browser.cookies.all(verbose=True)
    location = 'cookies/' + the_name
    pickle_save(yummy, location)
    print(the_name, "saved", len(yummy))


def pickle_save(obj, location):
    file_name = location
    file_object = open(file_name, 'wb')
    pickle.dump(obj, file_object)
    file_object.close()


def pickle_load_account(cookie_file_name):
    try:
        return pickle.load(open(cookie_file_name, "rb"))
    except FileNotFoundError:
        return 0


def browser_add_cookies(browser, cookies):
    if len(cookies) > 0:
        for cookie in cookies:
            browser.cookies.add({cookie['name']: cookie['value']})
        print("-----", len(cookies), " cookies added, reloading")
        browser.visit('https://mail.google.com/mail/u/0/#inbox')
    else:
        print("No cookies to load. Error.")


browser = Browser('firefox')
browser.visit('https://mail.google.com/mail/u/0/#inbox')
cookie_file = "cookies/name"
load_cookies = pickle_load_account(cookie_file)
browser_add_cookies(browser, load_cookies)
browser.visit('https://mail.google.com/mail/u/0/#inbox')
input("Save cookies?")
export_cookies(browser, "name")

此代码假定 cookie 已保存,但最后会重新保存它们,因此第二次运行(如果您第一次手动登录)。

我的猜测是 Gmail 不知何故使用了更高级的 cookie 识别方法?

【问题讨论】:

  • 对我发布的答案有任何反馈吗?

标签: python-3.x selenium gmail splinter


【解决方案1】:

您正在为一个域复制 cookie。您还需要为以下域复制

accounts.google.com
mail.google.com

可能还有更多,请参阅下面的新登录屏幕截图

【讨论】:

  • 这不提供解决方案,因为您将获得selenium.common.exceptions.InvalidCookieDomainException: Message: Cookies may only be set for the current domain (accounts.google.com),因为导航到mail.google.com 将强制重定向到accounts.google.com
【解决方案2】:

让设置 cookie 更容易的浏览器包装示例代码:

class SplinterBrowserWrapper:
    def __init__(self, splinter_browser):
        b = self.browser = splinter_browser
        b.visit('https://' + ROOT_DOMAIN)

    def add_cookies(self, cookies: dict):
        self.browser.cookies.add(cookies)
        for cookie in self.list_cookies():
            cookie['domain'] = ROOT_DOMAIN
            self.add_single_cookie_dict(cookie)
        self.browser.reload()

    def add_single_cookie_dict(self, single_cookie_dict):
        self.browser.driver.add_cookie(single_cookie_dict)

    def get_cookies(self):
        return self.browser.cookies.all()

    def list_cookies(self):
        return self.browser.driver.get_cookies()

常规:

  1. 访问mail.google.com
  2. mail.google.com问accounts.google.com:这家伙登录不登录?
  3. accounts 回答:没有!
  4. mail:好吧,又是一个流浪的客人……

客人不满意,尝试通过 splinter 设置 cookie:

  1. 访问mail.google.com并设置cookies
  2. cookies 已设置,但与子域mail.google.com 绑定(运行browser.driver.get_cookies() 并检查返回的列表)
  3. 子域accounts.google.com 仍然没有cookies
  4. mail问accounts同样的问题,得到同样的否定答案
  5. emmm...

客人现在知道诀窍了,客人再试一次:

  1. 访问accounts.google.com并设置cookies
  2. 访问mail.google.com
  3. mail问accounts,得到答案是的
  4. mail登录
  5. N~I~C~E~

另一个套路,另一个叫bilibili的网站:

  • 访问www.bilibili.com
  • www问account.bilibili.com
  • account 没有登录 cookie,account 将浏览器重定向到 passport.bilibili.com
  • passport 向用户询问用户名和密码
  • passport 获取正确的身份验证,设置cookie,并以登录名重定向回主页

分裂挑战 bilibili,第一轮:

  • 访问www.bilibili.com,设置cookies,重新加载页面,不要登录
  • 访问account.bilibili.com,被重定向到passport.bilibili.com
  • 在passport上设置cookies
  • 但 passport 不想要 cookie,passport 需要用户名和密码
  • passport 留在原地,拒绝重定向到 account 或 www
  • account 仍然没有 cookie
  • 再次访问account,再次重定向到passport,死循环

分裂挑战第 2 轮:

  • 访问www.bilibili.com,设置cookies,cookies绑定www.bilibili.com
  • 深入底层的 selenium 驱动,用browser.driver.get_cookies() 列出所有cookie,这个列表中的每一个cookie 都是一个字典,键为name,value,path,domain,secure,@ 987654366@
  • 迭代此cookie列表,对于每个cookie dict,将domain的值更改为父域bilibili.com,没有子域
  • 通过browser.driver.add_cookie将这些被操纵的cookie一一设置回硒驱动器中
  • 现在account 看到这些cookie 绑定到其父域bilibili.com
  • account 很听话,account 接受这些 cookie,account 现在在有人询问用户是否登录时回答“是”
  • 重新加载页面和用户登录

【讨论】:

    猜你喜欢
    • 2018-05-03
    • 2021-07-13
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    相关资源
    最近更新 更多