項目背景
- 本項目設(shè)立目的是為了通過腳本,實現(xiàn)學(xué)校體育場館的“秒約”。便于同學(xué)瞬間搶到熱門時間段的體育場。
- 服務(wù)器工作峰值時瀏覽器可能會卡死,因此例如selenium等需要加載瀏覽器界面的庫可能會降低效率。
- 采用requests庫直接向服務(wù)器發(fā)送請求,效率更高。
項目的組成部分
通過selenium庫模擬登錄獲取cookies
如果在預(yù)約界面,點擊“預(yù)約”按鈕。然后抓包獲取headers
、cookies
等參數(shù),很有可能只獲取的一部分cookies
。
如果傳遞的cookies
參數(shù)不夠全面,很有可能重新跳轉(zhuǎn)至登錄界面。requests.post()
返回的內(nèi)容如下:
(返回跳轉(zhuǎn)到登錄網(wǎng)址的代碼,而不是原網(wǎng)址內(nèi)容)
而如果通過requests庫,走正常流程登錄時,登錄系統(tǒng)用戶名及密碼通常進(jìn)行過加密。使得我們不知道如何向系統(tǒng)傳遞參數(shù)進(jìn)行登錄。(如圖)
因此我們可以通過用selenium模擬用戶成功登錄后,通過selenium獲取cookies傳遞給requests,借殼上市,實現(xiàn)requests對頁面的成功訪問。同時也不會影響在搶預(yù)約時的效率。
此外需要注意的是,建議采用requests.Session()
來進(jìn)行訪問。Session
對象可以獲取響應(yīng)的cookies值并自動進(jìn)行記錄,可以保持一個持續(xù)會話的狀態(tài),避免后面訪問網(wǎng)址需要多次傳遞cookies
具體代碼如下:
print('開始自動化操作')
# 繞過人機檢查
options = webdriver.EdgeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 采用Edge驅(qū)動
wb = webdriver.Edge(options = options,service=Service(r'D:\軟件\PyCharm Community Edition 2023.1.3\edgedriver_win64\msedgedriver.exe'))
# 繞過人機檢查
wb.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
# 直接獲取預(yù)約界面,隨后跳轉(zhuǎn)至登錄界面。完成登錄后,會再跳轉(zhuǎn)至預(yù)約界面。
wb.get(r'http://XXX.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1')
# 設(shè)置隱式等待5秒
wb.implicitly_wait(5)
# 在登錄界面,找到用戶名和密碼框
user = wb.find_element(By.XPATH, '/html/body/div/div[2]/div[3]/div/div[4]/div/form/p[1]/input')
password = wb.find_element(By.XPATH, '/html/body/div/div[2]/div[3]/div/div[4]/div/form/p[2]/input[1]')
login = wb.find_element(By.XPATH, '/html/body/div/div[2]/div[3]/div/div[4]/div/form/p[5]')
# 輸入用戶名及密碼完成登錄
user.send_keys('XXX')
password.send_keys('XXXX')
login.click()
time.sleep(3)
# 打印wb中所有的cookies
print(wb.get_cookies())
# 設(shè)置訪問頭
headers = {
略...
}
# 創(chuàng)建session對話對象
se = requests.Session()
# 將wb中所有的cookies傳遞給session對象
for co in wb.get_cookies():
requests.utils.add_dict_to_cookiejar(se.cookies, {co['name']: co['value']})
# 撤銷wb對象內(nèi)存
wb.close()
# 打印session對象中所有的cookies
print(se.cookies)
# 訪問預(yù)約網(wǎng)址
r1 = se.get(r'http://.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1', headers=headers)
# 打印預(yù)約網(wǎng)址源碼,打印成功即成功登錄
print(r1.text)
向服務(wù)器發(fā)送請求獲取驗證碼并識別
至此,即將進(jìn)入本項目第二個難點。獲取驗證碼及識別。
在選好場地和時間后,需要輸入手機號及驗證碼才能點擊預(yù)約。(如圖)
通過抓包,我們能夠清楚的知道請求網(wǎng)址及傳遞的參數(shù)。(如圖)
現(xiàn)在唯一需要做的就是驗證碼的識別。通過開發(fā)者工具確定驗證碼圖片位置,隨后通過Session
對象訪問圖片地址,并保存在本地。、
實現(xiàn)代碼如下:
# 訪問驗證碼地址
r2 = se.get(r'http://yuyue.XXX.XXX.cn/eduplus/validateimage', headers = headers)
image_path = 'test' + str(random.randint(0,99999)) + '.jpg'
with open(image_path, 'wb') as f:
f.write(r2.content)
隨后通過第三方接口,實現(xiàn)對驗證碼的識別及輸出。
(此次我選擇的是圖靈,雖然收費但是十分便宜)
實現(xiàn)代碼如下:
# 圖靈官方提供的API接口
def b64_api(username, password, img_path, ID):
with open(img_path, 'rb') as f:
b64_data = base64.b64encode(f.read())
b64 = b64_data.decode()
data = {"username": username, "password": password, "ID": ID, "b64": b64, "version": "3.1.1"}
data_json = json.dumps(data)
result = json.loads(requests.post("http://www.fdyscloud.com.cn/tuling/predict", data=data_json).text)
return result
# 通過圖靈官方接口,識別驗證碼
result = b64_api(username="XXX", password="XXX", img_path=image_path, ID="XXXX")
validate_code = result.get('data').get('result')
向服務(wù)器發(fā)送請求,實現(xiàn)預(yù)約
最后匯總參數(shù)向服務(wù)器發(fā)起預(yù)約。以下為項目整體代碼:文章來源:http://www.zghlxwxcb.cn/news/detail-764963.html
import time
import random
import json
import base64
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.common.by import By
import requests
# 圖靈驗證碼識別官方接口
def b64_api(username, password, img_path, ID):
with open(img_path, 'rb') as f:
b64_data = base64.b64encode(f.read())
b64 = b64_data.decode()
data = {"username": username, "password": password, "ID": ID, "b64": b64, "version": "3.1.1"}
data_json = json.dumps(data)
result = json.loads(requests.post("http://www.fdyscloud.com.cn/tuling/predict", data=data_json).text)
return result
print('開始自動化操作')
# 繞過人機檢查
options = webdriver.EdgeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 采用Edge驅(qū)動
wb = webdriver.Edge(options = options,service=Service(r'D:\軟件\PyCharm Community Edition 2023.1.3\edgedriver_win64\msedgedriver.exe'))
# 繞過人機檢查
wb.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
# 直接獲取預(yù)約界面,隨后跳轉(zhuǎn)至登錄界面。完成登錄后,會再跳轉(zhuǎn)至預(yù)約界面。
wb.get(r'http://XXX.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1')
# 設(shè)置隱式等待5秒
wb.implicitly_wait(5)
# 在登錄界面,找到用戶名和密碼框
user = wb.find_element(By.XPATH, '/html/body/div/div[2]/div[3]/div/div[4]/div/form/p[1]/input')
password = wb.find_element(By.XPATH, '/html/body/div/div[2]/div[3]/div/div[4]/div/form/p[2]/input[1]')
login = wb.find_element(By.XPATH, '/html/body/div/div[2]/div[3]/div/div[4]/div/form/p[5]')
# 輸入用戶名及密碼完成登錄
user.send_keys('XXX')
password.send_keys('XXX')
login.click()
time.sleep(3)
# 打印wb中所有的cookies
print(wb.get_cookies())
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Host': 'XXX.XXX.edu.cn',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
}
# 創(chuàng)建session對話對象
se = requests.Session()
# 將wb中所有的cookies傳遞給session對象
for co in wb.get_cookies():
requests.utils.add_dict_to_cookiejar(se.cookies, {co['name']: co['value']})
# 撤銷wb對象內(nèi)存
wb.close()
# 打印session對象中所有的cookies
print(se.cookies)
# 訪問預(yù)約網(wǎng)址
r1 = se.get(r'http://XXX.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1', headers=headers)
# 打印預(yù)約網(wǎng)址源碼,打印成功即成功登錄
print(r1.text)
# 訪問驗證碼網(wǎng)址
r2 = se.get(r'http://XXX.XXX.edu.cn/eduplus/validateimage', headers = headers)
image_path = 'test' + str(random.randint(0,99999)) + '.jpg'
with open(image_path, 'wb') as f:
f.write(r2.content)
# 通過圖靈官方接口,識別驗證碼
result = b64_api(username="XXX", password="XXX", img_path=image_path, ID="XXX")
validate_code = result.get('data').get('result')
# 相關(guān)預(yù)約參數(shù)
data={
'useTime': 'XXX', # 預(yù)約時段
'預(yù)約項目': 'XXX', # 時段項目, 10 為九龍湖羽毛球
'allowHalf': '2',
'validateCode': validate_code, # 驗證碼
'phone': 'XXX', # 手機號
'remark': '' # 備注
}
# 向網(wǎng)站發(fā)出預(yù)約
r3 = se.post('http://XXX.XXX.edu.cn/eduplus/order/order/getOrderInfo.do?sclId=1', headers=headers, data=data)
input('結(jié)束')
新人項目,歡迎指教交流!文章來源地址http://www.zghlxwxcb.cn/news/detail-764963.html
到了這里,關(guān)于selenium+requests 實現(xiàn)網(wǎng)頁跳轉(zhuǎn)登錄及爬取的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!