鱼C论坛

 找回密码
 立即注册
查看: 1627|回复: 7

[已解决]求助cookies操作

[复制链接]
发表于 2020-7-29 20:52:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

问题描述:
我用selenium模拟登陆douban.登陆成功. 用webdriver.get_cookies()方法 取得登陆成功的cookies为
  1. [{'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用.  让它一直维持登陆状态. 获取需要登陆才能取到的个人主页.  
当我用.
  1. for cookie in cookies:
  2.     s.cookies.set(cookie['name'], cookie['value'])
复制代码

发现. selenium的get_cookies()方法. 传回来的是一个列表. 列表中有3个字典.  这样for他就循环3次. 就完事了. 所以就过去3个值
  1. ('apiKey', '')
  2. ('bid', '-dDW2CjywbM')
  3. ('login_start_time', '1596025621029')
复制代码

我如何能让所有的 name,value 全部过去呢?
尝试了把3个字典合成1个.. 但是里面存在多个重复name  会被顶替成最后一个. 很无解..
或者有没有更好的转换方案? 或者模块?
最佳答案
2020-7-30 10:01:49
纠正一下我在2楼的说法,我仔细看了一些requests的cookie,和selenium虽然对象类型不同,但是内容是差不多的。
  1. >>> s = requests.session()
  2. >>> s.cookies
  3. <RequestsCookieJar[]>
  4. >>> s.cookies.set('BID','123')
  5. 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)
  6. >>>
复制代码
可以看出也有domain,path等参数,所以从selenium获得的cookie字典,需要看看是否与默认值相同,不同就需要传入:
  1. s.cookies.set('BID', '123', domain='www.aidu.com', expires='')
复制代码




小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 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:
  1. driver.get(url)
  2. time.sleep(10)
  3. pickle.dump(driver.get_cookies(), open("cookies.pkl", "wb"))
复制代码

读取时时遍历列表即可:
  1. cookies = pickle.load(open("cookies.pkl", "rb"))
  2. for cookie in cookies:
  3.     driver.add_cookie(cookie)
  4. driver.get(url)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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天了. 还在研究这个问题
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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正确的情况下测试才比较稳妥。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-30 10:01:49 | 显示全部楼层    本楼为最佳答案   
纠正一下我在2楼的说法,我仔细看了一些requests的cookie,和selenium虽然对象类型不同,但是内容是差不多的。
  1. >>> s = requests.session()
  2. >>> s.cookies
  3. <RequestsCookieJar[]>
  4. >>> s.cookies.set('BID','123')
  5. 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)
  6. >>>
复制代码
可以看出也有domain,path等参数,所以从selenium获得的cookie字典,需要看看是否与默认值相同,不同就需要传入:
  1. s.cookies.set('BID', '123', domain='www.aidu.com', expires='')
复制代码




小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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是我用抓包软件抓出来的. 完全可以验证登陆状态. 问题还是出在转换上.
QQ图片20200730151023.png
  1. from selenium import webdriver
  2. import requests
  3. import pickle

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


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

  14.     wd.switch_to.frame(wd.find_element_by_tag_name("iframe"))
  15.     print('进入iframe')
  16.     wd.find_element_by_class_name('account-tab-account').click()
  17.     print('输入模式')
  18.     wd.find_element_by_class_name('account-form-input').send_keys('账号')
  19.     print('输入账号完毕')
  20.     wd.find_element_by_id('password').send_keys('密码')
  21.     print('输入密码完毕')
  22.     wd.find_element_by_xpath('/html/body/div[1]/div[2]/div[1]/div[5]/a').click()
  23.     print('点击登录完毕')
  24.     return wd.get_cookies()


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

  34. # driver任务完成 关闭

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

  38. headers = {
  39.     'Connection': 'keep-alive',
  40.     'Cache-Control': 'max-age=0',
  41.     'Upgrade-Insecure-Requests': '1',
  42.     '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',
  43.     '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',
  44.     'Sec-Fetch-Site': 'same-site',
  45.     'Sec-Fetch-Mode': 'navigate',
  46.     'Sec-Fetch-User': '?1',
  47.     'Sec-Fetch-Dest': 'document',
  48.     'Referer': 'https://www.douban.com/',
  49.     'Accept-Language': 'zh-CN,zh;q=0.9',
  50. }
  51. s.headers = headers
  52. # 使用Session对象s访问网页(内部携带了登录cookies)
  53. res = s.get(url='https://www.douban.com/')
  54. print('s使用的cookies:', res.cookies)
  55. cookie_dict = requests.utils.dict_from_cookiejar(res.cookies)
  56. for i in cookie_dict.items():
  57.     print('展开cookies的内容:', i)
  58. print('s使用的headers:', res.headers)
  59. res.encoding = 'utf-8'
  60. print(res.text[:500])

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

  64. print('end')
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

 楼主| 发表于 2020-7-30 17:40:01 | 显示全部楼层
还是没人知道吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-24 12:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表