4gtv 在台湾地区也属于比较流行的流媒体平台,它的频道数量是非常多的,正常情况下,普通用户只能观看免费频道以及 720P 的直播,但实际上它的系统代码是比较简单的,下面的方法可以帮助你解析出 1080P 的直播地址,以及付费频道的直播地址。
首先按照我的理解,我将 4gtv 的频道分为三类:
了解 Livednow 的朋友应该知道,之前我们提供港澳台的频道直播,但是后面因为一些原因暂停了,现在重新整理代码的时候发现之前使用的方法已经失效,所以本贴先暂时分享其中一种有效的方法,等我后续再发布其他方式。
本方法无需绕过 Cloudflare WAF 验证,但是有些代理 IP 无法解锁,具体需要自己测试
这类频道的 ID 类似 民視第一台 对应的 1,以下是代码:
import json
from urllib.parse import urlparse, parse_qs
from utils import my_requester, encrypt_data, decrypt_data
def get_channel(channel_id):
channel_info = {
'id': channel_id,
}
get_channel_api = f'https://api2.4gtv.tv/Channel/GetChannel/{channel_id}'
headers = {
'User-Agent': 'okhttp/3.12.11'
}
response = my_requester('GET', url=get_channel_api, headers=headers)
if not response:
print('Failed to get channel info')
return channel_info
response_dict = response.json()
channel_info['name'] = response_dict['Data']['fsNAME']
request_dict = {
'fnCHANNEL_ID': response_dict['Data']['fnID'],
'fsASSET_ID': response_dict['Data']['fs4GTV_ID'],
'fsDEVICE_TYPE': 'mobile',
'clsIDENTITY_VALIDATE_ARUS': {'fsVALUE': ''}
}
encrypt = encrypt_data(json.dumps(request_dict))
request_data = {'value': encrypt.decode()}
headers['Content-Type'] = 'application/x-www-form-urlencoded'
response = my_requester('POST',
url='https://api2.4gtv.tv/Channel/GetChannelUrl3',
data=request_data, headers=headers)
if not response:
print('Failed to get channel play info')
return channel_info
response_dict = response.json()
if 'Data' not in response_dict:
print('Failed to get channel play info')
return channel_info
decrypt = decrypt_data(response_dict['Data'])
playlist = json.loads(decrypt)
play_url = playlist['flstURLs'][0]
if play_url.startswith('https://4gtvfree-cds.cdn.hinet.net'):
play_url = play_url.replace('/index.m3u8?', '/1080.m3u8?')
else:
play_url = get_play_raw(play_url, return_type='url')
channel_info['play_url'] = play_url
return channel_info
def get_play_raw(url, return_type='raw'):
headers = {
'User-Agent': 'okhttp/3.12.11'
}
response = my_requester('GET', url=url, headers=headers)
parsed_url = urlparse(url)
if not response:
return None
resp_text = response.text.strip()
latest_line = resp_text.split('\n')[-1]
url_path = '/'.join(parsed_url.path.split('/')[0:-1])
new_url = f'{parsed_url.scheme}://{parsed_url.netloc}{url_path}/{latest_line}'
if return_type == 'url':
return new_url
if '.ts' in latest_line:
return resp_text
else:
return get_play_raw(new_url, return_type)
def play_4gtv(play_url):
m3u8_raw = get_play_raw(play_url)
if not m3u8_raw:
print('Failed to get play url')
if play_url.startswith('https://4gtvfree-cds.cdn.hinet.net'):
# live 格式的处理
base_url = play_url.split('?')[0].rsplit('/', 1)[0]
lines = []
for line in m3u8_raw.split('\n'):
if line.startswith('#EX') or not line.strip():
lines.append(line)
elif '.ts' in line:
ts_file = line.split('?')[0]
parsed_url = urlparse(line)
params = parse_qs(parsed_url.query)
params_simplified = {k: v[0] for k, v in params.items()}
ts_url = (f'{base_url}/{ts_file}?'
f'token1={params_simplified["token1"]}'
f'&expires1={params_simplified["expires1"]}')
lines.append(ts_url)
else:
lines.append(line)
m3u8_raw = '\n'.join(lines)
else:
channel = play_url.split('?')[0].split('/')[-3]
lines = []
prex = f'https://litvpc-hichannel.cdn.hinet.net/live/pool/{channel}/litv-pc/'
for line in m3u8_raw.split('\n'):
if line.startswith('#EXT') or not line.strip():
lines.append(line)
else:
ts_file = line.split('?')[0]
ts_file = ts_file.replace('video=2000000', 'video=6000000')
ts_file = ts_file.replace('video=2936000', 'video=5936000')
ts_file = ts_file.replace('video=3000000', 'video=6000000')
ts_file = ts_file.replace('avc1_2000000=3', 'avc1_6000000=1')
ts_file = ts_file.replace('avc1_2000000=6', 'avc1_6000000=1')
ts_file = ts_file.replace('avc1_2936000=4', 'avc1_6000000=5')
ts_file = ts_file.replace('avc1_3000000=3', 'avc1_6000000=1')
ts_url = f'{prex}{ts_file}'
lines.append(ts_url)
m3u8_raw = '\n'.join(lines)
print(m3u8_raw)
if __name__ == '__main__':
info = get_channel('1')
print(info)
if 'play_url' in info:
play_4gtv(info['play_url'])
以上代码仅提供一些思路和测试方法,如果要在播放器中播放,可以使用我已经构建好的 Docker 镜像 pixman/4gtv:
# run
docker run --name=4gtv -d -p 5000:5000 pixman/4gtv
# 使用代理 (192.168.1.1:7890 替换成你的代理地址)
docker run --name=4gtv -d -p 5000:5000 -e HTTP_PROXY=http://192.168.1.1:7890 -e HTTPS_PROXY=http://192.168.1.1:7890 pixman/4gtv
# test
curl http://localhost:5000/4gtv/1 --location
在播放器中使用 http://localhost:5000/4gtv/{ID} 即可播放。
关于代理,只需将以下域名添加到你的规则中即可:
如果你在请求时,报错 ERROR in utils: Request failed: 403 Client Error: Forbidden for url: https://api2.4gtv.tv/Channel/GetChannelUrl3,说明你的 IP 无法解锁,可以尝试使用其他代理。
import base64
import time
import logging
import requests
import urllib3
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import pad, unpad
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
KEY = 'ilyB29ZdruuQjC45JhBBR7o2Z8WJ26Vg'.encode()
IV = 'JUMxvVMmszqUTeKn'.encode()
def my_requester(method, **kwargs):
retry_times = 3
timeout = 5
if 'timeout' in kwargs:
timeout = kwargs.pop('timeout', 5)
verify = False
if 'verify' in kwargs:
verify = kwargs.pop('verify', False)
while retry_times > 0:
try:
resp = requests.request(method, timeout=timeout, verify=verify, **kwargs)
resp.raise_for_status()
return resp
except Exception as e:
retry_times -= 1
time.sleep(0.5)
logging.error(f'Request failed: {e}, retrying...')
logging.error('Request failed after retrying')
return None
def encrypt_data(data):
cipher = AES.new(KEY, AES.MODE_CBC, IV)
padded_data = pad(data.encode(), AES.block_size)
return base64.b64encode(cipher.encrypt(padded_data))
def decrypt_data(encrypted_data):
decipher = AES.new(KEY, AES.MODE_CBC, IV)
decrypted_data = unpad(decipher.decrypt(base64.b64decode(encrypted_data)), AES.block_size)
return decrypted_data.decode()
| id | name |
|---|---|
| 1 | 民視第一台 |
| 2 | 民視台灣台 |
| 3 | 民視 |
| 4 | 中視 |
| 6 | 華視 |
| 7 | 公視戲劇 |
| 8 | 好消息 2 台 |
| 9 | 好消息 |
| 11 | 達文西頻道 |
| 15 | 靖天卡通台 |
| 16 | 民視綜藝台 |
| 19 | 愛爾達娛樂台 |
| 21 | 靖天綜合台 |
| 22 | 靖天日本台 |
| 23 | 龍華戲劇台 |
| 24 | 民視影劇台 |
| 25 | 采昌影劇台 |
| 28 | 龍華日韓台 |
| 30 | 中天新聞台 |
| 31 | 民視新聞台 |
| 33 | 中視新聞 |
| 34 | 華視新聞 |
| 36 | 寰宇新聞台 |
| 38 | 視納華仁紀實頻道 |
| 39 | amc 電影台 |
| 40 | 影迷數位電影台 |
| 42 | 靖天映畫 |
| 48 | 博斯高球台 |
| 50 | 博斯運動一台 |
| 51 | 博斯無限台 |
| 52 | 博斯網球台 |
| 57 | TRACE Sport Stars |
| 58 | 智林體育台 |
| 59 | 靖洋卡通 Nice Bingo |
| 60 | i-Fun 動漫台 |
| 61 | 民視旅遊台 |
| 69 | 時尚運動 X |
| 78 | TRACE Urban |
| 79 | Mezzo Live HD |
| 80 | CLASSICA 古典樂 |
| 82 | 靖天電影台 |
| 83 | 靖天育樂台 |
| 84 | KLT-靖天國際台 |
| 85 | 半島國際新聞台 |
| 86 | VOA 美國之音 |
| 88 | 靖天資訊台 |
| 93 | 鳳梨直擊台 |
| 94 | 香蕉直擊台 |
| 106 | ELTV 生活英語台 |
| 107 | 客家電視台 |
| 113 | 豬哥亮歌廳秀 |
| 114 | 八大綜藝台 |
| 116 | 靖天戲劇台 |
| 118 | 靖洋戲劇台 |
| 119 | Nice TV 靖天歡樂台 |
| 121 | 龍華電影台 |
| 123 | 中視菁采台 |
| 124 | 中視經典台 |
| 139 | Love Nature |
| 160 | 車迷 TV |
| 168 | 幸福空間居家台 |
| 169 | 三立綜合台 |
| 170 | 國會頻道 1 |
| 171 | 國會頻道 2 |
| 172 | 八大精彩台 |
| 173 | 東森購物一台 |
| 174 | 東森購物二台 |
| 175 | LUXE TV Channel |
| 176 | My Cinema Europe HD 我的歐洲電影 |
| 178 | TV5MONDE STYLE HD 生活時尚 |
| 179 | GINX Esports TV |
| 180 | ROCK Action |
| 181 | TechStorm |
| 182 | Pet Club TV |
| 183 | TVBS |
| 184 | TVBS 歡樂台 |
| 185 | 尼克兒童頻道 |
| 186 | HITS 頻道 |
| 188 | LiveABC 互動英語頻道 |
| 189 | ARIRANG 阿里郎頻道 |
| 201 | 經典電影台 |
| 202 | 經典卡通台 |
| 204 | 精選動漫台 |
| 209 | 大愛電視 |
| 210 | 人間衛視 |
| 212 | 影迷數位紀實台 |
| 213 | MTV Live HD 音樂頻道 |
| 214 | History 歷史頻道 |
| 215 | CI 罪案偵查頻道 |
| 217 | Lifetime 娛樂頻道 |
| 218 | 電影原聲台 CMusic |
| 219 | Nick Jr. 兒童頻道 |
| 223 | XTR 亞太台 |
| 224 | SBN 全球財經台 |
| 225 | CinemaWorld |
| 226 | DW 德國之聲 |
| 227 | TVBS 精采台 |
| 229 | 三立新聞 iNEWS |
| 230 | 大愛二台 |
| 231 | MOMO 親子台 |
| 235 | CNBC Asia 財經台 |
| 236 | 金光布袋戲 |
| 237 | 愛爾達生活旅遊台 |
| 244 | 戲劇免費看 2 台 |
| 245 | 電影免費看 2 台 |
| 246 | 民視 |
| 249 | 滾動力 rollor |
| 250 | 亞洲旅遊台 |
| 252 | Global Trekker |
| 254 | 民視第一台 |
| 255 | 民視台灣台 |
| 256 | 華視新聞 |
| 257 | 民視新聞台 |
| 258 | 中視新聞 |
| 260 | 中天新聞台 |
| 261 | 亞洲旅遊台 |
| 268 | 鏡電視新聞台 |
| 269 | 兒童卡通台 |
| 270 | 戲劇免費看 1 台 |
| 273 | 原住民族電視台 |
| 274 | fun 探索娛樂台 |
| 275 | ROCK Entertainment |
| 277 | 時尚運動 X |
| 278 | 超人力霸王整套看 |
| 279 | 花系列 經典劇場 |
| 280 | 寰宇新聞台灣台 |
| 281 | 寰宇財經台 |
| 282 | DreamWorks 夢工廠動畫 |
| 283 | Bloomberg TV |
| 284 | TVBS 綜藝台 |
| 285 | TVBS 台劇台 |
| 286 | 東森購物四台 |
| 287 | 東森購物三台 |
| 288 | Globetrotter 環遊旅行家 |
| 289 | 番茄直擊台 |
| 290 | 芭樂直擊台 |
| 291 | TVBS 新聞 |
| 292 | 東森新聞台 |
| 293 | 東森財經新聞台 |