Ir al contenido
GProxy
Registro
Гайды 8 min de lectura 33 vistas

Uso de Proxies en Ruby

Esta guía explora la integración de proxies en aplicaciones Ruby usando Net::HTTP y Mechanize. Aprenda a configurar y aprovechar proxies para operaciones web seguras y anónimas.

Uso de Proxies en Ruby

En Ruby, Net::HTTP y Mechanize facilitan el uso de proxies al permitir la configuración directa del host, puerto y credenciales de autenticación del proxy durante la inicialización del objeto o el establecimiento de la conexión. Estas bibliotecas permiten que las aplicaciones Ruby enruten las solicitudes de red a través de servidores proxy intermediarios, soportando casos de uso como la rotación de IP, la orientación geográfica y la elusión de límites de tasa.

Configuración de Proxy con Net::HTTP

Net::HTTP es la biblioteca estándar de Ruby para realizar solicitudes HTTP. Proporciona control directo sobre los parámetros de conexión, incluyendo la configuración del proxy.

Parámetros Directos del Proxy

Para configurar un proxy para una solicitud Net::HTTP, especifique el host, puerto, nombre de usuario y contraseña del proxy al crear el objeto Net::HTTP o al iniciar la conexión.

require 'net/http'
require 'uri'

# Detalles del proxy
proxy_host = 'your_proxy_host.com'
proxy_port = 8080
proxy_user = 'proxy_username'
proxy_pass = 'proxy_password'

# URL de destino
uri = URI('http://example.com/data')

# Método 1: Especificar parámetros del proxy en Net::HTTP.new
http = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port, proxy_user, proxy_pass)
http.use_ssl = (uri.scheme == 'https') # Requerido para HTTPS

request = Net::HTTP::Get.new(uri.request_uri)

begin
  response = http.request(request)
  puts "Method 1 Response Status: #{response.code}"
  # puts response.body
rescue Net::HTTPClientException => e
  puts "HTTP Error: #{e.message}"
rescue Net::ReadTimeout, Net::OpenTimeout => e
  puts "Timeout Error: #{e.message}"
rescue StandardError => e
  puts "An error occurred: #{e.message}"
ensure
  http.finish if http.started? # Asegura que la conexión se cierre
end

# Método 2: Especificar parámetros del proxy en el bloque Net::HTTP.start
uri_https = URI('https://api.ipify.org?format=json') # Un endpoint simple para verificar la IP

Net::HTTP.start(uri_https.host, uri_https.port,
                proxy_host, proxy_port, proxy_user, proxy_pass,
                use_ssl: uri_https.scheme == 'https') do |http_with_proxy|

  request_https = Net::HTTP::Get.new(uri_https.request_uri)
  response_https = http_with_proxy.request(request_https)
  puts "Method 2 Response Status: #{response_https.code}"
  puts "External IP via proxy: #{response_https.body}" # Debería mostrar la IP del proxy
rescue Net::HTTPClientException => e
  puts "HTTP Error: #{e.message}"
rescue Net::ReadTimeout, Net::OpenTimeout => e
  puts "Timeout Error: #{e.message}"
rescue StandardError => e
  puts "An error occurred: #{e.message}"
end

Variables de Entorno

