鱼C论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 159|回复: 19

关于爬虫cookie的疑惑

[复制链接]
最佳答案
1 
发表于 2019-3-8 22:47:20 | 显示全部楼层 |阅读模式
10鱼币
楼主最近在爬自己学校的教务,发现使用浏览器的时候获得的cookie爬虫用的时候可以获取成绩也的response
而使用requests.Session获得的登陆时响应返回的cookie就无法获取成绩页的response

我自己的思路是,学校教务的cookie可能计算方式非常复杂,使用浏览器登陆时的cookie才是真的,使用爬虫的时候获得cookie便无效。。

我自己尝试了从登陆界面,再到里面获取成绩页的页面,一直在看请求头的cookie,都一直一样,也不是没点一下cookie就稍变了这种,应该是一开始建立Session的时候就已经确定了
所以问题只可能是在最一开始建立的时候,就给了我的爬虫一个假cookie,请问有大佬知道是怎么实现这样的做法吗

吐槽一下破教务居然还有这种。。。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
27 
发表于 2019-3-8 22:56:16 | 显示全部楼层
本帖最后由 Stubborn 于 2019-3-8 23:11 编辑

爬虫就是模拟用户浏览的行为,不存在给你一个假的cookie,你确认下,需不需要额外的请求,来获得需要的额外cookie.
下面是我爬12306网页的网络请求代码:其中,在115行author函数就额外获取了2个cookie,
  1. from PyQt5.Qt import *
  2. from urllib.parse import unquote,quote
  3. import requests,json,base64,re,os,time

  4. class Config(object):

  5.     map_dic = {"1": "hard_seat","9":"business_seat","6":"vip_soft_bed","4":"soft_bed","3":"hard_bed","0":"second_seat","M":"first_seat","F":"move_bed","WZ":"no_seat"}

  6.     @staticmethod
  7.     def get_station_file_path():
  8.         currrent_path = os.path.realpath(__file__) #文件绝对路径
  9.         #print(currrent_path)
  10.         current_dir = os.path.split(currrent_path)[0]
  11.         return current_dir + r"\staionse.json"

  12.     @staticmethod
  13.     def get_yzm_file_path():
  14.         currrent_path = os.path.realpath(__file__) #文件绝对路径
  15.         #print(currrent_path)
  16.         current_dir = os.path.split(currrent_path)[0]
  17.         return current_dir + r"\yzm.jpg"

  18. class TimeToll(object):
  19.     @staticmethod
  20.     def getTrainFormatDate(train_data):
  21.         date_arr = time.strptime(train_data,"%Y%m%d")
  22.         time_tamp = time.mktime(date_arr)
  23.         time_local = time.localtime(time_tamp)
  24.         format = "%a %b %d %Y %H:%M:%S GMT+0800 (China Standard Time)"
  25.         return time.strftime(format,time_local)

  26. class API(object):
  27.     #下载验证码  GET
  28.     GET_YZM_URL = "https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand"

  29.     #校验验证码 POST
  30.     # callback: jQuery191037043257607249735_1550240582305
  31.     # answer: 188, 112, 128, 116
  32.     # rand: sjrand
  33.     # login_site: E
  34.     # _: 1550240582307
  35.     CHECK_YZM_URL = "https://kyfw.12306.cn/passport/captcha/captcha-check?callback"

  36.     #登陆验证 POST
  37.     #username : **
  38.     #password:**
  39.     #appid:otn
  40.     #answer: 253,20,29,29
  41.     CHECK_ACCOUNT_PWD_URL = "https://kyfw.12306.cn/passport/web/login"

  42.     #uamtk POST请求,获取第一个cookie值
  43.     UAMTK_URL = "https://kyfw.12306.cn/passport/web/auth/uamtk"

  44.     #authorclient POST
  45.     #appid:otn
  46.     #tk: 通uamtk获取
  47.     AUTHORT_URL = "https://kyfw.12306.cn/otn/uamauthclient"
  48.     #获取用户姓名,给予问候 POST
  49.     HELLO_URL = "https://kyfw.12306.cn/otn/index/initMy12306Api"

  50.    
  51. class APITool(QObject):

  52.     #保持会话,建立会话对象“客户端”,
  53.     session = requests.session()

  54.     @classmethod  #类方法,因为需要共用cookies,借此保持会话
  55.     def download_yzm(cls):
  56.         print("API_Tool.download_yzm启动:下载验证码")
  57.         response = cls.session.get(API.GET_YZM_URL)
  58.         yzm_file_path = Config.get_yzm_file_path()
  59.         _base64 = (response.json()["image"])
  60.         content = base64.b64decode(_base64)
  61.         with open(yzm_file_path,"wb") as f:
  62.             f.write(content)
  63.         print("API_Tool.download_yzm退出:返回验证码路径")
  64.         return yzm_file_path

  65.     @classmethod
  66.     def check_yzm(cls,yzm):
  67.         print("API_Tool.check_yzm启动:校验验证码")
  68.         data_dic = {
  69.             #"callback": "jQuery191037043257607249735_1550240582305",
  70.             "answer": yzm,
  71.             "rand": "sjrand",
  72.             "login_site": "E",
  73.             #"_": "1550240582307"
  74.         }
  75.         response = cls.session.post(API.CHECK_YZM_URL,data=data_dic)
  76.         result = re.findall(r'.*"(.*)"\}.*',response.text)[0]
  77.         print("API_Tool.check_yzm退出:校验结果=",response.text)
  78.         return result == "4"


  79.     @classmethod
  80.     def check_account_pwd(cls,account,pwd,answer):
  81.         print("API_Tool.check_account_pwd启动:验证登录")
  82.         data_dict = {
  83.             "username" : account,
  84.             "password":pwd,
  85.             "appid":"otn",
  86.             "answer": answer
  87.         }
  88.         response = cls.session.post(API.CHECK_ACCOUNT_PWD_URL,data=data_dict)
  89.         result_code = response.json()["result_code"]
  90.         if result_code == 0:
  91.             cls.author() #授权
  92.             print("API_Tool.check_account_pwd退出:验证通过")
  93.             return ",".join(cls.get_hellow())
  94.         else:
  95.             print("API_Tool.check_account_pwd退出:验证失败")
  96.             return None #授权失败

  97.     @classmethod
  98.     def author(cls):
  99.         print("API_Tool.author启动:获取tk值")
  100.         response = cls.session.post(API.UAMTK_URL,data={"appid":"otn"})
  101.         tk = response.json()["newapptk"]
  102.         print("UAMTK获取成功=",tk)
  103.         cls.session.post(API.AUTHORT_URL,data={"tk":tk})
  104.         print("第二个cookie获取成功")


  105.     @classmethod
  106.     def get_hellow(cls):
  107.         "注意比对cookie值"
  108.         print("API_Tool.get_hellow启动:获取问候信息")
  109.         response = cls.session.post(API.HELLO_URL)
  110.         dic = response.json()
  111.         if dic["httpstatus"] == 200:#获取信息成功
  112.             print("API_Tool.get_hellow退出:",dic["data"]["user_name"],dic["data"]["user_regard"])
  113.             return (dic["data"]["user_name"],dic["data"]["user_regard"]) #用户名 +问候
  114.         else:
  115.             print("API_Tool.get_hellow退出:获取问候信息失败")
  116.             return ("","")





