Хочу спарсить список игроков с SA-MP сервера legacy.samp-rp.ru:7777 на Python
Сервер отвечает, но не отдает список игроков.
Что пробовал на Python:
Работает:
- Подключение к серверу - ок
- DNS legacy.samp-rp.ru -> 5.252.33.202
- Info запрос (opcode 'i') - показывает 130 игроков онлайн
- Rules запрос (opcode 'r') - отдает правила сервера
Не работает:
- Opcode 'd' (детальные игроки) - таймаут
- Opcode 'c' (базовые игроки) - таймаут
- Opcode 'p' - отвечает, но только 15 байт пустых данных
Вывод:
Сервер специально блокирует получение списка игроков.
Возвращает только базовую инфу, но самих игроков не отдает.
Вопрос:
Кто сталкивался с такой защитой на SA-MP серверах?
Как можно обойти на Python? Может есть другие методы получить список игроков?
Сервер отвечает, но не отдает список игроков.
Что пробовал на Python:
Работает:
- Подключение к серверу - ок
- DNS legacy.samp-rp.ru -> 5.252.33.202
- Info запрос (opcode 'i') - показывает 130 игроков онлайн
- Rules запрос (opcode 'r') - отдает правила сервера
Не работает:
- Opcode 'd' (детальные игроки) - таймаут
- Opcode 'c' (базовые игроки) - таймаут
- Opcode 'p' - отвечает, но только 15 байт пустых данных
Вывод:
Сервер специально блокирует получение списка игроков.
Возвращает только базовую инфу, но самих игроков не отдает.
Вопрос:
Кто сталкивался с такой защитой на SA-MP серверах?
Как можно обойти на Python? Может есть другие методы получить список игроков?
Код:
# Запрос правил сервера - РАБОТАЕТ
def get_rules(self):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(10)
packet = b'SAMP'
packet += socket.inet_aton(self.server_ip)
packet += struct.pack('<H', self.server_port)
packet += b'r' # opcode для правил
sock.sendto(packet, (self.server_ip, self.server_port))
data, addr = sock.recvfrom(4096)
return data # Возвращает правила (101 байт)
except:
return None
Код:
# Запрос списка игроков - НЕ РАБОТАЕТ (таймаут)
def get_players_detailed(self):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(10)
packet = b'SAMP'
packet += socket.inet_aton(self.server_ip)
packet += struct.pack('<H', self.server_port)
packet += b'd' # opcode для детального списка
sock.sendto(packet, (self.server_ip, self.server_port))
data, addr = sock.recvfrom(8192) # Таймаут здесь
return data
except socket.timeout:
return "TIMEOUT"
Код:
# Кастомный opcode 'p' - отвечает но без данных
def try_opcode_p(self):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(5)
packet = b'SAMP'
packet += socket.inet_aton(self.server_ip)
packet += struct.pack('<H', self.server_port)
packet += b'p' # кастомный opcode
sock.sendto(packet, (self.server_ip, self.server_port))
data, addr = sock.recvfrom(1024)
print(f"Opcode p response: {len(data)} bytes") # Всего 15 байт
print(f"Data: {data.hex()}") # 53414d5005fc21ca611e7000000000
return data
except Exception as e:
return f"Error: {e}"
Код:
# DNS разрешение - работает
def resolve_server(self):
try:
ip = socket.gethostbyname("legacy.samp-rp.ru")
print(f"Server IP: {ip}") # 5.252.33.202
return ip
except:
return None
Код:
# Парсинг полученных данных
def parse_server_info(self, data):
if len(data) > 11:
offset = 11
passworded = data[offset] == 1
players = struct.unpack('<H', data[offset+1:offset+3])[0]
max_players = struct.unpack('<H', data[offset+3:offset+5])[0]
# Чтение hostname
hostname_len = struct.unpack('<I', data[offset+5:offset+9])[0]
hostname = data[offset+9:offset+9+hostname_len].decode('latin-1')
return {
'players': players,
'max_players': max_players,
'hostname': hostname
}
return None