鍍金池/ 問答/Python  Linux/ Python Selenium模擬登錄成功后,使用此cookie、利用reque

Python Selenium模擬登錄成功后,使用此cookie、利用requests庫進行g(shù)et時,提示“非法登陸”。

一. 步驟概述

 a. 模擬登錄學(xué)校選課系統(tǒng)(使用Selenium庫登陸http://xk.suibe.edu.cn/xsxk/login.xk)
 b. 取得cookie后傳入requests的session中。(參考博客:https://blog.csdn.net/big__v/article/details/78151940)
 c. 使用requests庫中的post提交選課序號至http://xk.suibe.edu.cn/xsxk/xkOper.xk
 d. 完成選課

二. 手動登錄時瀏覽器截圖(Chrmoe)

1. 登錄時request headers(這里有一個cookie就是之后會出錯的地方。)

圖片描述

2. 登錄時post

圖片描述
三. 出錯情況概述

1. 如果手動用瀏覽器登錄并復(fù)制上述cookie直接進入get的headers里,get命令能夠成功完成,并提示選課成功。
2. 如果把手動用瀏覽器登錄這一步用Selenium模擬登錄代替,并直接將cookies傳入requests的session中,再次嘗試gett就會報出“非法進入”。

四. 問題排除

1. 第二步get推測沒有問題,因為復(fù)制瀏覽器中cookie直接進入get的headers里,post命令能夠成功完成。
2. 不是cookie格式問題,因為格式問題會導(dǎo)致報錯“登錄過期”,而不是“非法登錄”。

五. 問題猜測

  1. 猜測可能cookie進行過加密
  2. 猜測存在其他反爬蟲手段
  3. 猜測cookie存在時效性

六. 完整代碼如下

# -*- coding:utf-8 -*-
from selenium import webdriver
import requests
from selenium.webdriver.support.wait import WebDriverWait

# 添加選課序號
codes = []
while True:
    code = raw_input(u'請輸入選課序號(輸入回車結(jié)束):')
    if code != '':
        codes.append(code)
    else:
        break

# 開始登錄
driver = webdriver.Chrome()
url = "http://xk.suibe.edu.cn/xsxk/login.xk"
s = requests.session()
while True:
    driver.get(url)
    name_input = driver.find_element_by_id('username')  # 找到用戶名的框框
    pass_input = driver.find_element_by_id('password')  # 找到輸入密碼的框框
    login_button = driver.find_element_by_xpath('//*[@id="loginForm"]/table/tbody/tr[4]/td[2]/input[1]')
    name_input.clear()
    name_input.send_keys('1*******')  # 填寫用戶名
    pass_input.clear()
    pass_input.send_keys('********')  # 填寫密碼
    WebDriverWait(driver, 300000000).until_not(lambda x: x.find_element_by_id("verifyCode").is_displayed())  # 等待直到登錄成功
    if u'夜大學(xué)' in driver.page_source:
        print u"登錄成功!"
        selenium_cookies = driver.get_cookies()  # 把selenium獲取的cookies保存到變量,備用。
        # print(selenium_cookies)
        driver.close()
        break
    else:
        driver.close()

# 處理cookie
s = requests.Session()
for i in selenium_cookies:
    requests.utils.add_dict_to_cookiejar(s.cookies, {i['name']: i['value']})

# 以下用post提交選課
for code in codes:
    info = {'method': 'handleQxgxk',
            'jxbid': '201820191' + code,
            'glJxbid': '',
            'xyjc': ''}
    r = s.get('http://xk.suibe.edu.cn/xsxk/xkOper.xk', params=info)
    if 'false' in r.text:
        print '選課序號:%s,選課失敗。' % code, r.text
    else:
        print '選課序號:%s,選課成功。' % code
回答
編輯回答
神經(jīng)質(zhì)

既然是 POST 表單,應(yīng)該將 session.get() 改成 session.post(),同時 params= 的值改向 data=。

另外,可以開啟 wireshark 抓包確認(rèn)瀏覽器最后一次得到的 cookie,與你用 requests 發(fā)出去的一致。

若仍然不奏效,嘗試添加 User-AgentReferer 請求頭參數(shù)到 session.post()。

2017年8月15日 10:51
編輯回答
笨尐豬

問題解決了——是存在第二次驗證的問題(我也不知道叫什么,姑且這么叫它,如有不對請各位在評論指出。)
一開始猜測是編碼有問題——畢竟python2.7的編碼實在是讓人有些頭疼。各種調(diào)試之后發(fā)現(xiàn)并不是編碼問題。
繼續(xù)從頭分析瀏覽器后發(fā)現(xiàn)這么一個get,如圖:
圖片描述
猜測這個是“二次認(rèn)證”。
果斷在代碼中加入如下代碼:

check = s.get('http://xk.suibe.edu.cn/xsxk/xkjs.xk?pyfaid=04265&jxqdm=2&data-frameid=main&data-timer=2000&data-proxy=proxy.xk', headers=headers)

然后就成功了。

2017年12月7日 03:55