复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-8 23:01:46 | 显示全部楼层
Stubborn 发表于 2019-3-8 22:56
爬虫就是模拟用户浏览的行为,不存在给你一个假的cookie,你确认下,需不需要额外的请求,来获得需要的额外 ...

你好,我确认过了从浏览器访问时获得的cookie与爬虫Session获得的cookie等长,形式一样。
且我使用浏览器获得的cookie粘贴到爬虫里,也可以获得response,但是使用爬虫会话的cookie就获得空
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
27 
发表于 2019-3-8 23:05:51 | 显示全部楼层
t6am3 发表于 2019-3-8 23:01
你好,我确认过了从浏览器访问时获得的cookie与爬虫Session获得的cookie等长,形式一样。
且我使用浏览 ...


只能内网爬么 不然我去看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-8 23:19:29 | 显示全部楼层
本帖最后由 t6am3 于 2019-3-8 23:21 编辑
Stubborn 发表于 2019-3-8 23:05
只能内网爬么 不然我去看看


对的
我详细比对了两条不同的cookie,从爬虫session获得的cookie
  1. B039A199A936D99789E8E5379B877945.tomcat77_1
复制代码

与从Browser获得的
  1. D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1
复制代码

实际上cookie还有其他的字符串,但是除了这一段之外都一样,证据就是使用浏览器获得的cookie在爬虫headers里面粘贴也可以获得response, 但是使用爬虫获得的就不可以。。。

