Skip to content

Commit

Permalink
scf version commit
Browse files Browse the repository at this point in the history
  • Loading branch information
6r6 authored and d8b committed Feb 11, 2019
1 parent 5e691dd commit d2aa65f
Show file tree
Hide file tree
Showing 20 changed files with 5,231 additions and 2 deletions.
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,36 @@
# yz
点点鼠标快速上线一个研招网成绩查询的接口
### 介绍一下?
无需拥有服务器,点点鼠标就能上线一个研招网成绩查询的接口。

实质是通过腾讯云无服务器云函数,制作一个REST风格的接口,通过GET请求即可**查询研究生入学考试的初试成绩**

### 特性
- [x] 自动识别验证码
- [x] 无需修改我的💩脚本
- [x] 支持Server酱

### 预览一下?

> 作者不会收集任何人的信息。代码是开源的,最好自行部署较为放心。
请求方式:GET

`
https://service-5ur64h8n-1251079053.ap-shanghai.apigateway.myqcloud.com/release/yanzhao?xm=姓名&id=身份证号&kh=准考证号
`

返回样例:JSON

`{"Code": 101, "Msg": "Score not released yet", "Request_id": "e43f5c16-2dde-11e9-93a2-5254005d5fdb"}`

### 如何部署?
你需要准备注册[腾讯云](https://console.cloud.tencent.com/scf)[腾讯优图](https://open.youtu.qq.com/#/open)

- 下载最新的release压缩包
- [腾讯云SCF](https://console.cloud.tencent.com/scf)后台新建 > 空白函数 ,函数名请随意,运行环境选择Python36
- 执行方法填入`index.main_handler`
- 提交方法选择本地上传ZIP包,上传刚下载的ZIP包
- 环境变量请配置`app_id``secret_id``secret_key`,请在腾讯优图开放平台获取这三个值
- 保存
- 触发方式 > API网关触发 > 默认参数保存,获得一个公网的查询地址

---
159 changes: 159 additions & 0 deletions index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 6r6

import os
import time
import random
import hmac
import hashlib
import binascii
import base64
import json
import logging
import re
import requests

# (*)腾讯优图配置
app_id = ''
secret_id = ''
secret_key = ''

# Server酱V3配置
sckey = ''

logger = logging.getLogger()

class Youtu(object):

def __init__(self, app_id, secret_id, secret_key, qq=10000):
self.app_id = app_id
self.secret_id = secret_id
self.secret_key = secret_key
self.qq = qq

def cal_sig(self):
timestamp = int(time.time())
expired = str(timestamp + 2592000)
rdm = str(random.randint(0, 999999999))
plain_text = 'a={appid}&k={secret_id}&e={expired}&t={timestamp}&r={rdm}&u={qq}&f='
plain_text = plain_text.format(appid=self.app_id,
secret_id=self.secret_id,
timestamp=timestamp,
rdm=rdm, qq=self.qq,
expired=expired)
bin = hmac.new(self.secret_key.encode(), plain_text.encode(), hashlib.sha1).hexdigest()
s = binascii.unhexlify(bin)
s = s + plain_text.encode('ascii')
signature = base64.b64encode(s).rstrip().decode()
return signature

def get_text(self, image_raw):
signature = self.cal_sig()
headers = {'Host': 'api.youtu.qq.com', 'Content-Type': 'text/json', 'Authorization': signature}
data = {'app_id': self.app_id, 'image': ''}
data['image'] = base64.b64encode(image_raw).rstrip().decode('utf-8')
resp = requests.post('https://api.youtu.qq.com/youtu/ocrapi/generalocr',
data=json.dumps(data),
headers=headers)
if 'items' in resp.text:
return resp.content.decode('utf-8')
else:
return '0'

class SocreQuery:

def __init__(self, xm, id, ksbh):
self.xm = xm
self.id = id
self.ksbh = ksbh
self.cookies = requests.cookies.RequestsCookieJar()
self.headers = {
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate, br',
'Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8',
'Cache-Control':'max-age=0',
'Content-Type':'application/x-www-form-urlencoded',
'DNT':'1',
'Host':'yz.chsi.com.cn',
'Origin':'https://yz.chsi.com.cn',
'Referer':'https://yz.chsi.com.cn/apply/cjcx/',
'Upgrade-Insecure-Requests':'1',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.37 (KHTML, like Gecko) Chrome/70.0.3537.110 Safari/537.37'
}

def get_cookies(self):
base_url = 'https://yz.chsi.com.cn/apply/cjcx'
session = requests.session()
base_resp = session.get(base_url, headers=self.headers)
self.cookies = base_resp.cookies

def get_checkcode(self):
pic_url = 'https://yz.chsi.com.cn/apply/cjcx/image.do'
resp = requests.get(pic_url, headers=self.headers, cookies=self.cookies).content
ocr = Youtu(app_id, secret_id, secret_key)
try:
resp = ocr.get_text(resp)
resp = eval(resp)
return resp['items'][0]['itemstring']
except:
return '0'

def get_score_page(self):
self.get_cookies()
checkcode = self.get_checkcode().replace(' ','')
post_url = 'https://yz.chsi.com.cn/apply/cjcx/cjcx.do'
data = {
'xm': self.xm,
'zjhm':self.id,
'ksbh':self.ksbh,
'bkdwdm':None,
'checkcode':checkcode
}
post_resp = requests.post(post_url,data=data, headers=self.headers).text
return post_resp

@staticmethod
def get_mid_text(w1, w2, text):
pat = re.compile(w1+'(.*?)'+w2,re.S)
result_dict = pat.findall(text)
return result_dict

@staticmethod
def notice(key, title, desp):
url = 'https://sc.ftqq.com/{}.send'.format(key)
payload = {'text':title,'desp':desp}
r = requests.get(url,params=payload)
return r.text


def main_handler(event, context):
data = {
"isBase64Encoded": False,
"statusCode": 200,
"headers": {"Content-Type":"application/json"},
"body": ""}
try:
rid = context["request_id"]
xm = event['queryString']['xm']
id = event['queryString']['id']
kh = event['queryString']['kh']
query = SocreQuery(xm,id,kh)
page = query.get_score_page()
if '无查询结果' in page:
logging.info('成绩还没出')
data['body'] = json.dumps({"Code":101,"Msg":"Score not released yet","Request_id":rid})
return data
elif '总分' in page:
score_content = query.get_mid_text('<tbody>','</tbody>',page)[0]
logging.info('成绩查询成功')
data['headers']['Content-Type'] = 'text/html'
data['body'] = score_content
#query.notice(sckey,'成绩出了',page)
return data
else:
data['body'] = json.dumps({"Code":103,"Msg":"Unexpected page contents","Request_id":rid})
return data
except:
data['body'] = json.dumps({"Code":102,"Msg":"Unexpected url parameters","Request_id":rid})
return data
131 changes: 131 additions & 0 deletions requests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-

# __
# /__) _ _ _ _ _/ _
# / ( (- (/ (/ (- _) / _)
# /

"""
Requests HTTP Library
~~~~~~~~~~~~~~~~~~~~~
Requests is an HTTP library, written in Python, for human beings. Basic GET
usage:
>>> import requests
>>> r = requests.get('https://www.python.org')
>>> r.status_code
200
>>> 'Python is a programming language' in r.content
True
... or POST:
>>> payload = dict(key1='value1', key2='value2')
>>> r = requests.post('https://httpbin.org/post', data=payload)
>>> print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
The other HTTP methods are supported - see `requests.api`. Full documentation
is at <http://python-requests.org>.
:copyright: (c) 2017 by Kenneth Reitz.
:license: Apache 2.0, see LICENSE for more details.
"""

import urllib3
import chardet
import warnings
from .exceptions import RequestsDependencyWarning


def check_compatibility(urllib3_version, chardet_version):
urllib3_version = urllib3_version.split('.')
assert urllib3_version != ['dev'] # Verify urllib3 isn't installed from git.

# Sometimes, urllib3 only reports its version as 16.1.
if len(urllib3_version) == 2:
urllib3_version.append('0')

# Check urllib3 for compatibility.
major, minor, patch = urllib3_version # noqa: F811
major, minor, patch = int(major), int(minor), int(patch)
# urllib3 >= 1.21.1, <= 1.24
assert major == 1
assert minor >= 21
assert minor <= 24

# Check chardet for compatibility.
major, minor, patch = chardet_version.split('.')[:3]
major, minor, patch = int(major), int(minor), int(patch)
# chardet >= 3.0.2, < 3.1.0
assert major == 3
assert minor < 1
assert patch >= 2


def _check_cryptography(cryptography_version):
# cryptography < 1.3.4
try:
cryptography_version = list(map(int, cryptography_version.split('.')))
except ValueError:
return

if cryptography_version < [1, 3, 4]:
warning = 'Old version of cryptography ({}) may cause slowdown.'.format(cryptography_version)
warnings.warn(warning, RequestsDependencyWarning)

# Check imported dependencies for compatibility.
try:
check_compatibility(urllib3.__version__, chardet.__version__)
except (AssertionError, ValueError):
warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "
"version!".format(urllib3.__version__, chardet.__version__),
RequestsDependencyWarning)

# Attempt to enable urllib3's SNI support, if possible
try:
from urllib3.contrib import pyopenssl
pyopenssl.inject_into_urllib3()

# Check cryptography version
from cryptography import __version__ as cryptography_version
_check_cryptography(cryptography_version)
except ImportError:
pass

# urllib3's DependencyWarnings should be silenced.
from urllib3.exceptions import DependencyWarning
warnings.simplefilter('ignore', DependencyWarning)

from .__version__ import __title__, __description__, __url__, __version__
from .__version__ import __build__, __author__, __author_email__, __license__
from .__version__ import __copyright__, __cake__

from . import utils
from . import packages
from .models import Request, Response, PreparedRequest
from .api import request, get, head, post, patch, put, delete, options
from .sessions import session, Session
from .status_codes import codes
from .exceptions import (
RequestException, Timeout, URLRequired,
TooManyRedirects, HTTPError, ConnectionError,
FileModeWarning, ConnectTimeout, ReadTimeout
)

# Set default logging handler to avoid "No handler found" warnings.
import logging
from logging import NullHandler

logging.getLogger(__name__).addHandler(NullHandler())

# FileModeWarnings go off per the default.
warnings.simplefilter('default', FileModeWarning, append=True)
14 changes: 14 additions & 0 deletions requests/__version__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# .-. .-. .-. . . .-. .-. .-. .-.
# |( |- |.| | | |- `-. | `-.
# ' ' `-' `-`.`-' `-' `-' ' `-'

__title__ = 'requests'
__description__ = 'Python HTTP for Humans.'
__url__ = 'http://python-requests.org'
__version__ = '2.21.0'
__build__ = 0x022100
__author__ = 'Kenneth Reitz'
__author_email__ = 'me@kennethreitz.org'
__license__ = 'Apache 2.0'
__copyright__ = 'Copyright 2018 Kenneth Reitz'
__cake__ = u'\u2728 \U0001f370 \u2728'
42 changes: 42 additions & 0 deletions requests/_internal_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-

"""
requests._internal_utils
~~~~~~~~~~~~~~
Provides utility functions that are consumed internally by Requests
which depend on extremely few external helpers (such as compat)
"""

from .compat import is_py2, builtin_str, str


def to_native_string(string, encoding='ascii'):
"""Given a string object, regardless of type, returns a representation of
that string in the native string type, encoding and decoding where
necessary. This assumes ASCII unless told otherwise.
"""
if isinstance(string, builtin_str):
out = string
else:
if is_py2:
out = string.encode(encoding)
else:
out = string.decode(encoding)

return out


def unicode_is_ascii(u_string):
"""Determine if unicode string only contains ASCII characters.
:param str u_string: unicode string to check. Must be unicode
and not Python 2 `str`.
:rtype: bool
"""
assert isinstance(u_string, str)
try:
u_string.encode('ascii')
return True
except UnicodeEncodeError:
return False
Loading

0 comments on commit d2aa65f

Please sign in to comment.