Перейти к основному содержимому

Как экспортировать детали прокси Indigo с помощью Python

Вы можете легко создавать списки учетных данных прокси в формате JSON из любого набора профилей браузера Indigo X с помощью Python, используя их идентификаторы профилей! Эта статья поможет вам эффективно создавать эти списки.

Перед началом работы

Убедитесь, что у вас настроена среда Python со следующими установленными пакетами:

  • os
  • json
  • dotenv
  • hashlib
  • requests

Сохраните скрипт proxies_to_json.py в нужной вам папке.

к сведению

Значения конфигурации, такие как учетные данные, идентификатор папки и пути к файлам, управляются внутри скрипта или в сопутствующем файле .env. Вам нужно будет настроить их в соответствии с вашей конфигурацией.

Скрипт Python: proxies_to_json.py

import os
import json
import dotenv
import hashlib
import requests

dotenv.load_dotenv()

# Credentials are pulled from a local .env file
USERNAME = os.getenv("indigoUSERNAME")
PASSWORD = os.getenv("indigoPASSWORD")

# Insert Your FolderID here (optional, used if you customize profile_search)
FOLDERID = "91f042e6-xxx-4e1f-adee-5eed6bb47d60"

# Insert your profile_ids.json filepath here (used for option 3)
LIST_PATH = "C:/.../files/pid_list.json" # Example: "C:/Users/YourUser/indigo_profiles/profile_ids.json"

# Paste your string values manually (used for option 1)
LIST_MANUAL = [
"95f6d02c-xxxx-47c4-b1d4-369801f2a37c",
"48da90d8-xxxx-40a2-8ccb-2d9e7e3eaebb",
"e2f9d96a-xxxx-4439-ae74-10beda6bf109",
"fffca377-xxxx-495e-a408-3a98716e14ea",
"f3559ca3-xxxx-479c-8a8a-c4b831e8f78b",
"1c1e09dc-xxxx-4495-979b-7cb805a3a8a1",
"a66ba910-xxxx-48ac-a6d1-615f996b3a1d",
"f17140f4-xxxx-47c5-96d5-1b9fd184203b",
"0a505d93-xxxx-4ba9-bd25-d37bf8bb168d",
]

# API-Related Objects
LOCALHOST = "http://127.0.0.1"
indigo_BASE = "https://api.indigo.com" # Main API endpoint
LAUNCHERV1 = "https://launcher.indigobrowser.com:45011/api/v1" # Launcher API endpoint
HEADERS = {"Accept": "application/json", "Content-Type": "application/json"}

# Login Function
def signin() -> str:
payload = {
"email": USERNAME,
"password": hashlib.md5(PASSWORD.encode()).hexdigest(),
}

r = requests.post(f"{indigo_BASE}/user/signin", json=payload)

if r.status_code != 200:
print(f"\nError during login: {r.status_code} - {r.text}\n")
return ""
else:
try:
response_data = r.json().get("data", {})
token = response_data.get("token")
if token:
print("Successfully signed in.")
return token
else:
print(f"\nError during login: Token not found in response. {r.json()}\n")
return ""
except requests.exceptions.JSONDecodeError:
print(f"\nError during login: Could not decode JSON response. {r.text}\n")
return ""

# Search Profiles (example: recently created by the Bulk Create function, called "TempName")
def profile_search():
url = f"{indigo_BASE}/profile/search"
body = {
"is_removed": False, # Search for active profiles? True/False
"limit": 100, # How many profile results to get
"offset": 0, # Check Indigo Documenter page for full parameter breakdown
"search_text": "", # e.g., "TempName" or "" for all
"storage_type": "all", # "local", "cloud", "all"
"order_by": "created_at", # "name", "created_at", "updated_at"
"sort": "asc", # "asc" or "desc"
}
print(f"Searching profiles with parameters: {body}")
response = requests.request("POST", url, headers=HEADERS, json=body)