很难受,输出
  1. 03CFBF101DCB5D6B619260C17283AC01.tomcat77_1
  2. 6532
  3. 长度相等吗? True
  4. D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1
  5. {'Server': 'nginx/1.15.3.1 Crow', 'Date': 'Fri, 08 Mar 2019 15:17:26 GMT', 'Content-Type': 'text/html;charset=GBK', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive'}
复制代码

中间6532是验证码,最后一个字典是res头,是用浏览器的cookie登陆时返回的,否则就返回
  1. 7DD897DBF17F161DFB3FBABF5C104FB2.tomcat77_1
  2. 1296
  3. 长度相等吗? True
  4. D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1
  5. {'Server': 'nginx/1.15.3.1 Crow', 'Date': 'Fri, 08 Mar 2019 15:20:53 GMT', 'Content-Type': 'text/html;charset=GBK', 'Content-Length': '0', 'Connection': 'keep-alive'}
复制代码


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
27 
发表于 2019-3-8 23:28:09 | 显示全部楼层
t6am3 发表于 2019-3-8 23:19
对的
我详细比对了两条不同的cookie,从爬虫session获得的cookie
与从Browser获得的


代码不长贴上来,研究研究 还有获取cookie的url 截图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-8 23:30:05 | 显示全部楼层
Stubborn 发表于 2019-3-8 23:05
只能内网爬么 不然我去看看

因为我用浏览器时, cookie一直也没有变过,从我登陆时到获取成绩页
所以想来也不需要多次获取cookie多个字段?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-8 23:33:49 | 显示全部楼层
本帖最后由 t6am3 于 2019-3-8 23:48 编辑
Stubborn 发表于 2019-3-8 23:05
只能内网爬么 不然我去看看


贴一点代码。。我是新手,,但是实在没想通咋回事
  1. import requests
  2. import datetime
  3. import os
  4. from vertificationCodeReg import vertificationCode
  5. from PIL import Image
  6. from PIL import ImageEnhance
  7. from bs4 import  BeautifulSoup as bs

  8. s = requests.Session()

  9. def login():
  10.     initialUrl = ##不显示##
  11.     initHeaders = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Connection': 'keep-alive', 'Host': 'gsmis.graduate.buaa.edu.cn', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
  12.     s.get(initialUrl, headers=initHeaders)

  13.     headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  14.                'Accept-Encoding': 'gzip, deflate',
  15.                'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  16.                'Cache-Control': 'max-age=0',
  17.                'Connection': 'keep-alive',
  18.                'Content-Length': '45',
  19.                'Content-Type': 'application/x-www-form-urlencoded',
  20.                'Host': ##不显示##
  21.                'Origin': ##不显示##
  22.                'Referer': ##不显示##
  23.                'Upgrade-Insecure-Requests': '1',
  24.                'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36',
  25.                }

  26.     JSESSIONID = s.cookies.get_dict()['JSESSIONID']
  27.     headers[ 'Cookie'] = f'JSESSIONID={JSESSIONID}; _ga=GA1.3.1234387313.1538569273; Hm_lvt_8edeba7d3ae859d72148a873531e0fa5=1539923770,1542172342; UM_distinctid=16771ed7aac159-028525f4a66be6-3a3a5d0c-1fa400-16771ed7aad774; CASTGC=TGT-189864-kqSVcobA7GQmbUEG0qmKaEGETmevCpUZL7Tv6VRWOi5HHRY61w-cas'

  28.     loginUrl = ##不显示##

  29.     data = {
  30.        #此部分为隐私
  31.     }
  32.     s.post(loginUrl, headers=headers, data=data)

  33. def gradeQuery():
  34.     headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  35.                'Accept-Encoding': 'gzip, deflate',
  36.                'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  37.                'Connection': 'keep-alive',
  38.                'Host': '##不显示##
  39.                'Referer':##不显示##
  40.                'Upgrade-Insecure-Requests': '1',
  41.                'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
  42.     url = ##不显示##
  43.     #print('query', s.cookies.get_dict())
  44.    
  45.     # 使用这个获取不到response
  46.     JSESSIONID1 = s.cookies.get_dict()['JSESSIONID']
  47.     print("这是Session的cookie", JSESSIONID1)
  48.     # 使用这个获取的到response
  49.     JSESSIONID2 = 'D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1'
  50.     print("这是浏览器的cookie", JSESSIONID2)
  51.     print("长度相等吗?", len(JSESSIONID1)==len(JSESSIONID2))
  52.     headers['Cookie'] = f'JSESSIONID={JSESSIONID1}; _ga=GA1.3.1234387313.1538569273; Hm_lvt_8edeba7d3ae859d72148a873531e0fa5=1539923770,1542172342; UM_distinctid=16771ed7aac159-028525f4a66be6-3a3a5d0c-1fa400-16771ed7aad774; CASTGC=TGT-189864-kqSVcobA7GQmbUEG0qmKaEGETmevCpUZL7Tv6VRWOi5HHRY61w-cas'

  53.     response = requests.get(url, headers=headers)
  54.     print(response.headers)
  55.     soup = bs(response.text, features="lxml")
  56.     with open('response1.html', 'w') as f:
  57.         f.write(response.text)
  58.     #print(soup)
  59.     #parseSoup(soup)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-8 23:36:51 | 显示全部楼层
