关于爬虫cookie的疑惑
楼主最近在爬自己学校的教务,发现使用浏览器的时候获得的cookie爬虫用的时候可以获取成绩也的response而使用requests.Session获得的登陆时响应返回的cookie就无法获取成绩页的response
我自己的思路是,学校教务的cookie可能计算方式非常复杂,使用浏览器登陆时的cookie才是真的,使用爬虫的时候获得cookie便无效。。
我自己尝试了从登陆界面,再到里面获取成绩页的页面,一直在看请求头的cookie,都一直一样,也不是没点一下cookie就稍变了这种,应该是一开始建立Session的时候就已经确定了
所以问题只可能是在最一开始建立的时候,就给了我的爬虫一个假cookie,请问有大佬知道是怎么实现这样的做法吗
吐槽一下破教务居然还有这种。。。{:9_220:} 本帖最后由 Stubborn 于 2019-3-8 23:11 编辑
爬虫就是模拟用户浏览的行为,不存在给你一个假的cookie,你确认下,需不需要额外的请求,来获得需要的额外cookie.
下面是我爬12306网页的网络请求代码:其中,在115行author函数就额外获取了2个cookie,
from PyQt5.Qt import *
from urllib.parse import unquote,quote
import requests,json,base64,re,os,time
class Config(object):
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"}
@staticmethod
def get_station_file_path():
currrent_path = os.path.realpath(__file__) #文件绝对路径
#print(currrent_path)
current_dir = os.path.split(currrent_path)
return current_dir + r"\staionse.json"
@staticmethod
def get_yzm_file_path():
currrent_path = os.path.realpath(__file__) #文件绝对路径
#print(currrent_path)
current_dir = os.path.split(currrent_path)
return current_dir + r"\yzm.jpg"
class TimeToll(object):
@staticmethod
def getTrainFormatDate(train_data):
date_arr = time.strptime(train_data,"%Y%m%d")
time_tamp = time.mktime(date_arr)
time_local = time.localtime(time_tamp)
format = "%a %b %d %Y %H:%M:%S GMT+0800 (China Standard Time)"
return time.strftime(format,time_local)
class API(object):
#下载验证码GET
GET_YZM_URL = "https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand"
#校验验证码 POST
# callback: jQuery191037043257607249735_1550240582305
# answer: 188, 112, 128, 116
# rand: sjrand
# login_site: E
# _: 1550240582307
CHECK_YZM_URL = "https://kyfw.12306.cn/passport/captcha/captcha-check?callback"
#登陆验证 POST
#username : **
#password:**
#appid:otn
#answer: 253,20,29,29
CHECK_ACCOUNT_PWD_URL = "https://kyfw.12306.cn/passport/web/login"
#uamtk POST请求,获取第一个cookie值
UAMTK_URL = "https://kyfw.12306.cn/passport/web/auth/uamtk"
#authorclient POST
#appid:otn
#tk: 通uamtk获取
AUTHORT_URL = "https://kyfw.12306.cn/otn/uamauthclient"
#获取用户姓名,给予问候 POST
HELLO_URL = "https://kyfw.12306.cn/otn/index/initMy12306Api"
class APITool(QObject):
#保持会话,建立会话对象“客户端”,
session = requests.session()
@classmethod#类方法,因为需要共用cookies,借此保持会话
def download_yzm(cls):
print("API_Tool.download_yzm启动:下载验证码")
response = cls.session.get(API.GET_YZM_URL)
yzm_file_path = Config.get_yzm_file_path()
_base64 = (response.json()["image"])
content = base64.b64decode(_base64)
with open(yzm_file_path,"wb") as f:
f.write(content)
print("API_Tool.download_yzm退出:返回验证码路径")
return yzm_file_path
@classmethod
def check_yzm(cls,yzm):
print("API_Tool.check_yzm启动:校验验证码")
data_dic = {
#"callback": "jQuery191037043257607249735_1550240582305",
"answer": yzm,
"rand": "sjrand",
"login_site": "E",
#"_": "1550240582307"
}
response = cls.session.post(API.CHECK_YZM_URL,data=data_dic)
result = re.findall(r'.*"(.*)"\}.*',response.text)
print("API_Tool.check_yzm退出:校验结果=",response.text)
return result == "4"
@classmethod
def check_account_pwd(cls,account,pwd,answer):
print("API_Tool.check_account_pwd启动:验证登录")
data_dict = {
"username" : account,
"password":pwd,
"appid":"otn",
"answer": answer
}
response = cls.session.post(API.CHECK_ACCOUNT_PWD_URL,data=data_dict)
result_code = response.json()["result_code"]
if result_code == 0:
cls.author() #授权
print("API_Tool.check_account_pwd退出:验证通过")
return ",".join(cls.get_hellow())
else:
print("API_Tool.check_account_pwd退出:验证失败")
return None #授权失败
@classmethod
def author(cls):
print("API_Tool.author启动:获取tk值")
response = cls.session.post(API.UAMTK_URL,data={"appid":"otn"})
tk = response.json()["newapptk"]
print("UAMTK获取成功=",tk)
cls.session.post(API.AUTHORT_URL,data={"tk":tk})
print("第二个cookie获取成功")
@classmethod
def get_hellow(cls):
"注意比对cookie值"
print("API_Tool.get_hellow启动:获取问候信息")
response = cls.session.post(API.HELLO_URL)
dic = response.json()
if dic["httpstatus"] == 200:#获取信息成功
print("API_Tool.get_hellow退出:",dic["data"]["user_name"],dic["data"]["user_regard"])
return (dic["data"]["user_name"],dic["data"]["user_regard"]) #用户名 +问候
else:
print("API_Tool.get_hellow退出:获取问候信息失败")
return ("","")
Stubborn 发表于 2019-3-8 22:56
爬虫就是模拟用户浏览的行为,不存在给你一个假的cookie,你确认下,需不需要额外的请求,来获得需要的额外 ...
你好,我确认过了从浏览器访问时获得的cookie与爬虫Session获得的cookie等长,形式一样。
且我使用浏览器获得的cookie粘贴到爬虫里,也可以获得response,但是使用爬虫会话的cookie就获得空 t6am3 发表于 2019-3-8 23:01
你好,我确认过了从浏览器访问时获得的cookie与爬虫Session获得的cookie等长,形式一样。
且我使用浏览 ...
只能内网爬么{:10_254:} 不然我去看看{:10_245:} 本帖最后由 t6am3 于 2019-3-8 23:21 编辑
Stubborn 发表于 2019-3-8 23:05
只能内网爬么 不然我去看看
对的{:10_285:}
我详细比对了两条不同的cookie,从爬虫session获得的cookieB039A199A936D99789E8E5379B877945.tomcat77_1
与从Browser获得的
D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1
实际上cookie还有其他的字符串,但是除了这一段之外都一样,证据就是使用浏览器获得的cookie在爬虫headers里面粘贴也可以获得response, 但是使用爬虫获得的就不可以。。。
很难受,输出
03CFBF101DCB5D6B619260C17283AC01.tomcat77_1
6532
长度相等吗? True
D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1
{'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登陆时返回的,否则就返回
7DD897DBF17F161DFB3FBABF5C104FB2.tomcat77_1
1296
长度相等吗? True
D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1
{'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'}
t6am3 发表于 2019-3-8 23:19
对的
我详细比对了两条不同的cookie,从爬虫session获得的cookie
与从Browser获得的
代码不长贴上来,研究研究{:10_258:} 还有获取cookie的url 截图 Stubborn 发表于 2019-3-8 23:05
只能内网爬么 不然我去看看
因为我用浏览器时, cookie一直也没有变过,从我登陆时到获取成绩页
所以想来也不需要多次获取cookie多个字段? 本帖最后由 t6am3 于 2019-3-8 23:48 编辑
Stubborn 发表于 2019-3-8 23:05
只能内网爬么 不然我去看看
贴一点代码。。我是新手,,但是实在没想通咋回事
import requests
import datetime
import os
from vertificationCodeReg import vertificationCode
from PIL import Image
from PIL import ImageEnhance
from bs4 importBeautifulSoup as bs
s = requests.Session()
def login():
initialUrl = ##不显示##
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'}
s.get(initialUrl, headers=initHeaders)
headers = {'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',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Content-Length': '45',
'Content-Type': 'application/x-www-form-urlencoded',
'Host': ##不显示##
'Origin': ##不显示##
'Referer': ##不显示##
'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',
}
JSESSIONID = s.cookies.get_dict()['JSESSIONID']
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'
loginUrl = ##不显示##
data = {
#此部分为隐私
}
s.post(loginUrl, headers=headers, data=data)
def gradeQuery():
headers = {'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': '##不显示##
'Referer':##不显示##
'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'}
url = ##不显示##
#print('query', s.cookies.get_dict())
# 使用这个获取不到response
JSESSIONID1 = s.cookies.get_dict()['JSESSIONID']
print("这是Session的cookie", JSESSIONID1)
# 使用这个获取的到response
JSESSIONID2 = 'D82FCE15DF573FBEE86A4A7C2FD470CA.tomcat77_1'
print("这是浏览器的cookie", JSESSIONID2)
print("长度相等吗?", len(JSESSIONID1)==len(JSESSIONID2))
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'
response = requests.get(url, headers=headers)
print(response.headers)
soup = bs(response.text, features="lxml")
with open('response1.html', 'w') as f:
f.write(response.text)
#print(soup)
#parseSoup(soup) _谪仙 发表于 2019-3-8 23:35
教务系统有Cookies登录和无Cookies的
这个需要cookies,并且我使用浏览器中截取的cookies粘贴进headers,可以get到response 我想问下,你既然使用Session了,还要cookies干嘛?
本帖最后由 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行 使用了session可以不需要cookies,session就是帮你维持本地会话, _谪仙 发表于 2019-3-8 23:48
使用了session可以不需要cookies,session就是帮你维持本地会话,
就是维持不了我才没有只使用session的
因为session里的cookies不完全。。。我把里面的字段复制进表单的一部分才可以使用 本帖最后由 Stubborn 于 2019-3-8 23:59 编辑
t6am3 发表于 2019-3-8 23:49
就是维持不了我才没有只使用session的
因为session里的cookies不完全。。。我把里面的字段复制进表单的 ...
{:10_299:}cookies不全,通过额外的网络请求,服务器肯定会给您cookie,不会凭空生出来,我用session去怕12306,从登录到订票,都是用session维持,校内网总不会比12306难爬吧{:10_284:}
我上面的代码51行:
#uamtk POST请求,获取第一个cookie值
UAMTK_URL = "https://kyfw.12306.cn/passport/web/auth/uamtk"
#authorclient POST
#appid:otn
#tk: 通uamtk获取
AUTHORT_URL = "https://kyfw.12306.cn/otn/uamauthclient"
#获取用户姓名,给予问候 POST
HELLO_URL = "https://kyfw.12306.cn/otn/index/initMy12306Api"
以及114行 通过UAMTK_URL这个网址获取第一个tk的cookie值,然后用tk的cookie值,进行AUTHORT_URL这个网址,继续获取第二个cookie,两个cookie获取完了,才能获取到正确的已经登录的界面
@classmethod
def author(cls):
print("API_Tool.author启动:获取tk值")
response = cls.session.post(API.UAMTK_URL,data={"appid":"otn"})
tk = response.json()["newapptk"]
print("UAMTK获取成功=",tk)
cls.session.post(API.AUTHORT_URL,data={"tk":tk})
print("第二个cookie获取成功")
就是用来获取额外的cookie值
Stubborn 发表于 2019-3-8 23:54
cookies不全,通过额外的网络请求,服务器肯定会给您cookie,不会凭空生出来,我用session去 ...
我觉得你说的很有道理,但是我就是很奇怪,为啥我用浏览器复制过来的cookie,凑进去也可以返回想要的界面。。就这种
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'
因为多次比对,发现后面一串实在是固定值 t6am3 发表于 2019-3-9 00:01
我觉得你说的很有道理,但是我就是很奇怪,为啥我用浏览器复制过来的cookie,凑进去也可以返回想要的界面 ...
试试,直接请求,看看返回了什么cookie值,在和浏览器对比,下有没有少 本帖最后由 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字段
萌新的问题很幼稚。。 t6am3 发表于 2019-3-9 00:09
我知道肯定是我的问题。。。我再研究一下,另外我想问一下 抓的包的response头里面没有set-cookies,是 ...
抓包浏览器开无痕模式去抓包,是开无痕的吗?不然谷歌会缓存的 你打印一下状态码,看一下是多少?? Stubborn 发表于 2019-3-9 00:23
抓包浏览器开无痕模式去抓包,是开无痕的吗?不然谷歌会缓存的
见鬼了
我。。。我找到response的cookie字段了!!!
我使用无痕模式去抓包,发现从访问登陆界面到登陆完之后在里面反复横跳,所有的response的cookies字段都为空。。。
我想找下鱼c编辑器的截图功能也找不到。。
页:
[1]
2