198 lines
6.5 KiB
Python
198 lines
6.5 KiB
Python
#!/usr/bin/env python
|
||
# -*- encoding: utf-8 -*-
|
||
'''
|
||
@Description:Server.py
|
||
@Date :2023/02/25 17:03:32
|
||
@Author :JohnserfSeed
|
||
@version :0.0.1
|
||
@License :MIT License
|
||
@Github :https://github.com/johnserf-seed
|
||
@Mail :johnserf-seed@foxmail.com
|
||
-------------------------------------------------
|
||
Change Log :
|
||
2023/02/25 17:03:32 - Create Flask Server XB Gen
|
||
2023/08/03 16:48:34 - Fix ttwid
|
||
-------------------------------------------------
|
||
'''
|
||
|
||
import time
|
||
import execjs
|
||
# import sqlite3
|
||
import requests
|
||
|
||
from flask import Flask
|
||
from flask import request
|
||
from flask import jsonify
|
||
# from flask import make_response
|
||
# from flask import render_template
|
||
|
||
from urllib.parse import urlencode
|
||
from urllib.parse import unquote
|
||
from urllib.parse import parse_qsl
|
||
|
||
class Server:
|
||
def __init__(self) -> None:
|
||
# 工厂模式
|
||
self.app = Flask(__name__)
|
||
|
||
self.app.config.from_mapping(
|
||
SECRET_KEY='douyin-xbogus'
|
||
)
|
||
|
||
self.app.config['JSON_AS_ASCII'] = False
|
||
|
||
with open("x-bogus.js", "r", encoding="utf-8") as fp:
|
||
self.xbogust_func = execjs.compile(fp.read())
|
||
|
||
with open("x-tt-params.js", "r", encoding="utf-8") as fp:
|
||
self.xttm_func = execjs.compile(fp.read())
|
||
|
||
self.ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
|
||
|
||
# 获取xg参数
|
||
def getXG(self, url_path, params):
|
||
xbogus = self.xbogust_func.call("getXB", url_path)
|
||
# 字典中添加xg
|
||
params["X-Bogus"] = xbogus
|
||
tips = {
|
||
"status_code": "200",
|
||
"time": {
|
||
"strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||
"timestamp": int(round(time.time() * 1000))
|
||
},
|
||
"result": [{
|
||
"params": params,
|
||
"paramsencode": urlencode(params, safe="="),
|
||
"user-agent": self.ua,
|
||
"X-Bogus": {
|
||
0: xbogus,
|
||
1: "X-Bogus=%s" % xbogus
|
||
}
|
||
}]
|
||
}
|
||
print(tips)
|
||
return jsonify(tips)
|
||
|
||
# 生成x-tt-params
|
||
def getxttparams(self, url_path):
|
||
xttp = self.xttm_func.call("getXTTP", url_path)
|
||
tips = {
|
||
"status_code": "200",
|
||
"time": {
|
||
"strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||
"timestamp": int(round(time.time() * 1000))
|
||
},
|
||
"result": [{
|
||
"headers": {
|
||
"user-agent": self.ua,
|
||
"x-tt-params": xttp
|
||
}
|
||
}]
|
||
}
|
||
print(tips)
|
||
return jsonify(tips)
|
||
|
||
def gen_ttwid(self) -> str:
|
||
"""生成请求必带的ttwid
|
||
param :None
|
||
return:ttwid
|
||
"""
|
||
url = 'https://ttwid.bytedance.com/ttwid/union/register/'
|
||
data = '{"region":"cn","aid":1768,"needFid":false,"service":"www.ixigua.com","migrate_info":{"ticket":"","source":"node"},"cbUrlProtocol":"https","union":true}'
|
||
response = requests.request("POST", url, data=data)
|
||
# j = ttwid k = 1%7CfPx9ZM.....
|
||
for j, k in response.cookies.items():
|
||
tips = {
|
||
"status_code": "200",
|
||
"time": {
|
||
"strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||
"timestamp": int(round(time.time() * 1000))
|
||
},
|
||
"result": [{
|
||
"headers": {
|
||
"user-agent": self.ua,
|
||
"cookie": "ttwid=%s;" % k
|
||
}
|
||
}]
|
||
}
|
||
print(tips)
|
||
return jsonify(tips)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
server = Server()
|
||
# 首页
|
||
@server.app.route('/', methods=['GET', 'POST'])
|
||
def index():
|
||
tips = {
|
||
"status_code": "-1",
|
||
"time": {
|
||
"strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||
"timestamp": int(round(time.time() * 1000))
|
||
},
|
||
"path": {
|
||
0: "/xg/path/?url=",
|
||
2: "/x-tt-params/path"
|
||
}
|
||
}
|
||
print(tips)
|
||
return jsonify(tips)
|
||
|
||
# xg参数
|
||
@server.app.route('/xg/path/', methods=['GET', 'POST'])
|
||
def xgpath():
|
||
path = request.args.get('url', '')
|
||
# 如果str路径为空
|
||
if not path:
|
||
tips = {
|
||
"status_code": "-3",
|
||
"time": {
|
||
"strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||
"timestamp": int(round(time.time() * 1000))
|
||
},
|
||
"message": {
|
||
0: "The key url cannot be empty and the need for url encoding, The '&' sign needs to be escaped to '%26', Use urllib.parse.quote(url) to escape. Example:/xg/path/?url=aid=6383%26sec_user_id=xxx%26max_cursor=0%26count=10",
|
||
1: "url参数不能为空,且需要注意传入值中的“&”需要转义成“%26”,使用urllib.parse.quote(url)转义. 例如:/xg/path/?url=aid=6383%26sec_user_id=xxx%26max_cursor=0%26count=10"
|
||
}
|
||
}
|
||
print(tips)
|
||
return jsonify(tips)
|
||
else:
|
||
# url转字典
|
||
params = dict(parse_qsl(path))
|
||
# 字典转url
|
||
url_path = urlencode(params, safe="=")
|
||
return server.getXG(url_path, params)
|
||
|
||
# x-tt-params参数
|
||
@server.app.route('/x-tt-params/path', methods=['GET', 'POST'])
|
||
def xttppath():
|
||
try:
|
||
path = request.json
|
||
except:
|
||
pass
|
||
if not path:
|
||
tips = {
|
||
"status_code": "-5",
|
||
"time": {
|
||
"strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||
"timestamp": int(round(time.time() * 1000))
|
||
},
|
||
"message": {
|
||
0: "Body uses raw JSON format to pass dictionary parameters, such as %s" % '{"aid": 1988,"app_name": "tiktok_web","channel": "tiktok_web".........}',
|
||
1: "body中使用raw json格式传递字典参数,如%s" % '{"aid": 1988,"app_name": "tiktok_web","channel": "tiktok_web".........}'
|
||
}
|
||
}
|
||
print(tips)
|
||
return jsonify(tips)
|
||
else:
|
||
return server.getxttparams(path)
|
||
|
||
# ttwid
|
||
@server.app.route('/xg/ttwid', methods=['GET', 'POST'])
|
||
def ttwid():
|
||
return server.gen_ttwid()
|
||
|
||
|
||
server.app.run(host='0.0.0.0',port='8889')
|