高考分数查询结果自动推送至微信(卷II)

祝各位端午节安康!只要心中无,每天都是

        在上一篇文章高考分数查询结果自动推送至微信(卷Ⅰ)-CSDN博客中谈了思路,今天具体实现。文中将敏感信息已做处理,读者根据自己的实际情况替换。

主要逻辑

- 轮询接口列表

- 提取IP和端口

- 替换查询接口的IP和端口

- 替换验证码接口的IP和端口

- 检测可达性

- 成功查询后保存结果并推送消息,跳出循环

某省去年放出的查询接口主页

主页源码中与查询入口有关的网页源码(部分)

<ul class="cfrk"><li> <a href="http://xxx.xxx.xxx.xxx:81/n_score/index.jsp" class="gkcj-btn">入口一</a></li><li>  <a href="http://xxx.xxx.xxx.xxx:82/n_score/index.jsp" class="gkcj-btn">入口二</a></li><li><a href="http://xxx.xxx.xxx.xxx:81/n_score/index.jsp" class="gkcj-btn">入口三</a></li><li>  <a href="http://xxx.xxx.xxx.xxx:83/n_score/index.jsp" class="gkcj-btn">入口四</a></li><li><a href="http://xxx.xxx.xxx.xxx:81/n_score/index.jsp" class="gkcj-btn">入口五</a> </li>中间省略若干行......<li>  <a href="http://xxx.xxx.xxx.xxx:86/n_score/index.jsp" class="gkcj-btn">入口十六</a></li>
</ul>

我们从上面接口列表中提取IP和端口,检测可达性,自动查询分数,然后推送微信。

完整程序

