From bc3c425d137f6f8205cb1b8308824ec2601cbd5f Mon Sep 17 00:00:00 2001 From: ihmily <114978440+ihmily@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:12:41 +0800 Subject: [PATCH] feat: add haixiu live record --- demo.py | 4 + douyinliverecorder/javascript/haixiu.js | 539 ++++++++++++++++++++++++ douyinliverecorder/spider.py | 44 ++ main.py | 26 +- 4 files changed, 603 insertions(+), 10 deletions(-) create mode 100644 douyinliverecorder/javascript/haixiu.js diff --git a/demo.py b/demo.py index 01229bd..bbf20d6 100644 --- a/demo.py +++ b/demo.py @@ -139,6 +139,10 @@ LIVE_STREAM_CONFIG = { "chzzk": { "url": "https://chzzk.naver.com/live/458f6ec20b034f49e0fc6d03921646d2", "func": spider.get_chzzk_stream_data, + }, + "haixiu": { + "url": "https://www.haixiutv.com/6095106", + "func": spider.get_haixiu_stream_url, } } diff --git a/douyinliverecorder/javascript/haixiu.js b/douyinliverecorder/javascript/haixiu.js new file mode 100644 index 0000000..f0efcb0 --- /dev/null +++ b/douyinliverecorder/javascript/haixiu.js @@ -0,0 +1,539 @@ +var closeGeetest = !1, _a123 = "haija1c7", _b2x = "xiuhc2a6", _c3y = "anchc3a5", _dx34 = "famic7a2", _hf_constants1 = "sowh1e", _hf_constants2 = "1000ha", _hf_constants3 = "butr12", _hf_constants4 = "2000h5", _gf_constants1 = "lehaaj", _gf_constants2 = "1000ax", _gf_constants3 = "lehaData" +let CryptoJS = null; +function EnmoliParamter() { + + this._a123 = eval("_hf_constants1"), + this._b2x = eval("_hf_constants2"), + this._c3y = eval("_hf_constants3"), + this._dx34 = eval("_hf_constants4"), + this.getA123 = function() { + return this._a123 + } + , + this.getB2X = function() { + return this._b2x + } + , + this.getC3Y = function() { + return this._c3y + } + , + this.getDX34 = function() { + return this._dx34 + } +} +EnmoliParamter.prototype = { + aa: function(e, t) { + if (e === t) + return e; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e; + if (e.arity === t.arity && e.string === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + ac: function(e, t) { + if (e === t) + return e; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e; + if (e.id === t.id && (e = CryptoJS.MD5(e) + ""), + e.arity1 === t.arity && e.string2 === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + ad: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e; + if (e.arity2 === t.arity && e.string3 === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + ae: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity3 === t.arity && e.string4 === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + af: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity4 === t.arity && e.string5 === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + ah: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e; + if (e.arity6 === t.arity && e.string9 === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + ai: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e; + if (e.arity2 === t.arity5 && e.string === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + aj: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity44 === t.arity42 && e.string === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + ak: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity21 === t.arity322 && e.string === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + ax: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity22 === t.arity32 && e.string === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + az: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity42 === t.arity57 && e.string2 === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return e + }, + are_similar: function(e, t) { + if (e === t) + return !0; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return !0; + return !0 + } + return e + } + if (Array.isArray(t)) + return e; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity === t.arity && e.string === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third); + case "function": + case "regexp": + return e; + default: + return !0 + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e.second.string === t.second.string && "(string)" === t.second.id; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return e.second.string === t.second.string && "(string)" === e.second.id + } + return !1 + }, + ayz: function(e, t) { + if (e === t) + return e; + if (Array.isArray(e)) { + if (Array.isArray(t) && e.length === t.length) { + var i; + for (i = 0; i < e.length; i += 1) + if (!this.are_similar(e[i], t[i])) + return e; + return e + } + return e + } + if (Array.isArray(t)) + return t; + if ("(number)" === e.id && "(number)" === t.id) + return e.number === t.number; + if (e.arity42 === t.arity57 && e.string2 === t.string) + switch (e.arity) { + case "prefix": + case "suffix": + case "infix": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second); + case "ternary": + return this.are_similar(e.first, t.first) && this.are_similar(e.second, t.second) && this.are_similar(e.third, t.third) + } + else { + if ("." === e.id && "[" === t.id && "infix" === t.arity) + return e; + if ("[" === e.id && "infix" === e.arity && "." === t.id) + return t + } + return this.getA123().substring(4) + this.getB2X().substring(4) + this.getC3Y().substring(4) + this.getDX34().substring(4) + } +} +function EnmoliSubmiter() {} +EnmoliSubmiter.prototype = { + bsq: function(e) { + var t = this.pf(e) + , i = this.as(t); + return this.brm(i) + }, + pf: function(e) { + var t = {}; + for (var i in e) + "" !== e[i] && (t[i] = e[i]); + return t + }, + as: function(e) { + for (var t = {}, i = Object.keys(e).sort(), o = 0; o < i.length; o++) { + var n = i[o]; + t[n] = e[n] + } + return t + }, + brm: function(e) { + var t = this.cls(e) + , i = new EnmoliParamter; + return this.pt(t, i.ayz(t, "showselfAnchorVisitorParameters")) + }, + cls: function(e) { + var t = ""; + for (var i in e) + t = t + i + "=" + e[i] + "&"; + return t = t.substring(0, t.length - 1) + }, + pt: function(e, t) { + var i = new EnmoliParamter; + return e += t, + i.az(i.ax(i.ak(i.aj(i.ai(i.ah(i.af(i.ae(i.ad(i.ac(i.aa(e, e + "01" + t), e + "escape" + t), e + "same"), e + "visitor"), "anchor"), e + "person"), e + "ax" + t), "ae" + t), e + "ax" + t), e + "inspect" + t), "af" + t) + }, + bnu: function(e, t) { + for (var i = e.split("&"), o = 0; o < i.length; o++) { + var n = i[o].split("="); + 2 == n.length && (t[n[0]] = encodeURIComponent($.trim(n[1])).toString()) + } + }, + bn: function(e, t) { + for (var i in e) + "object" == typeof e[i] ? t[i] = encodeURIComponent($.trim(JSON.stringify(e[i]))).toString() : t[i] = encodeURIComponent($.trim(e[i])).toString() + } +} +var enmoliSubmiter = new EnmoliSubmiter(); + +function sign(options, cryptoJSPath){ + CryptoJS = require(cryptoJSPath); + return enmoliSubmiter.bsq(options); +} +module.exports = { + sign +}; + +// const options = { +// "accessToken": "pLXSC%252FXJ0asc1I21tVL5FYZhNJn2Zg6d7m94umCnpgL%252BuVm31GQvyw%253D%253D", +// "tku": "3000006", +// "c": "10138100100000", +// "_st1": "1728621076958" +// } +// const cryptoJSPath = './crypto-js.min.js' +// console.log(sign(options, cryptoJSPath)) \ No newline at end of file diff --git a/douyinliverecorder/spider.py b/douyinliverecorder/spider.py index e843be2..e49c67b 100644 --- a/douyinliverecorder/spider.py +++ b/douyinliverecorder/spider.py @@ -2541,4 +2541,48 @@ def get_chzzk_stream_data(url: str, proxy_addr: Union[str, None] = None, cookies prefix = m3u8_url.split('?')[0].rsplit('/', maxsplit=1)[0] m3u8_url_list = [prefix + '/' + i for i in m3u8_url_list] result["play_url_list"] = m3u8_url_list + return result + + +@trace_error_decorator +def get_haixiu_stream_url(url: str, proxy_addr: Union[str, None] = None, cookies: Union[str, None] = None) -> \ + Dict[str, Any]: + headers = { + 'origin': 'https://www.haixiutv.com', + 'referer': 'https://www.haixiutv.com/', + 'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36', + } + if cookies: + headers['Cookie'] = cookies + + room_id = url.split("?")[0].rsplit('/', maxsplit=1)[-1] + access_token = "pLXSC%252FXJ0asc1I21tVL5FYZhNJn2Zg6d7m94umCnpgL%252BuVm31GQvyw%253D%253D" + params = { + "accessToken": access_token, + "tku": "3000006", + "c": "10138100100000", + "_st1": int(time.time()*1000) + } + ajax_data = execjs.compile(open(f'{JS_SCRIPT_PATH}/haixiu.js').read()).call('sign', params, f'{JS_SCRIPT_PATH}/crypto-js.min.js') + + params["accessToken"] = urllib.parse.unquote(urllib.parse.unquote(access_token)) + params['_ajaxData1'] = ajax_data + params['_'] = int(time.time()*1000) + + api = f'https://service.haixiutv.com/v2/room/{room_id}/media/advanceInfoRoom?{urllib.parse.urlencode(params)}' + json_str = get_req(api, proxy_addr=proxy_addr, headers=headers, abroad=True) + json_data = json.loads(json_str) + + stream_data = json_data['data'] + anchor_name = stream_data['nickname'] + live_status = stream_data['live_status'] + result = { + "anchor_name": anchor_name, + "is_live": False, + } + if live_status == 1: + result["is_live"] = True + flv_url = stream_data['media_url_web'] + result['flv_url'] = flv_url + result['record_url'] = flv_url return result \ No newline at end of file diff --git a/main.py b/main.py index d017c91..fdfd7ec 100644 --- a/main.py +++ b/main.py @@ -35,9 +35,9 @@ from douyinliverecorder.msg_push import ( dingtalk, xizhi, tg_bot, email_message, bark ) -version = "v3.0.8" +version = "v3.0.9" platforms = ("\n国内站点:抖音|快手|虎牙|斗鱼|YY|B站|小红书|bigo|blued|网易CC|千度热播|猫耳FM|Look|TwitCasting|百度|微博|" - "酷狗|花椒|流星|Acfun|时光|映客|音播|知乎" + "酷狗|花椒|流星|Acfun|时光|映客|音播|知乎|嗨秀" "\n海外站点:TikTok|AfreecaTV|PandaTV|WinkTV|FlexTV|PopkonTV|TwitchTV|LiveMe|ShowRoom|CHZZK") recording = set() @@ -703,6 +703,12 @@ def start_record(url_data: tuple, count_variable: int = -1): url=record_url, proxy_addr=proxy_address, cookies=chzzk_cookie) port_info = stream.get_stream_url(json_data, record_quality, spec=True) + elif record_url.find("www.haixiutv.com/") > -1: + platform = '嗨秀直播' + with semaphore: + port_info = spider.get_haixiu_stream_url( + url=record_url, proxy_addr=proxy_address, cookies=haixiu_cookie) + else: logger.error(f'{record_url} {platform}直播地址') return @@ -733,11 +739,6 @@ def start_record(url_data: tuple, count_variable: int = -1): clear_record_info(record_name, record_url) return - if record_name in recording: - print(f"新增的地址: {anchor_name} 已经存在,本条线程将会退出") - need_update_line_list.append(f'{record_url}|#{record_url}') - return - if url_data[-1] == "" and run_once is False: if is_long_url: need_update_line_list.append( @@ -1418,6 +1419,7 @@ while True: yingke_cookie = read_config_value(config, 'Cookie', 'yingke_cookie', '') zhihu_cookie = read_config_value(config, 'Cookie', 'zhihu_cookie', '') chzzk_cookie = read_config_value(config, 'Cookie', 'chzzk_cookie', '') + haixiu_cookie = read_config_value(config, 'Cookie', 'haixiu_cookie', '') video_save_type_list = ("FLV", "MKV", "TS", "MP4", "MP3音频", "M4A音频") if video_save_type and video_save_type.upper() in video_save_type_list: @@ -1506,7 +1508,8 @@ while True: 'live.ybw1666.com', 'wap.ybw1666.com', 'www.inke.cn', - 'www.zhihu.com' + 'www.zhihu.com', + 'www.haixiutv.com' ] overseas_platform_host = [ 'www.tiktok.com', @@ -1532,7 +1535,9 @@ while True: "www.xiaohongshu.com", "www.redelight.cn", "www.huya.com", - "chzzk.naver.com" + "chzzk.naver.com", + "www.liveme.com", + "www.haixiutv.com" ) if url_host in platform_host: @@ -1547,7 +1552,8 @@ while True: url_tuples_list.append(new_line) else: print(f"\r{origin_line} 本行包含未知链接.此条跳过") - update_file(url_config_file, url, url, start_str='#') + if not origin_line.startswith('#'): + update_file(url_config_file, url, url, start_str='#') while len(need_update_line_list): a = need_update_line_list.pop()