将 cookie 加载到 Python 请求会话时出错

问题描述 投票:0回答:7

我正在尝试从 selenium 导出的 cookie 将 cookie 加载到 Python 中的请求会话中,但是当我这样做时,它会返回以下错误: “‘list’对象没有属性‘extract_cookies’”

def load_cookies(filename):
    with open(filename, 'rb') as f:
        return pickle.load(f)

initial_state= requests.Session()
initial_state.cookies=load_cookies(time_cookie_file)
search_requests = initial_state.get(search_url)

我在任何地方看到这都应该有效,但是我的 cookie 是一个字典列表,这就是我所理解的所有 cookie 的含义,也是为什么我认为这适用于 Selenium。然而,由于某种原因,它不适用于请求,这方面的任何和所有帮助都非常好,感觉就像我错过了一些明显的东西!

Cookie 已从 Selenium 中转储,使用:

with open("Filepath.pkl", 'wb') as f:
    pickle.dump(driver.get_cookies(), f)

cookie 的一个例子是(稍微混淆了):

[{'domain': '.website.com',
  'expiry': 1640787949,
  'httpOnly': False,
  'name': '_ga',
  'path': '/',
  'secure': False,
  'value': 'GA1.2.1111111111.1111111111'},
 {'domain': 'website.com',
  'expiry': 1585488346,
  'httpOnly': False,
  'name': '__pnahc',
  'path': '/',
  'secure': False,
  'value': '0'}]

我现在已经设法按照下面的答案加载cookie,但是cookie似乎没有正确加载,因为它们不记得任何东西,但是如果我在浏览Selenium时加载cookie,它们就可以正常工作。

python selenium cookies python-requests
7个回答
6
投票

饼干

Cookie
HTTP 请求标头包含服务器之前使用
HTTP cookie
标头发送的存储的
Set-Cookie
HTTP cookie 是服务器发送到用户 Web 浏览器的一小段数据。浏览器可以存储 cookies 并将其与下一个请求一起发送回同一服务器。通常, 可以判断两个请求是否来自同一浏览器,从而保持用户登录状态。


使用 Selenium 的演示