_谪仙 发表于 2019-3-8 23:35
教务系统有Cookies登录和无Cookies的

这个需要cookies,并且我使用浏览器中截取的cookies粘贴进headers,可以get到response
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
14 
发表于 2019-3-8 23:40:51 | 显示全部楼层
我想问下,你既然使用Session了,还要cookies干嘛?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-8 23:43:17 | 显示全部楼层
本帖最后由 t6am3 于 2019-3-8 23:45 编辑
_谪仙 发表于 2019-3-8 23:40
我想问下,你既然使用Session了,还要cookies干嘛?


因为Session获得的cookies和提交表单的cookies不一样,
Session.cookies.get_dict()获得的字典里只有cookies的一部分字段
但是也只有这一部分字段的cookies是变化的,其他部分的cookies没有变化,所以我获取了这一部分,套进要提交的cookies里就可以提交,
比如我从浏览器里也复制cookies的这变化的一小段,放进我的cookie字段里,就可以get到response,我的代码里就是这么写的,
54-61行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
14 
发表于 2019-3-8 23:48:00 | 显示全部楼层
使用了session可以不需要cookies,session就是帮你维持本地会话,
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-8 23:49:11 | 显示全部楼层
_谪仙 发表于 2019-3-8 23:48
使用了session可以不需要cookies,session就是帮你维持本地会话,

就是维持不了我才没有只使用session的
因为session里的cookies不完全。。。我把里面的字段复制进表单的一部分才可以使用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
27 
发表于 2019-3-8 23:54:01 | 显示全部楼层
本帖最后由 Stubborn 于 2019-3-8 23:59 编辑
t6am3 发表于 2019-3-8 23:49
就是维持不了我才没有只使用session的
因为session里的cookies不完全。。。我把里面的字段复制进表单的 ...


cookies不全,通过额外的网络请求,服务器肯定会给您cookie,不会凭空生出来,我用session去怕12306,从登录到订票,都是用session维持,校内网总不会比12306难爬吧
我上面的代码51行:

  1. #uamtk POST请求,获取第一个cookie值
  2.     UAMTK_URL = "https://kyfw.12306.cn/passport/web/auth/uamtk"

  3.     #authorclient POST
  4.     #appid:otn
  5.     #tk: 通uamtk获取
  6.     AUTHORT_URL = "https://kyfw.12306.cn/otn/uamauthclient"
  7.     #获取用户姓名,给予问候 POST
  8.     HELLO_URL = "https://kyfw.12306.cn/otn/index/initMy12306Api"