# coding=utf-8
import requests
from bs4 import BeautifulSoup
import time
import itertools
import json
import random
import ddddocr
import onnxruntime
import schedule# 设置日志级别用于去除ddddocr广告
onnxruntime.set_default_logger_severity(3)# 你的 Server 酱 SCKEY
SERVER_CHAN_SCKEY = 'YOUR_SERVER_CHAN_SCKEY'  # 替换成你的 SCKEYdef imgRecognition(img):"""识别验证码图片内容:param img: 图片文件路径:return: 返回识别结果字符串,如果失败则返回None"""try:ocr = ddddocr.DdddOcr()with open(img, 'rb') as f:img_bytes = f.read()res = ocr.classification(img_bytes)return resexcept Exception as e:print(f"OCR failed: {e}")return Nonedef getVerifyimagepage(session, headers, cookies, captcha_url):"""获取验证码图片并保存为 img.jpg:param session: requests.Session 对象:param headers: 请求头信息:param cookies: 请求时带的Cookie:param captcha_url: 验证码URL:return: 无"""time.sleep(random.random())t = random.uniform(0.0, 1.0)params = {'rnd': t,}try:res = session.get(captcha_url, headers=headers, params=params, cookies=cookies, verify=False)with open('img.jpg', 'wb') as img:img.write(res.content)except Exception as e:print(f"Failed to get image: {e}")def get_Kaptcha(session, headers, cookies, captcha_url):"""获取验证码图片并进行识别:param session: requests.Session 对象:param headers: 请求头信息:param cookies: 请求时带的Cookie:param captcha_url: 验证码URL:return: 返回识别结果字符串,如果失败则返回None"""getVerifyimagepage(session, headers, cookies, captcha_url)return imgRecognition('img.jpg')def get_query_endpoints(session, base_url):"""获取包含查询接口的URL列表:param session: requests.Session 对象:param base_url: 主页URL:return: 返回查询接口URL列表,如果获取失败则返回空列表"""try:response = session.get(base_url)response.raise_for_status()html_content = response.textsoup = BeautifulSoup(html_content, 'html.parser')ul_tag = soup.find('ul', class_='cfrk')if ul_tag:return [a['href'] for a in ul_tag.find_all('a')]else:print("No query endpoints found.")return []except requests.RequestException as e:print(f"Failed to get query endpoints: {e}")return []def extract_ip_port(url):"""从URL中提取IP和端口部分:param url: 完整URL:return: 返回IP和端口字符串,如果提取失败则返回None"""parts = url.split('/')if len(parts) > 2:return parts[2]return Nonedef ping_website(session, full_url):"""检查网站的可达性:param session: requests.Session 对象:param full_url: 完整网站URL:return: 网站可达返回True,否则返回False"""try:response = session.head(full_url)return response.status_code == 200except requests.RequestException as e:print(f"Request failed: {e}")return Falsedef send_to_wechat(message):"""通过 Server 酱发送消息到微信:param message: 要发送的消息文本:return: 返回响应的JSON数据,如果发送失败则返回None"""url = f'https://sc.ftqq.com/{SERVER_CHAN_SCKEY}.send'data = {'text': '查询结果通知','desp': message}try:response = requests.post(url, data=data)response.raise_for_status()return response.json()except requests.RequestException as e:print(f"Failed to send message: {e}")return Nonedef perform_query(session, headers, cookies, query_url, idNumber, ticketNumber, captcha_url):"""执行具体的查询任务:param session: requests.Session 对象:param headers: 请求头信息:param cookies: 请求时带的Cookie:param query_url: 查询接口URL:param idNumber: 身份证号:param ticketNumber: 准考证号:param captcha_url: 验证码URL:return: 返回查询结果的JSON数据,如果查询失败则返回None"""randCode = get_Kaptcha(session, headers, cookies, captcha_url)if randCode is None:print("Failed to get CAPTCHA code.")return Nonequery_full_url = f'{query_url}?idNumber={idNumber}&ticketNumber={ticketNumber}&randCode={randCode}'try:response = session.get(query_full_url, headers=headers, cookies=cookies)response.raise_for_status()return response.json()except requests.RequestException as e:print(f"Query failed: {e}")return Noneterminate = False  # 终止程序标志def job():"""每分钟执行一次的任务,用于进行查询并处理结果:return: 无,但当查询成功并发送消息后,会返回return schedule.CancelJob取消定时任务"""global terminatefor full_url in url_cycle:ip_port = extract_ip_port(full_url)if ip_port:base_query_url = base_query_url_template.format(ip_port)captcha_url = base_captcha_url_template.format(ip_port)if ping_website(session, full_url):print(f"{full_url} is reachable")# 动态设置 headers 中的 Referer 和 Hostheaders["Referer"] = f"http://{ip_port}/n_score/"headers["Host"] = ip_portresult = perform_query(session, headers, cookies, base_query_url, idNumber, ticketNumber, captcha_url)if result:print("Query success:", result)score_text = json.dumps(result, ensure_ascii=False, indent=4)json_path = 'result.json'with open(json_path, 'w') as json_file:json.dump(result, json_file, ensure_ascii=False, indent=4)response = send_to_wechat(score_text)if response and response.get('message') == '':print("信息发送成功")terminate = Truereturn schedule.CancelJob  # 成功后返回取消任务else:print("发送信息失败!")else:print("查询失败")break  # 无论成功还是失败,都跳出循环else:print(f"{full_url} 暂时不能访问!")else:print(f"IP、端口错误 {full_url}")# 初始化配置
session = requests.Session()
headers = {"Accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8","Accept-Encoding": "gzip, deflate","Accept-Language": "zh-CN,zh;q=0.9","Cache-Control": "no-cache","Pragma": "no-cache","Proxy-Connection": "keep-alive","Referer": "http://xxx.xxx.xxx.xxx:81/n_score/",  # 此处应与查询的IP和端口一致"Host": "xxx.xxx.xxx.xxx:81",  # 此处应与查询的IP和端口一致"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"
}
cookies = {"JSESSIONID": "FB32CDA83DF30554A9C01A2BE77260B6",  # 实际使用时请替换"Hm_lvt_9b3b578b0b797c6004bfd68445de9e88": "1687654663"  # 时间戳可以不要
}base_url = "https://xxx.xxx.xxx.xxx/cx/"  # 查询入口主页
idNumber = "your_id_number"  # 替换为实际身份证号
ticketNumber = "your_ticket_number"  # 替换为实际准考证号
base_query_url_template = 'http://{}/n_score/rest/api/queryscore/snquery'  # 查询接口模板
base_captcha_url_template = 'http://{}/n_score/Kaptcha.do'  # 生成验证码接口模板# 获取查询接口列表
href_list = get_query_endpoints(session, base_url)
url_cycle = itertools.cycle(href_list)  # 将查询接口用于循环迭代# 使用 schedule 模块每分钟执行一次 job
schedule.every(1).minutes.do(job)while not terminate:schedule.run_pending()time.sleep(1)print("程序结束")

几点说明:

1、在Server酱中传送json或text

