johnnyb 发表于 2020-7-29 20:52:44

求助cookies操作

本帖最后由 johnnyb 于 2020-7-29 20:57 编辑

问题描述:
我用selenium模拟登陆douban.登陆成功. 用webdriver.get_cookies()方法 取得登陆成功的cookies为
[{'domain': 'accounts.douban.com', 'httpOnly': False, 'name': 'login_start_time', 'path': '/', 'secure': False, 'value': '1596025621029'}, {'domain': 'accounts.douban.com', 'httpOnly': False, 'name': 'apiKey', 'path': '/', 'secure': False, 'value': ''}, {'domain': '.douban.com', 'expiry': 1627561620, 'httpOnly': False, 'name': 'bid', 'path': '/', 'secure': False, 'value': '-dDW2CjywbM'}]
我把他直接放到headers中. requests.get(url) 可以取得登陆成功页面. 但是我的目标是把这个cookies传递给requests.Session对象s用.让它一直维持登陆状态. 获取需要登陆才能取到的个人主页.
当我用.
for cookie in cookies:
    s.cookies.set(cookie['name'], cookie['value'])
发现. selenium的get_cookies()方法. 传回来的是一个列表. 列表中有3个字典.这样for他就循环3次. 就完事了. 所以就过去3个值
('apiKey', '')
('bid', '-dDW2CjywbM')
('login_start_time', '1596025621029')
我如何能让所有的 name,value 全部过去呢?
尝试了把3个字典合成1个.. 但是里面存在多个重复name会被顶替成最后一个. 很无解..
或者有没有更好的转换方案? 或者模块?

suchocolate 发表于 2020-7-29 22:45:16

本帖最后由 suchocolate 于 2020-7-30 09:51 编辑

你的代码key是'name'和'value'的已经正确添加在cookie里了,是没问题的。
selenium的cookie和urllib的不同,它的cookie由多个key相同的字典组成。 # 说法有误请忽略
每个字典的key不仅仅有name和value,还有有expire和domain等等。
存储建议使用pickle:
driver.get(url)
time.sleep(10)
pickle.dump(driver.get_cookies(), open("cookies.pkl", "wb"))
读取时时遍历列表即可:
cookies = pickle.load(open("cookies.pkl", "rb"))
for cookie in cookies:
    driver.add_cookie(cookie)
driver.get(url)

johnnyb 发表于 2020-7-30 08:07:46

suchocolate 发表于 2020-7-29 22:45
你的代码key是'name'和'value'的已经正确添加在cookie里了,是没问题的。
selenium的cookie和urllib的不同 ...

意思明白了. 但是我的核心是. 取到的cookies传递给 Session对象用.. 比如s.cookie.set()   我要怎么保证传进去是可用呢?2天了. 还在研究这个问题

suchocolate 发表于 2020-7-30 09:08:58

johnnyb 发表于 2020-7-30 08:07
意思明白了. 但是我的核心是. 取到的cookies传递给 Session对象用.. 比如s.cookie.set()   我要怎么保证 ...

cookie能不能用这个不敢保证,但你的cookie代码是没问题的。
一次请求,header的字段有很多,cookie是其中之一,有时cookie正确,其他字段没设对也可请求不成功。
另外自己构建cookie,尽量以【浏览器f12】-【网络】中实际的cookie为模板,即使是用selenium获取的,也print的参考一下模板。这样headers正确的情况下测试才比较稳妥。

suchocolate 发表于 2020-7-30 10:01:49

纠正一下我在2楼的说法,我仔细看了一些requests的cookie,和selenium虽然对象类型不同,但是内容是差不多的。
>>> s = requests.session()
>>> s.cookies
<RequestsCookieJar[]>
>>> s.cookies.set('BID','123')
Cookie(version=0, name='BID', value='123', port=None, port_specified=False, domain='', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)
>>>
可以看出也有domain,path等参数,所以从selenium获得的cookie字典,需要看看是否与默认值相同,不同就需要传入:s.cookies.set('BID', '123', domain='www.aidu.com', expires='')