if response.status_code != 200:
print(f"Error during profile search: {response.status_code} - {response.text}")
return {"data": {"total_count": 0, "profiles": []}} # Return empty structure on error

try:
resp_json = response.json()
return resp_json
except requests.exceptions.JSONDecodeError:
print(f"Error decoding JSON from profile search: {response.text}")
return {"data": {"total_count": 0, "profiles": []}} # Return empty structure on error

# Obtain a list of ProfileIDs retrieved by the Profile Search endpoint
def get_profile_ids():
profile_list_response = profile_search()

if not profile_list_response or profile_list_response.get("data", {}).get("total_count") == 0:
print("No profiles found or error in response during profile search.")
return []

profiles_data = profile_list_response.get("data", {}).get("profiles", [])
if profiles_data:
profile_ids = [profile["id"] for profile in profiles_data if "id" in profile]
print(f"Found {len(profile_ids)} profile IDs from search.")
return profile_ids
else:
print("Error: 'profiles' key not found or empty in profile search response.")
return []

# Use Profile Metas endpoint to get the Proxy information registered.
def search_proxy_metas(option_call):
url = f"{indigo_BASE}/profile/metas"
profile_ids_to_query = []

if option_call == "1": # Manual List
profile_ids_to_query = LIST_MANUAL
print(f"Using manual list of {len(profile_ids_to_query)} profile IDs.")
elif option_call == "2": # Profile Search
profile_ids_to_query = get_profile_ids()
if not profile_ids_to_query:
print("No profile IDs obtained from profile search. Aborting proxy meta search.")
return
print(f"Using {len(profile_ids_to_query)} profile IDs from profile search.")
elif option_call == "3": # From file PATH
try:
with open(LIST_PATH, "r") as file:
profile_ids_to_query = json.load(file)
if not isinstance(profile_ids_to_query, list):
print(f"Error: Content of {LIST_PATH} is not a JSON list.")
return
print(f"Using {len(profile_ids_to_query)} profile IDs from file: {LIST_PATH}.")
except FileNotFoundError:
print(f"Error: File not found at {LIST_PATH}. Please check the path.")
return
except json.JSONDecodeError:
print(f"Error: Could not decode JSON from {LIST_PATH}. Ensure it's a valid JSON array of strings.")
return
else:
# This case should ideally be caught by the main function's input validation
print("Invalid option for search_proxy_metas. This should not happen.")
return

if not profile_ids_to_query:
print("No profile IDs to query. Exiting proxy meta search.")
return

payload = json.dumps({"ids": profile_ids_to_query})
print(f"Requesting metas for {len(profile_ids_to_query)} profiles.")
response = requests.request("POST", url, headers=HEADERS, data=payload)

if response.status_code != 200:
print(f"Error fetching profile metas: {response.status_code} - {response.text}")
return

try:
response_data = response.json()
except requests.exceptions.JSONDecodeError:
print(f"Error decoding JSON response from profile metas: {response.text}")
return

query_result = []
if response_data and "data" in response_data and "profiles" in response_data["data"]:
for profile_meta in response_data["data"]["profiles"]:
if "parameters" in profile_meta and "proxy" in profile_meta["parameters"]:
proxy_metas = profile_meta["parameters"]["proxy"]
# Optionally, include profile ID with its proxy details
# query_result.append({"profile_id": profile_meta.get("id"), "proxy": proxy_metas})
query_result.append(proxy_metas)
else:
print(f"Warning: Proxy parameters not found for profile ID {profile_meta.get('id', 'N/A')}")
else:
print(f"Unexpected response structure or no profile data in metas response: {response_data}")
return

if not query_result:
print("No proxy details found for the given profile IDs.")
return

proxy_json = json.dumps(query_result, indent=4)
# print(proxy_json) # Optionally print to console

output_filename = "proxy_credentials.json"
try:
with open(output_filename, "w") as json_file:
json_file.write(proxy_json)
print(
f"\nTotal of {len(query_result)} proxies were saved to {output_filename}\n"
)
except IOError as e:
print(f"Error writing to file {output_filename}: {e}")


