import time
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
# 邮件配置
smtp_server = '你用的邮箱的服务器地址' # SMTP 服务器地址
smtp_port = SMTP端口 # SMTP 端口(通常为587或465)
email_user = '你的邮箱' # 发件人邮箱
email_password = '你的邮箱密码' # 发件人邮箱密码
recipient_email = '收件人邮箱密码' # 收件人邮箱
subject = '实验项目预约输出' # 邮件主题
body = '请查收实验项目预约的输出文件。'# 邮件正文
# 创建邮件
msg = MIMEMultipart()
msg['From'] = email_user
msg['To'] = recipient_email
msg['Subject'] = subject
# 附加邮件正文
msg.attach(MIMEText(body, 'plain'))
# 初始化 WebDriver
driver = webdriver.Chrome()
# 登录页面
driver.get('需要登陆的网站地址')
# 输入用户名和密码
driver.find_element(By.ID, 'username').send_keys('账号')
driver.find_element(By.ID, 'password').send_keys('密码')
# 点击登录按钮
driver.find_element(By.XPATH, '//*[@id="fm1"]/div/table/tbody/tr[4]/td/input[1]').click()
while(True):
# 获取跳转后的页面
driver.get('大物选课界面的src')
# 等待页面加载完毕
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "tbody")))
# 重新获取页面信息
page_source = driver.page_source
soup = BeautifulSoup(page_source, 'html.parser')
# 获取所有行
rows = soup.find_all('tr', align='center')
# 指定要检查的实验项目名称
target_projects = ["导热系数测量", "磁悬浮动力学", "声速测定", "刚体转动惯量的测定", "霍尔效应及螺线管测磁场"]
# 用于记录已预约的课程及其时间
reserved_courses = {}
#记录是否允许发送文件
available = False
# 打开输出文件
with open('output.txt', 'w', encoding='utf-8') as output_file:
for row in rows:
# 获取实验项目名称
project_name_cell = row.find_all('td')[2] # 假设实验项目名称是第3列
project_name = project_name_cell.text.strip()
# 查找状态单元格
status_cell = row.find('span', id=lambda x: x and x.startswith('gvUser_ctl'))
# 打印状态和项目名称
if status_cell and project_name in target_projects:
output_file.write(f'实验项目: {project_name}, 当前行状态: {status_cell.text}\n')
# 如果可以预约且项目属于目标项目之一
if '预约课堂' in status_cell.text and project_name in target_projects:
link = status_cell.find('a') # 查找链接
if link:
full_url = f"http://syjx.hyit.edu.cn/student/{link['href']}"
output_file.write(f'预约课堂链接: {full_url}\n')
# 进入预约课堂的链接
driver.get(full_url)
driver.find_element(By.XPATH, '//*[@id="ddlxq"]/option[3]').click()
soup1 = BeautifulSoup(driver.page_source, 'html.parser')
# 获取所有对齐为center的行
rows1 = soup1.find_all('tr', align='center')
# 用于记录是否找到可预约的项目
found_available = False
for row1 in rows1:
# 获取实验项目名称
project_name_cell = row1.find_all('td')[1] # 假设实验项目名称是第2列
project_name = project_name_cell.find('font').text.strip() # 提取 <font> 标签中的文本
if project_name:
# 获取实验时间
time_cell = row1.find_all('td')[3].text.strip() # 第4列为实验时间
# 获取预约进度
progress_cell = row1.find_all('td')[5].text.strip() # 第6列为预约进度
# 提取时间部分并解析
time_str = time_cell.split()[2] # 获取时间部分
experiment_time = datetime.strptime(time_str, '%H:%M:%S') # 解析时间
# 解析预约进度
total, current = map(int, progress_cell.split('/')) # 预约进度格式为"当前/总数"
# 检查条件:时间在9点之后且当前预约人数小于总人数
if experiment_time.hour >= 9 and current < total:
# 检查是否已预约该课程
if project_name not in reserved_courses:
# 检查与已预约课程的时间冲突
if not any(
abs((experiment_time - time).total_seconds()) < 7200 # <2小时冲突
for time in reserved_courses.values()
):
available = found_available = True
output_file.write(f'实验项目: {project_name.strip()}, '
f'指导教师: {row1.find_all("td")[2].text.strip()}, '
f'实验时间: {time_cell}, '
f'预约进度: {progress_cell}\n')
reserve_button = row1.find('input', {'type': 'submit'})
if reserve_button and reserve_button.get('disabled') != 'disabled':
driver.execute_script("arguments[0].click();", reserve_button)
output_file.write(f'成功预约实验项目: {project_name.strip()}\n')
reserved_courses[project_name] = experiment_time # 记录已预约课程及时间
else:
output_file.write(f'预约按钮不可用: {project_name.strip()}\n')
else:
output_file.write(f'课程 {project_name} 已预约\n')
if(available):
file_path = r'电脑中.txt文件的地址' # 本地文件路径
with open(file_path, 'rb') as attachment:
part = MIMEApplication(attachment.read(), Name='output.txt')
part['Content-Disposition'] = f'attachment; filename="output.txt"'
msg.attach(part)
# 发送邮件
try:
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # 启动TLS加密
server.login(email_user, email_password) # 登录
server.send_message(msg) # 发送邮件
print('邮件发送成功!')
except Exception as e:
print(f'发送邮件失败: {e}')
time.sleep(1) #一秒钟执行一次
以上就是具体的代码了,emmmm,属于开袋即食,有些被我更改的信息也加注中文了,大家修改一下换成自己的信息即可,对了,不要问站主什么“难道要注册两个邮箱吗”这种问题,,,,,愿意的话可以尝试自己发给自己,,,,
python环境是3.11.9,建议使用此版本,其他版本可能会有bug?
使用之前记得先安装一下库文件,emmmm,,,
代码格式有点乱,如果想看运行过程的话可以复制到自己的编辑器里看,这个框架只能设置这么大间距了,我也无能为力,,,,
几行代码的小设计我就直接放在博客里了,emmm,以后如果有机会做一些比较大的项目会更新到github中,,,目前来说,应该要等到站主读研吧,,,,希望有导师收留我,我真的很会打工,QAQ
下面是一些重点步骤的解析,一些不重要的步骤我就跳过了,,,,,
问题一:什么是src
网站中的 src
是 HTML 标签的属性之一,代表 source(源)的缩写,通常用于指定外部资源(如图片、视频、音频、脚本等)的路径。这个属性告诉浏览器从哪里加载相关的文件或资源。——来自chatgpt
问题二:为什么要用src,如何找到src
src这个属性标签可以用来加载其他网页或嵌入内容,常在<iframe>(内嵌框架标签)用于此作用,所以我们可以通过查找src找到我们想要的跳转的网站的地址,网站的src是固定的,不用担心发生变化
在跳转前的网页中我们按下 F12 审计网页js代码,之后按下Ctrl(唱跳rap篮球/小黑子又黑我家哥哥/bushi)+F,查找关键词iframe,肉眼搜索有无出现的src,有的话可以点击看看是不是需要的src,找到需要的src执行
driver.get('大物选课界面的src')
让爬虫跳转到你需要的网页
——感谢班上某位不愿透露姓名的同学分享的知识,伟大的开源精神!!!
问题三:为什么要这么麻烦,既然网页的src不会改变,我直接去gank网站,找到src,让爬虫直接请求不就行了?搞登录干什么,那么麻烦
首先介绍一下Cookie
Cookie 是浏览器和服务器之间通信时使用的一小段数据,通常用于以下用途:
- 身份验证:当用户登录网站后,服务器会发送一个包含用户身份信息的 Cookie,浏览器会存储该 Cookie。在后续的每个请求中,浏览器会自动将 Cookie 发送回服务器,服务器通过 Cookie 确认用户身份。
- 会话管理:Cookie 可以用于保存用户的会话信息,比如登录状态、购物车信息等。
- 个性化设置:例如,保存用户的语言、主题等偏好设置。
- 跟踪和分析:网站可以通过 Cookie 记录用户行为,进行数据分析或广告投放。
Cookie 的结构
Cookie 是一对 键-值
形式的数据。一个典型的 Cookie 可能包含以下内容:
- 名称 (
name
):Cookie 的标识符。 - 值 (
value
):Cookie 的数据内容。 - 域 (
domain
):Cookie 所属的域名,只有在该域名下的请求才能访问 Cookie。 - 路径 (
path
):限定 Cookie 的有效路径,通常是站点的根目录(/
)。 - 有效期 (
expires
):Cookie 的失效时间,超过该时间后,浏览器会删除该 Cookie。 - 安全性 (
secure
):如果设置了该标志,Cookie 只能通过 HTTPS 发送。 - HttpOnly:如果设置了该标志,JavaScript 无法访问 Cookie,只能通过 HTTP 请求发送。
——来自chatgpt
Cookie可以作用于登陆状态,如果我们直接去让爬虫get指定网站的地址,这样对于需要登录的网站是不会成功的,因为爬虫没有获得你的Cookie,他无法通过登录认证这一步,所以我们呢才有上面那么繁琐的操作,先让爬虫自动登录网站,保存对应的Cookie值,维持登录状态,之后再以登录的状态去进行其他操作
以上就是我觉得比较值得分享的内容,大家有兴趣的话可以把代码拿去自己调试,因为我写完之后其实也没怎么用过,emmmm,,,,测试了剩余课程的扫描,这个应该是没问题的,抢课的代码我不想写了,,,就让chatgpt自己搞了,所以错误的可能性很大,大家别随便用抢课的功能,,,,有兴趣的话可以完善一下代码,有新想法可以和我讨论,非常喜欢和别人讨论的说,但是别问“难道我要注册两个邮箱吗?”“什么是SMTP?”这种百度一下就可以知道的回答,emmmm,这样会让我感觉有点不尊重我的劳动成果,站主不会很开心呢
编写不易,如果喜欢可以点赞+分享,赞助的话也是非常支持的hhh,如果要评论的话记得修改昵称,不要随便暴露个人信息哦
Comments | 2 条评论
来捧场了ヾ(≧▽≦*)o
@Link 好欸!