# 假定得到的结果为字典
text = {"querytime": "查询时间:2022-09-22 12:46:47", "totalScore": " 433"}
# 将结果转为json
json_text = json.dumps(text, ensure_ascii=False)
data = {'title': '查询结果通知','desp': json_text
}
headers = {'Content-Type': 'application/json'} # 在头中设置Content-Type 为 json
response = requests.post("https://sctapi.ftqq.com/你自己的key.send?title={}", data=data, headers=headers)#############################################################################################
# 如果结果为table, 可将table转为列表,再转成文格传送
# 提取表格数据
table_data = []
for table in soup.find_all('table'):for row in table.find_all('tr'):cols = row.find_all(['td'])cols = [ele.text.strip() for ele in cols]table_data.append(cols)# 将列表中的元素都转换为字符串类型
str_list = [str(item) for item in table_data]
# 使用 join() 方法将列表转换为文本
text = ', '.join(str_list)data = {'title': '查询结果通知','desp': text
}
response = requests.post("https://sctapi.ftqq.com/你自己的key.send?title={}", data=data)

2、为了确保在查询分数网页和获取验证码时使用同一个会话,我们需要确保所有与网络交互的请求都通过同一个requests.Session。

3、可以将程序部署到阿里云使用FC功能 ,在高考查分前一天触发,让其自动运行直到查询到结果。

       

        此程序是基于我去年成功运行的版本进行修改的。目前,由于今年的查分接口尚未发布,我只能使用去年的接口列表进行开发。因此,当下的接口无法Ping通。基于此限制,我在理论上完成了整个程序,但尚未进行实际测试。

        希望以后高考分数,家长和考生第一时间知晓,自动推送。家长无需费心,考生无需烦恼,无需查询,消息早已送达。此时我无需多言,只愿学子一举夺魁,金榜题名。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/25701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零开始精通Onvif之获取设备信息

&#x1f4a1; 如果想阅读最新的文章&#xff0c;或者有技术问题需要交流和沟通&#xff0c;可搜索并关注微信公众号“希望睿智”。 与设备交互的第一步 发现设备之后&#xff0c;与设备进行交互的第一步&#xff0c;是连接上设备&#xff0c;并获取设备的信息。连接设备&#…

FiRa标准之认证流程

在实现FiRa MAC时需要考虑其兼容性&#xff0c;同时对外部而言&#xff0c;如何证明一个UWB设备是否满足FiRa的规范要求&#xff0c;就需要通过一定的组织对相应的设备进行检测、认证。 为此&#xff0c;FiRa联盟已经建立了国际认证程序&#xff0c;制定了验证待检设备&#x…

React+TS前台项目实战(四)-- layout整体布局搭建

文章目录 前言一、Layout组件代码注释说明二、Content全局组件注释说明三、Header基础布局组件1. Header父级组件注释说明2. NavMenu导航子组件详细说明 四、效果展示总结 前言 本文主要讲Layout整体布局的构建以及全局内容盒子Content组件的使用。还包括了导航栏组件的基本封…

【QT】QT6.3新特性,以及使用技巧

Qt 6.3作为Qt框架的一个重要更新&#xff0c;引入了许多新特性和改进&#xff0c;以提高开发效率和应用程序性能。以下是一些使用Qt 6.3的技巧和最佳实践&#xff1a; 利用新模块和特性&#xff1a; 了解并利用Qt 6.3中新增的模块和特性&#xff0c;例如Qt Quick 3D、Qt PDF等&…

未来几年,同样的性能,推理功耗降低为现在的几万分之一,有可能吗

未来几年,同样的性能,推理功耗降低为现在的几万分之一,有可能吗 一.数据二.抓取LLM排行榜,相同的MMLU精度,模型参数量缩减倍数三.其它 有人说未来几年,推理功耗能降低为现在的几万分之一,好奇怎么能做到呢 一.数据 二.抓取LLM排行榜,相同的MMLU精度,模型参数量缩减倍数 import…

spool 管道 小文件 mknod

Spool File In SQL*PLUS in Multiple Small Files ? (Doc ID 2152654.1)​编辑To Bottom In this Document Goal Solution APPLIES TO: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 12.1.0.2 [Release 10.2 to 12.1] Oracle Database Cloud Schema Service…

从零开始搭建Electron项目之运行例程

最好的学习方式就是&#xff1a;给一段能够运行的代码示例。 本文给出了例程资源&#xff0c;以及运行的步骤。 在国内开发electron有一点特别不好&#xff0c;就是如果不爬梯子&#xff0c;下载依赖容易出错。 一、例程资源 到如下路径下载例程到本地。 GitCode - 全球开发者…

32、matlab:基于模板匹配的车牌识别

1、准备工作 1&#xff09;准备材料 车牌字符模板和测试的实验车牌 2&#xff09;车牌字符模板 数字、字母和省份缩写 3&#xff09;测试车牌 四张测试车牌 2、车牌识别实现(已将其嵌入matlab) 1&#xff09;打开APP 找到APP 找到我的APP双击点开 2)界面介绍 包括&am…

