项目概况
- 在线地址:https://g.565455.xyz/youdian.html
- 设计想法:好朋友学校最近在使用优点英语练习听力,查看听力答案需要一个密码,而有一回老师并没有给密码,于是手动找到密码便是极为迫切的事。鉴于听力这种东西时效性很强,一般老师都会给答案的密码,故本项目使用率并不高
- 代码实现:使用后端Python服务器搭配前端html实现
代码设计
实例分析
首先我们先来看一个案例
https://h5.clewm.net/?url=h.qr61.cn%2FobzgrD%2Fqt4MEes&hasredirect=1
滑到底部是密码获取的二维码,扫出来是https://h5.clewm.net/?url=h.qr61.cn%2FobzgrD%2FqLuLhcP&hasredirect=1
进入后可以发现,我们虽然无法找到密码的获取api,但是可以通过标题取巧,在qrcodeRouteNew
中传输标题([‘data’][‘qrcode_msg’][‘qrcode_record’][‘list_name’])后面都会带有密码,这使我们获取密码的想法成为可能
分析请求我发现这个api是通过POST
进行请求的,其携带的参数如下
很明显,最重要的参数是qrcode_route
,而它就出自于第二个二维码扫描出来的URL中携带的参数
?url=h.qr61.cn/obzgrD/qLuLhcP&hasredirect=1
程序后端
我采用了Python作为服务器后端
需要导入的库有requests
, json
, re
还有一部分服务器所需库
1
2
3
4
import requests
import re
import json
...
接下来模拟POST
请求,请求头中即使没有浏览器标识,也可以正常获得数据,故这里不添加
1
2
3
4
5
6
7
8
9
10
11
# SERVER GET ROUTE BY PARAMETER
...
url = "https://nc.cli.im/qrcoderoute/qrcodeRouteNew"
data = {
"qrcode_route": route,
"password": "",
"render_default_fields": "0",
"render_edit_btn": "1"
}
response = requests.post(url, data=data)
response.encoding = "utf-8"
最后将获取到的数据转为json类型并获取键值,通过正则表达式匹配密码最后返回
1
2
3
4
5
6
res_js = json.loads(response.text)
mmline = res_js['data']['qrcode_msg']['qrcode_record']['list_name']
mm = re.findall(r"(密码:(.*?))", mmline)[0]
self.reply["mima"] = mm
# self.reply is defined at the top of the py file
...
程序前端
前端没什么好说的,引入API并对用户的字符串预处理即可
1
2
3
4
5
6
7
8
9
<body>
<h1>提取优点英语听力密码</h1>
<p>使用教程:请在优点英语听力需要输入密码的页面(你需要扫描两次二维码)点击右上角三个点复制链接到下方输入框</p>
<input type="text" placeholder="请输入链接" id="i" style="width: 250px;">
<button onclick="get_title()" id="get_title">获取</button>
<p id="tip"></p>
<p>Designed By FANCC.</p>
<p>接口失效请联系fancc@565455.xyz</p>
</body>
至于那个button的onclick事件为什么叫get_title,因为这部分脚本直接拷贝自另一个项目,懒得改了,凑合看吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<script type="text/javascript">
// 跨域加载api
let api_response;
function load_script(url, f){
setTimeout(function(){
let s = document.createElement("script");
s.src = url;
document.querySelector("body").appendChild(s);
s.onload = function(){
s.remove();
f();
};
}, 0);
}
//
let l = "";
let mm = "";
let r = /=(.*?)&/;
// 加载
function get_title(){
tip("加载中请稍后……请勿多次请求造成带宽浪费>_<");
l = document.querySelector("#i").value;
if (l === "") {
tip("错误:您还未输入链接");
return;
}
l = decodeURIComponent(l);
l = l.match(r);
if (!l){
tip("错误:链接格式错误");
return;
}
l = l[1];
load_script(
url = "https://api.565455.xyz/api/youdian/?route=" + l,
f = function(){
if (!api_response['code']){
// 成功
console.log(api_response['mima']);
vdlink = api_response['mima']
tip("密码是:"+api_response['mima']);
}else{
// 失败
console.log(api_response['msg']);
tip("失败:"+api_response['msg'])
}
}
);
}
// 提示
function tip(text){
document.querySelector("#tip").innerText = text;
}
</script>
后记
如果你需要完整代码,请去Github查看
- 前端代码https://github.com/Fancc666/Fancc666.github.io/blob/master/youdian.html
- 后端代码https://github.com/Fancc666/565455/blob/main/api/youdian.py
这个项目是我35分钟写出来的,对于初学者来说是很好的练手项目,虽然我已经把程序上线了,但是大家不妨也跟着来试一试
我之前搭建的博客数据全都没了,真是个悲伤的故事,我会陆续把我写过的几个有趣的项目的讲解放到这里的博客上,敬请期待
朋友们也可以在下方的Github Issue中反馈和留言,期待你的评论!