Net::HTTP puede detectar automáticamente la configuración del proxy a partir de variables de entorno. Este enfoque es adecuado para la configuración de proxy a nivel de sistema o de aplicación sin modificar el código.

  • http_proxy: Para solicitudes HTTP (ej., http://user:pass@proxy.example.com:8080)
  • https_proxy: Para solicitudes HTTPS (ej., https://user:pass@proxy.example.com:8080)
  • no_proxy: Una lista de nombres de host separados por comas que deben omitir el proxy.
require 'net/http'
require 'uri'

# Establecer variables de entorno (ejemplo, típicamente se hace fuera del script)
# ENV['http_proxy'] = 'http://proxy_username:proxy_password@your_proxy_host.com:8080'
# ENV['https_proxy'] = 'http://proxy_username:proxy_password@your_proxy_host.com:8080' # Nota: https_proxy también puede ser un proxy http
# ENV['no_proxy'] = 'localhost,127.0.0.1'

uri = URI('http://example.com/data')
http = Net::HTTP.new(uri.host, uri.port) # Sin parámetros de proxy explícitos
request = Net::HTTP::Get.new(uri.request_uri)

# Si http_proxy/https_proxy están configurados, Net::HTTP los usará.
begin
  response = http.request(request)
  puts "Env Var Response Status: #{response.code}"
rescue StandardError => e
  puts "An error occurred: #{e.message}"
end

# Limpiar variables de entorno después de usarlas si se configuraron programáticamente
# ENV.delete('http_proxy')
# ENV.delete('https_proxy')

Configuración de Proxy con Mechanize

Mechanize es una gema de Ruby que simplifica el web scraping emulando un navegador web. Se basa en Net::HTTP y ofrece una API de nivel superior para manejar proxies.

Parámetros Directos del Proxy

Mechanize permite configurar los detalles del proxy durante la inicialización del agente o llamando al método set_proxy.

require 'mechanize'

# Detalles del proxy
proxy_host = 'your_proxy_host.com'
proxy_port = 8080
proxy_user = 'proxy_username'
proxy_pass = 'proxy_password'

# Método 1: Inicializar Mechanize con parámetros de proxy
agent = Mechanize.new do |a|
  a.set_proxy(proxy_host, proxy_port, proxy_user, proxy_pass)
  a.user_agent_alias = 'Mac Safari' # Recomendado para web scraping
end

begin
  page = agent.get('http://example.com/')
  puts "Method 1 Mechanize Page Title: #{page.title}"
rescue Mechanize::ResponseCodeError => e
  puts "Mechanize HTTP Error: #{e.response_code} - #{e.page.uri}"
rescue Mechanize::Error => e
  puts "Mechanize Error: #{e.message}"
rescue StandardError => e
  puts "An error occurred: #{e.message}"
end

# Método 2: Pasar parámetros de proxy directamente a Mechanize.new (más simple para una sola vez)
agent_direct = Mechanize.new(proxy_addr: proxy_host,
                             proxy_port: proxy_port,
                             proxy_user: proxy_user,
                             proxy_pass: proxy_pass)
agent_direct.user_agent_alias = 'Linux Firefox'

begin
  page_direct = agent_direct.get('https://api.ipify.org?format=json')
  puts "Method 2 Mechanize External IP via proxy: #{page_direct.body}"
rescue Mechanize::ResponseCodeError => e
  puts "Mechanize HTTP Error: #{e.response_code} - #{e.page.uri}"
rescue Mechanize::Error => e
  puts "Mechanize Error: #{e.message}"
rescue StandardError => e
  puts "An error occurred: #{e.message}"
end

Rotación de Proxy con Mechanize

Para escenarios que requieren cambios frecuentes de IP, como la recopilación de datos a gran escala, la rotación de proxy es esencial. El método set_proxy de Mechanize se puede llamar varias veces para cambiar el proxy durante el ciclo de vida de un agente.

require 'mechanize'

proxies = [
  { host: 'proxy1.example.com', port: 8080, user: 'user1', pass: 'pass1' },
  { host: 'proxy2.example.com', port: 8080, user: 'user2', pass: 'pass2' },
  # ... más proxies
]

agent = Mechanize.new
agent.user_agent_alias = 'Windows Chrome'

proxies.each_with_index do |p, i|
  puts "Using proxy #{i+1}: #{p[:host]}"
  agent.set_proxy(p[:host], p[:port], p[:user], p[:pass])
  begin
    page = agent.get('https://api.ipify.org?format=json')
    puts "Current IP: #{page.body.strip}"
    sleep(2) # Pausa para evitar saturar el objetivo
  rescue Mechanize::ResponseCodeError => e
    puts "Error with proxy #{p[:host]}: #{e.response_code}"
  rescue Mechanize::Error, StandardError => e
    puts "Connection error with proxy #{p[:host]}: #{e.message}"
  end
end

Comparación: Net::HTTP vs. Mechanize para Proxies

Característica Net::HTTP Mechanize
Nivel de Abstracción Cliente HTTP de bajo nivel. Control directo del socket. Biblioteca de web scraping de alto nivel. Emula navegador.
Configuración de Proxy Argumentos del constructor o Net::HTTP.start. Método set_proxy u opciones de Mechanize.new.
Facilidad de Uso Más verboso para tareas complejas. Más simple para navegar sitios web, envío de formularios.
Características Automáticas Ninguna más allá de HTTP básico. Manejo de cookies, redirecciones, interpretación de JavaScript (limitada), gestión de user-agent.
Manejo de Errores Excepciones de Net::HTTP (ej., Net::OpenTimeout). Mechanize::Error, Mechanize::ResponseCodeError.
Mejor para Llamadas API simples, solicitudes HTTP/S específicas. Web scraping, automatización de navegador, navegación compleja.
Dependencia Biblioteca estándar. Gema (mechanize).

Tipos y Limitaciones de Proxy

Net::HTTP (y por extensión Mechanize) soporta principalmente tipos de proxy HTTP y HTTPS. Estos proxies reenvían solicitudes HTTP/HTTPS.

  • Proxies HTTP: Utilizados para tráfico HTTP no cifrado.
  • Proxies HTTPS (CONNECT): Utilizados para tráfico HTTPS cifrado. Net::HTTP establece un túnel CONNECT a través del proxy hacia el host de destino.
  • Proxies SOCKS: Net::HTTP no soporta nativamente proxies SOCKS (SOCKS4, SOCKS5). Para usar proxies SOCKS en Ruby, se requiere una gema externa como socks-ruby. Esta gema puede integrarse con Net::HTTP sobrescribiendo su creación de socket.
# Ejemplo de uso de proxy SOCKS con socks-ruby (requiere la gema 'socks-ruby')
# gem install socks-ruby
require 'net/http'
require 'socks-ruby'
require 'uri'

socks_proxy_host = 'your_socks_proxy.com'
socks_proxy_port = 1080
socks_proxy_user = 'socks_user'
socks_proxy_pass = 'socks_pass'

uri = URI('https://api.ipify.org?format=json')

# Sobrescribir la creación de socket de Net::HTTP
Net::HTTP.class_eval do
  def connect
    if proxy_address
      # Lógica existente de proxy HTTP/HTTPS
      super
    elsif ENV['SOCKS_PROXY'] # Variable de entorno personalizada para SOCKS
      socks_uri = URI(ENV['SOCKS_PROXY'])
      socks_socket = Socks::HTTP.new(socks_uri.host, socks_uri.port,
                                     socks_uri.user, socks_uri.password)
      @socket = socks_socket.connect(@address, @port)
      @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
      if use_ssl?
        @socket = Net::HTTP::SSL_SOCKET_CLASS.new(@socket, read_timeout: @read_timeout)
        @socket.sync_close = true
        @socket.connect
      end
    else
      super
    end
  end
end

# Establecer una variable de entorno personalizada para el proxy SOCKS
ENV['SOCKS_PROXY'] = "socks5://#{socks_proxy_user}:#{socks_proxy_pass}@#{socks_proxy_host}:#{socks_proxy_port}"

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true # Esencial para HTTPS
http.verify_mode = OpenSSL::SSL::VERIFY_PEER # Recomendado por seguridad

request = Net::HTTP::Get.new(uri.request_uri)

begin
  response = http.request(request)
  puts "SOCKS Proxy Response Status: #{response.code}"
  puts "External IP via SOCKS proxy: #{response.body}"
rescue StandardError => e
  puts "SOCKS Proxy Error: #{e.message}"
end

ENV.delete('SOCKS_PROXY') # Limpiar

Manejo de Errores y Tiempos de Espera

Al usar proxies, los problemas de red, las configuraciones incorrectas del proxy o las fallas del servidor proxy son comunes. Un manejo robusto de errores es crucial.

Errores Comunes

  • Net::OpenTimeout: La conexión al proxy o al servidor de destino agotó el tiempo de espera antes de establecerse.
  • Net::ReadTimeout: El servidor (proxy o destino) no envió datos dentro del período de tiempo de espera especificado.
  • Errno::ECONNREFUSED: El servidor proxy rechazó activamente la conexión.
  • Net::HTTPBadResponse: El servidor proxy o el destino devolvieron una respuesta HTTP no válida.
  • Mechanize::ResponseCodeError: Error específico de Mechanize cuando el servidor de destino devuelve un código de estado HTTP que no es 2xx (ej., 403 Forbidden, 404 Not Found, 500 Internal Server Error).

Configuración de Tiempos de Espera

Establecer tiempos de espera apropiados evita que los scripts se queden colgados indefinidamente.

require 'net/http'
require 'uri'

uri = URI('http://slow-api.example.com')
proxy_host = 'your_proxy_host.com'
proxy_port = 8080

http = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port)
http.open_timeout = 5 # Tiempo de espera para establecer la conexión (segundos)
http.read_timeout = 10 # Tiempo de espera para leer datos de la conexión (segundos)
http.use_ssl = (uri.scheme == 'https')

request = Net::HTTP::Get.new(uri.request_uri)

begin
  response = http.request(request)
  puts "Response Status: #{response.code}"
rescue Net::OpenTimeout
  puts "Connection to proxy or target timed out."
rescue Net::ReadTimeout
  puts "Reading data from proxy or target timed out."
rescue Errno::ECONNREFUSED
  puts "Connection refused by proxy or target server."
rescue StandardError => e
  puts "An unexpected error occurred: #{e.message}"
end

# Mechanize también soporta tiempos de espera
# agent = Mechanize.new
# agent.set_proxy(proxy_host, proxy_port)
# agent.open_timeout = 5
# agent.read_timeout = 10

Mejores Prácticas

  • Cadenas de User-Agent: Al hacer scraping, siempre establezca un encabezado User-Agent realista. Muchos sitios web bloquean solicitudes sin uno o con unos genéricos. user_agent_alias de Mechanize simplifica esto.
  • Encabezados Referer: Para algunos sitios, un encabezado Referer válido es necesario para imitar el comportamiento legítimo del navegador.
  • Gestión de Cookies: Mechanize maneja las cookies automáticamente, lo cual es crucial para mantener sesiones a través de un proxy. Con Net::HTTP, se requiere una gestión manual de cookies.
  • Manejo de Errores y Reintentos: Implemente lógica de reintento con retroceso exponencial para errores de red transitorios o problemas de proxy.
  • Comprobaciones de Salud del Proxy: Antes de usar un proxy, considere una verificación rápida contra un endpoint conocido (ej., https://api.ipify.org) para verificar su funcionalidad y dirección IP.
  • Gestión de Recursos: Asegúrese de que las conexiones Net::HTTP se cierren correctamente, especialmente cuando no se usa el bloque start, para evitar fugas de recursos. Mechanize gestiona las conexiones internamente.
Actualizado: 03.03.2026
Volver a la categoría

Pruebe nuestros proxies

20,000+ proxies en 100+ países del mundo

support_agent
GProxy Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.