def display(a, data): """ 将统计数据生成markdown表格,print到屏幕 """ display = "|username|count|registertime|\n|--|--|--|\n" for username, count in data: quoted_username = quote(bytes(username, encoding='utf-8')) regtime = getuserregistertime(a, quoted_username) display += "|[{username}](/dispuser.asp?name={quoted_username})|{count}|`{regtime}`|\n".format( **locals()) print(display)
def main(): a = EasyLogin(cookie=COOKIE) if len(sys.argv) < 3: print("Usage: python3 {filename} boardid postid".format( filename=sys.argv[0])) return _data = getpostuser_frequencydict(a, sys.argv[1], sys.argv[2]) data = sorted(_data.items(), key=lambda i: i[1], reverse=True) print("# 帖数统计(截至目前{count}帖)".format(count=sum([j for i, j in data]))) print("## 按照发帖频率排序") display(a, data) data = sorted( _data.items(), key=lambda i: string2timestamp( getuserregistertime(a, quote(bytes(i[0], encoding='utf-8'))))) print("## 按注册时间排序") display(a, data)
def upload_by_collection_detailed(token, collection_code, filename, filesize, data): """ 详细的真实匿名上传过程 通过文件收集任务上传 需要先从上传页面中得到token collection_code即为配置文件中的upload_link 上传过程类似upload. 但多了一步collection_submit的操作 返回上传文件得到的服务器端的文件id 如果失败,抛出Exception """ global a x = a.post(DOMAIN + "/apps/processes/presign_upload", ("""{"code":"%s","file_name":"%s","file_size":%d}"""%(collection_code, filename, filesize)).encode('utf-8'), #在格式化字符串之后再进行编码 headers={"requesttoken":token,"X-Requested-With": "XMLHttpRequest", "Content-Type":"text/plain;charset=UTF-8"} ) result=x.json() if "success" not in result or result["success"]!=True: print("[FAILED] presign_upload") print(result) raise Exception("presign_upload failed") upload_url=result["upload_url"] x=a.post(upload_url, data, headers={"requesttoken": token,"X-File-Name": quote(filename), "Content-Type":"text/plain;charset=UTF-8"},dont_change_cookie=True) #header中的还是需要quote的 result=x.json() if "success" not in result or result["success"]!=True: print("[FAILED] upload") print(result) raise Exception("upload failed") fileid = result["new_file"]["id"] x = a.post(DOMAIN+"/apps/processes/collection_submit", """{"user_name":"x","code":"%s","file_ids":[%s]}"""%(collection_code,fileid), headers={"requesttoken":token, "X-Requested-With": "XMLHttpRequest", "Content-Type":"text/plain;charset=UTF-8"}, dont_change_cookie=True ) result=x.json() if "success" not in result or result["success"]!=True: print("[FAILED] collection_submit") print(result) raise Exception("collection_submit failed") return fileid
def upload(token, filename, data, filesize=None, folder_id=0, retry=5, fencrypt=None, _a=None): """ 上传文件,与亿方云基本一致,但需要引入dont_change_cookie token:islogin()返回的token filename: 存储的文件名 data:文件二进制数据, 也可以为block generator filesize: 文件总大小,如果data为block generator,必须填入 folder_id: 上传的目的文件夹id fencrypt: { #4个元素的dict fencrypt_filename(filename): 对文件名进行加密的函数,返回加密后的文件名ASCII 建议base64 fencrypt_data(data_generator): 对文件内容进行加密的函数,输入文件内容的generator,返回密文的generator;即使输入的data不是生成器也会被转为list传入 fencrypt_addlen: int 由于文件加密增加的字节数,一般就是iv的长度 fencrypt_callback(filename_plaintext, filename_ciphertext, folder_id, fileid): 上传成功后进行回调,便于存储加密信息,传入原文件名、加密文件名、上传目标目录id、上传得到的文件ID, 返回None } 返回服务器端的文件id """ if fencrypt is not None: fencrypt_filename = fencrypt.get("fencrypt_filename",None) fencrypt_data = fencrypt.get("fencrypt_data",None) fencrypt_addlen = fencrypt.get("fencrypt_addlen",0) fencrypt_callback = fencrypt.get("fencrypt_callback",None) else: fencrypt_filename = fencrypt_data = fencrypt_callback = None fencrypt_addlen = 0 if _a is None: global a else: a = _a print("upload: filename={filename}, folder_id={folder_id}".format(**locals())) _filename = safefilename(getfilename(filename)) if fencrypt_filename is not None: # for encrypting filename filename_plaintext = _filename _filename = fencrypt_filename(_filename) filename_ciphertext = _filename else: filename_plaintext = filename_ciphertext = _filename try: filename=quote(_filename) except: print("[ERROR] filename encoding is not utf-8! \nYou may need to convert filename encoding to utf-8 before we can continue. Have a look at https://py3.io/code/fixgbknames.py") raise if filesize is None: filesize = len(data) filesize += fencrypt_addlen x=a.post(DOMAIN+"/apps/files/presign_upload", """{"folder_id":%s,"file_size":%d}"""%(str(folder_id),filesize), headers={"requesttoken": token, "X-Requested-With": "XMLHttpRequest", "Content-Type":"text/plain;charset=UTF-8"}) try: result=x.json() except json.JSONDecodeError: print(x, x.text) if retry>0: return upload(token, filename, data, filesize, folder_id, retry = retry-1, fencrypt=fencrypt) else: raise if result["success"]!=True: print(result) return False upload_url=result["upload_url"] if fencrypt_data is not None: # add support for data encryption is_stream = all([ hasattr(data, '__iter__'), not isinstance(data, (str, bytes, list, tuple, dict)) ]) if not is_stream: data_to_encrypt = [data] # change data to a list for calling fencrypt_data else: data_to_encrypt = data data = fencrypt_data(data_to_encrypt) x=a.post(upload_url, data, headers={"requesttoken": token,"X-File-Name": filename},dont_change_cookie=True) result=x.json() if "success" not in result or result["success"]!=True: print(result) return False ret = result["new_file"]["typed_id"] if fencrypt_callback is not None: try: fencrypt_callback(filename_plaintext, filename_ciphertext, folder_id, ret) except: traceback.print_exc() pass # exception happened in callback should not have no influence return ret
def search_courses(name, schoolid=school): name = quote(name) return get("/courses/?q={name}&limit_type=school&limit_id={schoolid}&per_page=1000&page=1".format(**locals()))["data"]["courses"]
def search_teacher(name, schoolid=school): name = quote(name) return get("/teachers/?q={name}&limit_type=school&limit_id={schoolid}&per_page=1000&page=1".format(**locals()))["data"]['teachers']