在 github 上獲取免費節點,訂閱鏈接列表可以自己添加上去,理論上每天有無數的節點,不崇洋,也不要被忽悠,打破信息蠶房,獨立思考。
import requests
import yaml
import base64
# 定義訂閱鏈接列表
SUBSCRIPTION_URLS = ["https://raw.githubusercontent.com/Surfboardv2ray/TGParse/main/splitted/mixed"
"https://raw.githubusercontent.com/ripaojiedian/freenode/main/sub"
"https://raw.githubusercontent.com/roosterkid/openproxylist/main/V2RAY_RAW.txt"
"https://github.com/andrewji8/V2ray-Configs/blob/main/All_Configs_base64_Sub.txt"
]
def fetch_subscription(url):
"""獲取訂閱內容"""
try:
response = requests.get(url, timeout=10, verify=False) # 禁用 SSL 驗證
if response.status_code == 200:
return response.text.strip() # 去除多餘的空白字符
else:
print(f"無法獲取 {url} 的內容,狀態碼: {response.status_code}")
return None
except Exception as e:
print(f"請求 {url} 失敗: {e}")
return None
def decode_base64(content):
"""解碼 Base64 編碼的內容"""
try:
decoded_content = base64.b64decode(content).decode("utf-8")
return decoded_content
except Exception as e:
print(f"Base64 解碼失敗: {e}")
return None
def parse_yaml(content):
"""解析 YAML 內容"""
try:
data = yaml.safe_load(content)
if isinstance(data, dict): # 如果是字典類型,直接返回
return data
elif isinstance(data, str): # 如果是字符串類型,包裝為字典
return {"proxies": [data]} # 假設內容是代理節點列表
else:
print(f"解析結果不是字典或字符串類型: {type(data)}")
return None
except Exception as e:
print(f"解析 YAML 失敗: {e}")
return None
def merge_subscriptions(subscriptions):
"""合併多個訂閱內容,並去除重複項"""
merged_data = {}
for sub in subscriptions:
if not sub or not isinstance(sub, dict): # 確保訂閱內容是字典類型
print("跳過無效的訂閱內容")
continue
for key, value in sub.items():
if key not in merged_data:
merged_data[key] = value
elif isinstance(value, list) and isinstance(merged_data[key], list):
# 合併列表並去重
merged_data[key] = list(set(merged_data[key] + value))
elif isinstance(value, dict) and isinstance(merged_data[key], dict):
# 如果是字典類型,遞歸合併
merged_data[key].update(value)
return merged_data
def save_to_files(data, group_size=12000, base_filename="subscription_group"):
"""將數據分組保存到多個文件"""
if "proxies" not in data:
print("沒有代理節點可以分組")
return
proxies = data["proxies"]
total_groups = (len(proxies) + group_size - 1) // group_size # 計算分組數量
for i in range(total_groups):
group_proxies = proxies[i * group_size:(i + 1) * group_size]
group_data = {**data, "proxies": group_proxies} # 創建分組數據
filename = f"{base_filename}_{i + 1}.yaml"
with open(filename, "w", encoding="utf-8") as f:
yaml.dump(group_data, f, allow_unicode=True)
print(f"分組 {i + 1} 已保存到 {filename}")
def split_yaml_file(input_filename, output_base_filename="split_subscription", num_splits=3):
"""
將一個 YAML 文件分割成多個文件。
:param input_filename: 輸入的 YAML 文件名
:param output_base_filename: 輸出文件的基礎名稱
:param num_splits: 分割的文件數量
"""
try:
# 讀取輸入的 YAML 文件
with open(input_filename, "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
if "proxies" not in data:
print("沒有代理節點可以分割")
return
proxies = data["proxies"]
total_proxies = len(proxies)
print(f"總節點數: {total_proxies}")
# 計算每組的大小
group_size = (total_proxies + num_splits - 1) // num_splits # 向上取整
# 分割並保存到多個文件
for i in range(num_splits):
start_index = i * group_size
end_index = min((i + 1) * group_size, total_proxies)
group_proxies = proxies[start_index:end_index]
if not group_proxies:
print(f"分組 {i + 1} 沒有節點,跳過保存")
continue
# 創建分組數據
group_data = {**data, "proxies": group_proxies}
output_filename = f"{output_base_filename}_{i + 1}.yaml"
# 保存到文件
with open(output_filename, "w", encoding="utf-8") as f:
yaml.dump(group_data, f, allow_unicode=True)
print(f"分組 {i + 1} 已保存到 {output_filename}")
except Exception as e:
print(f"分割文件失敗: {e}")
def main():
# 獲取所有訂閱內容
subscription_contents = [fetch_subscription(url) for url in SUBSCRIPTION_URLS]
# 解碼 Base64 並解析為 YAML 格式
parsed_subscriptions = []
for content in subscription_contents:
if content:
print(f"原始內容: {content[:100]}...") # 打印前 100 個字符
decoded_content = decode_base64(content)
if decoded_content:
print(f"解碼後內容: {decoded_content[:100]}...") # 打印前 100 個字符
data = parse_yaml(decoded_content)
print(f"解析後數據類型: {type(data)}")
parsed_subscriptions.append(data)
# 合併訂閱內容
merged_data = merge_subscriptions(parsed_subscriptions)
# 分組保存到多個文件,每組 12000 個節點
if merged_data:
save_to_files(merged_data, group_size=12000) # 每組 12000 個節點
else:
print("沒有有效的訂閱內容可以合併")
# 將生成的第一個分組文件分割成 3 個子文件
input_filename = "subscription_group_1.yaml"
split_yaml_file(input_filename, output_base_filename="split_subscription", num_splits=3)
if __name__ == "__main__":
main()