复制代码

以及114行 通过UAMTK_URL这个网址获取第一个tk的cookie值,然后用tk的cookie值,进行AUTHORT_URL这个网址,继续获取第二个cookie,两个cookie获取完了,才能获取到正确的已经登录的界面
  1.     @classmethod
  2.     def author(cls):
  3.         print("API_Tool.author启动:获取tk值")
  4.         response = cls.session.post(API.UAMTK_URL,data={"appid":"otn"})
  5.         tk = response.json()["newapptk"]
  6.         print("UAMTK获取成功=",tk)
  7.         cls.session.post(API.AUTHORT_URL,data={"tk":tk})
  8.         print("第二个cookie获取成功")
复制代码


就是用来获取额外的cookie值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-9 00:01:47 | 显示全部楼层
Stubborn 发表于 2019-3-8 23:54
cookies不全,通过额外的网络请求,服务器肯定会给您cookie,不会凭空生出来,我用session去 ...

我觉得你说的很有道理,但是我就是很奇怪,为啥我用浏览器复制过来的cookie,凑进去也可以返回想要的界面。。就这种
  1. headers['Cookie'] = f'JSESSIONID={JSESSIONID1}; _ga=GA1.3.1234387313.1538569273; Hm_lvt_8edeba7d3ae859d72148a873531e0fa5=1539923770,1542172342; UM_distinctid=16771ed7aac159-028525f4a66be6-3a3a5d0c-1fa400-16771ed7aad774; CASTGC=TGT-189864-kqSVcobA7GQmbUEG0qmKaEGETmevCpUZL7Tv6VRWOi5HHRY61w-cas'
复制代码

因为多次比对,发现后面一串实在是固定值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
27 
发表于 2019-3-9 00:06:29 | 显示全部楼层
t6am3 发表于 2019-3-9 00:01
我觉得你说的很有道理,但是我就是很奇怪,为啥我用浏览器复制过来的cookie,凑进去也可以返回想要的界面 ...

试试,直接请求,看看返回了什么cookie值,在和浏览器对比,下有没有少
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-9 00:09:34 | 显示全部楼层
本帖最后由 t6am3 于 2019-3-9 00:10 编辑
Stubborn 发表于 2019-3-8 23:54
cookies不全,通过额外的网络请求,服务器肯定会给您cookie,不会凭空生出来,我用session去 ...


我知道肯定是我的问题。。。我再研究一下,另外我想问一下 抓的包的response头里面没有set-cookies,是不是这个原因,还是因为我chrome的设置不显示set-cookies?还是因为我没有找到有set-cookies的包。。。
我找cookie字段是从request头里面找的,因为response里面一直没有看到有cookies字段
萌新的问题很幼稚。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
27 
发表于 2019-3-9 00:23:38 | 显示全部楼层
t6am3 发表于 2019-3-9 00:09
我知道肯定是我的问题。。。我再研究一下,另外我想问一下 抓的包的response头里面没有set-cookies,是 ...

抓包浏览器开无痕模式去抓包,是开无痕的吗?不然谷歌会缓存的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
106 
发表于 2019-3-9 00:25:08 | 显示全部楼层
你打印一下状态码,看一下是多少??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
最佳答案
1 
 楼主| 发表于 2019-3-9 00:34:16 | 显示全部楼层
Stubborn 发表于 2019-3-9 00:23
抓包浏览器开无痕模式去抓包,是开无痕的吗?不然谷歌会缓存的


见鬼了
我。。。我找到response的cookie字段了!!!
我使用无痕模式去抓包,发现从访问登陆界面到登陆完之后在里面反复横跳,所有的response的cookies字段都为空。。。
我想找下鱼c编辑器的截图功能也找不到。。
c5b123dcf64f7a3329ececb3f4f84fc.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

小甲鱼强烈推荐上一条 /1 下一条

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号

GMT+8, 2019-3-20 04:42

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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