# Main function
def main():
token = signin()
if token:
HEADERS.update({"Authorization": f"Bearer {token}"})
else:
print("Failed to sign in. Please check credentials and network. Exiting.")
return

option_prompt = (
"\n\nSelect method to provide profile ID list:\n"
" (1) Manual List (uses LIST_MANUAL in script)\n"
" (2) From Profile Search (dynamic, uses profile_search function)\n"
" (3) From file PATH (uses LIST_PATH in script, e.g., profile_ids.json)\n"
"Write selection (1, 2, or 3): "
)

option_call = input(option_prompt)

if option_call not in ["1", "2", "3"]:
print("Invalid selection. Please enter 1, 2, or 3. Exiting.")
return

search_proxy_metas(option_call)

if __name__ == "__main__":
main()

Запуск скрипта

  1. Откройте терминал или командную строку.

  2. Перейдите в папку, содержащую proxies_to_json.py и ваш файл .env:

    cd path/to/your/script_folder
  3. Запустите скрипт с помощью Python:

    python proxies_to_json.py
  4. Выберите опцию ввода: Когда будет предложено, выберите, как скрипт должен получить список идентификаторов профилей:

    • Опция 1 (Список вручную): Использует список Python LIST_MANUAL, жестко запрограммированный в скрипте.
    • Опция 2 (Из поиска профилей): Динамически извлекает идентификаторы профилей с помощью функции profile_search.
      • Вы можете настроить параметры body функции profile_search (например, search_text, limit, folder_id, если вы его добавите), чтобы уточнить, какие профили являются целевыми. Текущий скрипт по умолчанию ищет до 100 активных профилей.
    • Опция 3 (Из пути к файлу): Считывает идентификаторы профилей из файла JSON, указанного переменной LIST_PATH в скрипте.
  5. Проверьте результаты: После выполнения скрипт попытается сохранить извлеченные данные прокси в файле JSON с именем proxy_credentials.json в той же папке. Он также выведет сводное сообщение в консоль.

Пример profile_ids.json (для Опции 3)

Если вы используете Опцию (3), убедитесь, что ваш profile_ids.json (или файл, указанный в LIST_PATH) содержит действительный массив JSON строк идентификаторов профилей:

[
"95f6d02c-xxxx-47c4-b1d4-369801f2a37c",
"48da90d8-xxxx-40a2-8ccb-2d9e7e3eaebb",
"e2f9d96a-xxxx-4439-ae74-10beda6bf109"
]

Понимание вывода: proxy_credentials.json

Файл proxy_credentials.json будет содержать массив JSON. Каждый объект в этом массиве представляет конфигурацию прокси, извлеченную для одного из указанных профилей Indigo. Точные поля в каждом объекте прокси будут зависеть от типа прокси (например, HTTP, HTTPS, SOCKS4, SOCKS5, SSH) и того, как он настроен в Indigo (например, хост, порт, имя пользователя, пароль).

Пример того, как может выглядеть вывод (структура будет варьироваться в зависимости от ваших фактических настроек прокси):

[
{
"type": "http",
"host": "proxy.example.com",
"port": 8080,
"username": "proxy_user_1",
"password": "proxy_password_1"
},
{
"type": "socks5",
"host": "another-proxy.example.org",
"port": 1080,
"username": "",
"password": ""
},
{
"type": "ssh",
"host": "ssh-server.example.net",
"port": 22,
"username": "ssh_user"
// SSH proxy might have 'sshPassword' or 'sshKey' fields
}
]
подсказка

Этот скрипт предлагает гибкий способ автоматизации извлечения данных прокси из ваших профилей Indigo, что может быть особенно полезно для управления многочисленными профилями или интеграции с другими инструментами и рабочими процессами. Не забывайте безопасно обращаться с выходным файлом proxy_credentials.json, так как он содержит конфиденциальную информацию.