johnnyb 发表于 2020-7-30 15:12:39

本帖最后由 johnnyb 于 2020-7-30 15:14 编辑

suchocolate 发表于 2020-7-30 10:01
纠正一下我在2楼的说法,我仔细看了一些requests的cookie,和selenium虽然对象类型不同,但是内容是差不多 ...

以下是我的全部代码.
我的目的是模拟登陆. 获取cookie然后给Session.get用

截图的cookies是我用抓包软件抓出来的. 完全可以验证登陆状态. 问题还是出在转换上.

from selenium import webdriver
import requests
import pickle

# 创建webdriver对象wd实例化参数是浏览器驱动地址(r'd:\chromedriver.exe')
wd = webdriver.Chrome('chromedriver.exe')


def get_cookies():
    # 隐式等待10秒
    wd.implicitly_wait(5)
    # 在运行的时候不弹出浏览器窗口
    #
    # 使用对象wd控制浏览器 打开网址
    print('opened login page....')
    wd.get('https://www.douban.com')

    wd.switch_to.frame(wd.find_element_by_tag_name("iframe"))
    print('进入iframe')
    wd.find_element_by_class_name('account-tab-account').click()
    print('输入模式')
    wd.find_element_by_class_name('account-form-input').send_keys('账号')
    print('输入账号完毕')
    wd.find_element_by_id('password').send_keys('密码')
    print('输入密码完毕')
    wd.find_element_by_xpath('/html/body/div/div/div/div/a').click()
    print('点击登录完毕')
    return wd.get_cookies()


# 创建一个Session对象
s = requests.Session()
# 取得driver里面的cookies
cookies = get_cookies()
print('get方法获取到的cookies',cookies)
# 遍历cookies里面各项,同时设置给Session对象s的cookie属性
for cookie in cookies:
    s.cookies.set(cookie['name'], cookie['value'])
    print('遍历的:', cookie['name'], cookie['value'])

# driver任务完成 关闭

cookie_dict = requests.utils.dict_from_cookiejar(s.cookies)
for i in cookie_dict.items():
    print('展开cookies的内容:',i)

headers = {
    'Connection': 'keep-alive',
    'Cache-Control': 'max-age=0',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
    '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-site',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-User': '?1',
    'Sec-Fetch-Dest': 'document',
    'Referer': 'https://www.douban.com/',
    'Accept-Language': 'zh-CN,zh;q=0.9',
}
s.headers = headers
# 使用Session对象s访问网页(内部携带了登录cookies)
res = s.get(url='https://www.douban.com/')
print('s使用的cookies:', res.cookies)
cookie_dict = requests.utils.dict_from_cookiejar(res.cookies)
for i in cookie_dict.items():
    print('展开cookies的内容:', i)
print('s使用的headers:', res.headers)
res.encoding = 'utf-8'
print(res.text[:500])

# 写入文件
with open('html.html', 'w+', encoding='utf-8') as f:
    f.write(res.text)

print('end')

johnnyb 发表于 2020-7-30 15:19:11

suchocolate 发表于 2020-7-30 10:01
纠正一下我在2楼的说法,我仔细看了一些requests的cookie,和selenium虽然对象类型不同,但是内容是差不多 ...

那这个get_cookies() 方法还有啥用? 取不全. 还得自己手动去挑. 哪个不一样. 在传进去. 我的理解不是应该. 把当前登陆状态的全部cookie获取到. 保存成一个requestscookie包. 等待处理. 然后创建一个session对象ss.cookies.set(get_cookies()得到的包) 这样就传递给了s对象让它携带. 现在问题是传过去了. 但少了一大堆. 传过去的没法用.   归根原因我猜是不是 get_cookies()方法取不全?我百度还没发现有同样问题. 很恼火. 无人解答.

johnnyb 发表于 2020-7-30 17:40:01

还是没人知道吗?
页: [1]
查看完整版本: 求助cookies操作