为了演示如何使用 Selenium 使用 cookie,我们在用户登录网站 后使用 pickle 存储 cookie。在下一步中,我们打开同一个网站,添加 cookie,并能够以登录用户身份登陆。

  • 存储cookie的代码块:

    from selenium import webdriver
    import pickle
    
    options = webdriver.ChromeOptions() 
    options.add_argument("start-maximized")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    driver = webdriver.Chrome(options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
    driver.find_element_by_name("username").send_keys("abc123")
    driver.find_element_by_name("password").send_keys("123xyz")
    driver.find_element_by_name("submit").click()
    pickle.dump( driver.get_cookies() , open("cookies.pkl","wb"))
    
  • 使用存储的 cookie 进行自动身份验证的代码块:

    from selenium import webdriver
    import pickle
    
    options = webdriver.ChromeOptions() 
    options.add_argument("start-maximized")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    driver = webdriver.Chrome(options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
    cookies = pickle.load(open("cookies.pkl", "rb"))
    for cookie in cookies:
        driver.add_cookie(cookie)
    driver.get('http://demo.guru99.com/test/cookie/selenium_cookie.php')
    

使用请求演示

为了演示使用 的 cookie 用法,我们访问了该网站 https://www.google.com,添加了新的 cookie 字典:

{'name':'my_own_cookie','value': 'debanjan' ,'domain':'.stackoverflow.com'}

接下来,我们使用相同的 requests 会话发送另一个成功的请求,如下所示:

  • 代码块:

    import requests
    
    s1 = requests.session()
    s1.get('https://www.google.com')
    print("Original Cookies")
    print(s1.cookies)
    print("==========")
    cookie = {'name':'my_own_cookie','value': 'debanjan' ,'domain':'.stackoverflow.com'}
    s1.cookies.update(cookie)
    print("After new Cookie added")
    print(s1.cookies)
    
  • 控制台输出:

    Original Cookies
    <RequestsCookieJar[<Cookie 1P_JAR=2020-01-21-14 for .google.com/>, <Cookie NID=196=NvZMMRzKeV6VI1xEqjgbzJ4r_3WCeWWjitKhllxwXUwQcXZHIMRNz_BPo6ujQduYCJMOJgChTQmXSs6yKX7lxcfusbrBMVBN_qLxLIEah5iSBlkdBxotbwfaFHMd-z5E540x02-YZtCm-rAIx-MRCJeFGK2E_EKdZaxTw-StRYg for .google.com/>]>
    ==========
    After new Cookie added
    <RequestsCookieJar[<Cookie domain=.stackoverflow.com for />, <Cookie name=my_own_cookie for />, <Cookie value=debanjan for />, <Cookie 1P_JAR=2020-01-21-14 for .google.com/>, <Cookie NID=196=NvZMMRzKeV6VI1xEqjgbzJ4r_3WCeWWjitKhllxwXUwQcXZHIMRNz_BPo6ujQduYCJMOJgChTQmXSs6yKX7lxcfusbrBMVBN_qLxLIEah5iSBlkdBxotbwfaFHMd-z5E540x02-YZtCm-rAIx-MRCJeFGK2E_EKdZaxTw-StRYg for .google.com/>]>
    

结论

显然,新添加的 cookie 字典

{'name':'my_own_cookie','value': 'debanjan' ,'domain':'.stackoverflow.com'}
在第二个请求中几乎得到了使用。


将 Selenium Cookie 传递给 Python 请求

现在,如果您的用例是将 Selenium Cookie 传递给 Python 请求,您可以使用以下解决方案:

from selenium import webdriver
import pickle
import requests

options = webdriver.ChromeOptions() 
options.add_argument("start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
driver.find_element_by_name("username").send_keys("abc123")
driver.find_element_by_name("password").send_keys("123xyz")
driver.find_element_by_name("submit").click()

# Storing cookies through Selenium
pickle.dump( driver.get_cookies() , open("cookies.pkl","wb"))
driver.quit()

# Passing cookies to Session
session = requests.session()  # or an existing session
with open('cookies.pkl', 'rb') as f:
    session.cookies.update(pickle.load(f))
search_requests = session.get('https://www.google.com/')
print(session.cookies)

3
投票

由于您要将 session.cookies (

RequestsCookieJar
) 替换为不具有这些属性的
list
,因此它将不起作用。

您可以使用以下方法逐一导入这些 cookie:

for c in your_cookies_list:
   initial_state.cookies.set(name=c['name'], value=c['value'])

我尝试加载整个 cookie,但请求似乎无法识别这些 cookie 并返回:

TypeError: create_cookie() got unexpected keyword arguments: ['expiry', 'httpOnly']

请求接受

expires
,并且
HttpOnly
嵌套在
rest

更新:

我们还可以更改

expiry
httpOnly
的字典键,以便请求正确加载它们而不是抛出异常,方法是使用
dict.pop()
,通过
key
从字典中删除项目并返回
value
已删除的
key
因此,在我们添加一个新的
key
和已删除的项目
value
后,然后解压并将它们作为
kwargs
传递:

for c in your_cookies_list:
    c['expires'] = c.pop('expiry')
    c['rest'] = {'HttpOnly': c.pop('httpOnly')}
    initial_state.cookies.set(**c)

0
投票

您可以获取 cookie 并仅使用名称/值。您还需要标题。您可以从开发工具或使用代理获取它们。

基本示例:

driver.get('https://website.com/')

# ... login or do anything

cookies = {}
for cookie in driver.get_cookies():
    cookies[cookie['name']] = cookie['value']
# Write to a file if need or do something
# import json
# with open("cookies.txt", 'w') as f:
#    f.write(json.dumps(cookies))

及用法:

# Read cookies from file as Dict
# with open('cookies.txt') as reader:
#     cookies = json.loads(reader.read())

# use cookies
response = requests.get('https://website.com/', headers=headers, cookies=cookies)

Stackoverflow headers 示例,有些 headers 可能是必需的,有些则不需要。您可以在此处此处找到信息。您可以使用开发工具“网络”选项卡获取请求标头:

headers = {
    'authority': 'stackoverflow.com',
    'pragma': 'no-cache',
    'cache-control': 'no-cache',
    'dnt': '1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36',
    'sec-fetch-user': '?1',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'navigate',
    'referer': 'https://stackoverflow.com/questions/tagged?sort=Newest&tagMode=Watched&uqlId=8338',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'ru,en-US;q=0.9,en;q=0.8,tr;q=0.7',
}

0
投票

您可以创建一个会话。会话类处理请求之间的 cookie。

s = requests.Session()


login_resp = s.post('https://example.com/login', login_data)
self.cookies = self.login_resp.cookies



cookiedictreceived = {}
cookiedictreceived=requests.utils.dict_from_cookiejar(self.login_resp.cookies)

0
投票

因此 requests 希望 cookie 中的所有“值”都是字符串。可能与“钥匙”相同。当您的函数

load_cookies
返回时,Cookie 也不需要列表。可以使用
cookies = requests.utils.cookiejar_from_dict(...
为 request.utils 创建 Cookie。

假设我使用 selenium 访问“https://stackoverflow.com/”并像您所做的那样保存 cookie。

from selenium import webdriver
import pickle
import requests

#Go to the website
driver = webdriver.Chrome(executable_path=r'C:\Path\\To\\Your\\chromedriver.exe')
driver.get('https://stackoverflow.com/')

#Save the cookies in a file
with open("C:\Path\To\Your\Filepath.pkl", 'wb') as f:
    pickle.dump(driver.get_cookies(), f)

driver.quit()
#you function to get the cookies from the file.
def load_cookies(filename):
  with open(filename, 'rb') as f:
    return pickle.load(f)

saved_cookies_list = load_cookies("C:\Path\To\Your\Filepath.pkl")

#Set request session
initial_state = requests.Session()
#Function to fix cookie values and add cookies to request_session
def fix_cookies_and_load_to_requests(cookie_list, request_session):
    for index in range(len(cookie_list)):
        for item in cookie_list[index]:
            if type(cookie_list[index][item]) != str:
                print("Fix cookie value: ", cookie_list[index][item])
                cookie_list[index][item] = str(cookie_list[index][item])
        cookies = requests.utils.cookiejar_from_dict(cookie_list[index])
        request_session.cookies.update(cookies)
    return request_session

initial_state_with_cookies = fix_cookies_and_load_to_requests(cookie_list=saved_cookies_list, request_session=initial_state)

search_requests = initial_state_with_cookies.get("https://stackoverflow.com/")
print("search_requests:", search_requests)

0
投票

-4
投票

因此 requests 希望 cookie 中的所有“值”都是字符串。可能与“钥匙”相同。当您的函数 load_cookies 返回时,Cookie 也不需要列表。可以使用 cookies = requests.utils.cookiejar_from_dict(...

为 request.utils 创建 Cookie

https://pinibuy.com/

© www.soinside.com 2019 - 2024. All rights reserved.