C语言考试内容

C语言考试通常会涵盖以下几个主要方面&#xff1a; 1. **基本概念**&#xff1a; - C语言的历史和特点 - C语言的编译过程 - 程序的基本结构&#xff08;包括预处理指令、主函数main()、函数定义等&#xff09; 2. **数据类型和运算符**&#xff1a; - 基本数据类…

一起学习Linux内核模块的知识,为编写复杂的设备驱动做好准备

一、Linux内核模块简介 Linux内核的整体架构非常庞大&#xff0c;包含的组件非常多&#xff0c;如果把所有的功能都编译到内核&#xff0c;有导致生成的内核映像越来越大&#xff0c;同时如果我们要修改现有内核的功能&#xff0c;需要重编内核&#xff0c;效率很低。 有没有…

【网络安全的神秘世界】web应用程序安全与风险

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 第一章&#xff1a;web应用程序安全与风险 web攻击基础知识 1、什么是web应用攻击 web攻击的本质&#xff0c;就是通过http协议篡改应用程序&#xff0…

c#自定义ORM框架-实体类扩展属性

步骤一、建立扩展属性类 实体类扩展属性要继承Attribute基类完成 步骤二、创建实体类并引用扩展实体类属性 Attributes属性定义&#xff0c;主要标明表名和主键名字 /// <summary> /// 表名 /// </summary> [AttributeUsage(AttributeTargets.Class)] [System.S…

蓝牙安全入门——两道CTF题目复现

文章目录 蓝牙安全入门题目 low_energy_crypto获取私钥解密 题目 蓝牙钥匙的春天配对过程配对方法密钥分发数据加密安全漏洞和保护实际应用实际应用 蓝牙安全入门 &#x1f680;&#x1f680;最近一直对车联网比较感兴趣&#xff0c;但是面试官说我有些技术栈缺失&#xff0c;所…

==Redis淘汰策略(内存满了触发)==

好的&#xff0c;面试官。这个问题我需要从三个方面来回答。第一个方面&#xff1a; 当 Redis 使用的内存达到 maxmemory 参数配置的阈值的时候&#xff0c;Redis 就会根据配置的内存淘汰策略。 把访问频率不高的 key 从内存中移除。maxmemory 默认情况是当前服务器的最大内存…

html5实现个人网站源码

文章目录 1.设计来源1.1 网站首页页面1.2 个人工具页面1.3 个人日志页面1.4 个人相册页面1.5 给我留言页面 2.效果和源码2.1 动态效果2.2 目录结构 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/139564407 ht…

Golang | Leetcode Golang题解之第141题环形链表

题目&#xff1a; 题解&#xff1a; func hasCycle(head *ListNode) bool {if head nil || head.Next nil {return false}slow, fast : head, head.Nextfor fast ! slow {if fast nil || fast.Next nil {return false}slow slow.Nextfast fast.Next.Next}return true }

unity到小游戏instantGame(流程演示,非内容制作 亲测可用)

unity到小游戏instantGame&#xff08;开发流程演示&#xff0c;非内容制作 亲测可用&#xff09; 写在前面直接 写在前面 instantGame 后妈级教学&#xff0c;主打一个填自己的坑&#xff0c;有问题下方评论交流 根据此教程使用后的一点心得记录和可能出现的问题补充&#xf…

vue面试题四

一、请解释v-show和v-if指令的区别&#xff1f; v-show 和 v-if 是 Vue.js 中用于控制元素显示与隐藏的两个常用指令&#xff0c;但它们的工作方式和性能表现有所不同。以下是它们之间的主要区别&#xff1a; 1. 工作原理 v-if&#xff1a; v-if 是“真实”的条件渲染&#x…

SpringBoot与Mybatis-plus实战

随着互联网技术的快速发展&#xff0c;企业级应用对开发效率和性能的要求越来越高。Spring Boot 作为一款快速开发框架&#xff0c;以其简洁、快速、配置方便等优点&#xff0c;得到了广泛的应用。而 MyBatis-Plus 作为 MyBatis 的增强工具&#xff0c;在简化开发、提高效率方面…

在 .NET Core 中构建工作服务和调度运行

介绍 .NET Core 中的工作服务已成为构建持续运行并执行各种任务的后台服务的强大机制。本文提供了有关创建工作服务的分步指南&#xff0c;深入研究了其演变过程&#xff0c;并阐明了代码片段以及执行过程。 工人服务的演变 工作服务是 .NET Core 旅程的延续&#xff0c;它源…