0


selenium+requests 实现网页跳转登录及爬取

项目背景

  • 本项目设立目的是为了通过脚本,实现学校体育场馆的“秒约”。便于同学瞬间抢到热门时间段的体育场
  • 服务器工作峰值时浏览器可能会卡死,因此例如selenium等需要加载浏览器界面的库可能会降低效率
  • 采用requests库直接向服务器发送请求,效率更高。

项目的组成部分

通过selenium库模拟登录获取cookies

**如果在预约界面,点击“预约”按钮。然后抓包获取

headers

cookies

等参数,很有可能只获取的一部分**

cookies


如果传递的

cookies

参数不够全面,很有可能重新跳转至登录界面。

requests.post()

返回的内容如下:
(返回跳转到登录网址的代码,而不是原网址内容)
在这里插入图片描述

而如果通过requests库,走正常流程登录时,登录系统用户名及密码通常进行过加密。使得我们不知道如何向系统传递参数进行登录。(如图)
在这里插入图片描述

因此我们可以通过用selenium模拟用户成功登录后,通过selenium获取cookies传递给requests,借壳上市,实现requests对页面的成功访问。同时也不会影响在抢预约时的效率。
***此外需要注意的是,建议采用

requests.Session()

来进行访问。

Session

对象可以获取响应的cookies值并自动进行记录,可以保持一个持续会话的状态,避免后面访问网址需要多次传递cookies***
具体代码如下:

print('开始自动化操作')# 绕过人机检查
options = webdriver.EdgeOptions()
options.add_experimental_option("excludeSwitches",["enable-automation"])
options.add_experimental_option('useAutomationExtension',False)# 采用Edge驱动
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})'})# 直接获取预约界面,随后跳转至登录界面。完成登录后,会再跳转至预约界面。
wb.get(r'http://XXX.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1')# 设置隐式等待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中所有的cookiesprint(wb.get_cookies())# 设置访问头
headers ={
    略...}# 创建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对象内存
wb.close()# 打印session对象中所有的cookiesprint(se.cookies)# 访问预约网址
r1 = se.get(r'http://.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1', headers=headers)# 打印预约网址源码,打印成功即成功登录print(r1.text)

向服务器发送请求获取验证码并识别

至此,即将进入本项目第二个难点。获取验证码及识别
在选好场地和时间后,需要输入手机号及验证码才能点击预约。(如图)
在这里插入图片描述

通过抓包,我们能够清楚的知道请求网址及传递的参数。(如图)
在这里插入图片描述
现在唯一需要做的就是验证码的识别。**通过开发者工具确定验证码图片位置,随后通过

Session

对象访问图片地址,并保存在本地**。、
在这里插入图片描述
实现代码如下:

# 访问验证码地址
r2 = se.get(r'http://yuyue.XXX.XXX.cn/eduplus/validateimage', headers = headers)
image_path ='test'+str(random.randint(0,99999))+'.jpg'withopen(image_path,'wb')as f:
    f.write(r2.content)

随后通过第三方接口,实现对验证码的识别及输出
(此次我选择的是图灵,虽然收费但是十分便宜)
实现代码如下:

# 图灵官方提供的API接口defb64_api(username, password, img_path, ID):withopen(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')

向服务器发送请求,实现预约

最后汇总参数向服务器发起预约。以下为项目整体代码:

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

# 图灵验证码识别官方接口defb64_api(username, password, img_path, ID):withopen(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驱动
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})'})# 直接获取预约界面,随后跳转至登录界面。完成登录后,会再跳转至预约界面。
wb.get(r'http://XXX.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1')# 设置隐式等待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中所有的cookiesprint(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'}# 创建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对象内存
wb.close()# 打印session对象中所有的cookiesprint(se.cookies)# 访问预约网址
r1 = se.get(r'http://XXX.XXX.edu.cn/eduplus/order/initOrderIndex.do?sclId=1', headers=headers)# 打印预约网址源码,打印成功即成功登录print(r1.text)# 访问验证码网址
r2 = se.get(r'http://XXX.XXX.edu.cn/eduplus/validateimage', headers = headers)
image_path ='test'+str(random.randint(0,99999))+'.jpg'withopen(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')# 相关预约参数
data={'useTime':'XXX',# 预约时段'预约项目':'XXX',#  时段项目, 10 为九龙湖羽毛球'allowHalf':'2','validateCode': validate_code,# 验证码'phone':'XXX',# 手机号'remark':''# 备注}# 向网站发出预约
r3 = se.post('http://XXX.XXX.edu.cn/eduplus/order/order/getOrderInfo.do?sclId=1', headers=headers, data=data)input('结束')

新人项目,欢迎指教交流!

标签: selenium python 爬虫

本文转载自: https://blog.csdn.net/qq_22649229/article/details/133104505
版权归原作者 东南方的某硕 所有, 如有侵权,请联系我们删除。

“selenium+requests 实现网页跳转登录及爬取”的评论:

还没有评论