Pular para o conteúdo
Guides 8 min de leitura 971 visualizações

Usando proxies em Ruby

Este guia mostra como integrar proxies em aplicações Ruby usando Net::HTTP e Mechanize. Aprenda a configurar e aproveitar proxies para operações web seguras e anônimas.

Usando proxies em Ruby

Em Ruby, Net::HTTP e Mechanize facilitam o uso de proxies ao permitirem a configuração direta de host, porta e credenciais de autenticação do proxy durante a inicialização do objeto ou no estabelecimento da conexão. Essas bibliotecas permitem que aplicações Ruby roteiem requisições de rede através de servidores proxy intermediários, atendendo casos de uso como rotação de IP, geo-targeting e contorno de rate limits.

Configuração de proxy no Net::HTTP

Net::HTTP é a biblioteca padrão do Ruby para fazer requisições HTTP. Ela oferece controle direto sobre os parâmetros de conexão, incluindo as configurações de proxy.

Parâmetros diretos de proxy

Para configurar um proxy em uma requisição Net::HTTP, informe host, porta, usuário e senha do proxy ao criar o objeto Net::HTTP ou ao iniciar a conexão.

require 'net/http'
require 'uri'

# Dados do 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: informar os parâmetros do proxy em 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') # Necessário 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? # Garante que a conexão seja fechada
end

# Método 2: informar os parâmetros do proxy no bloco Net::HTTP.start
uri_https = URI('https://httpbin.org/ip') # Endpoint simples para verificar o 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}" # Deve mostrar o IP do 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

Variáveis de ambiente

Net::HTTP consegue detectar automaticamente as configurações de proxy a partir de variáveis de ambiente. Essa abordagem serve para configurar o proxy em todo o sistema ou em toda a aplicação sem alterar o código.

  • http_proxy: para requisições HTTP (ex.: http://user:[email protected]:8080)
  • https_proxy: para requisições HTTPS (ex.: https://user:[email protected]:8080)
  • no_proxy: lista separada por vírgulas de hostnames que devem ignorar o proxy.
require 'net/http'
require 'uri'

# Define as variáveis de ambiente (exemplo; normalmente feito fora do 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' # Obs.: https_proxy também pode ser um proxy http
# ENV['no_proxy'] = 'localhost,127.0.0.1'

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

# Se http_proxy/https_proxy estiverem definidas, Net::HTTP vai usá-las.
begin
  response = http.request(request)
  puts "Env Var Response Status: #{response.code}"
rescue StandardError => e
  puts "An error occurred: #{e.message}"
end

# Limpe as variáveis de ambiente depois do uso, se definidas via código
# ENV.delete('http_proxy')
# ENV.delete('https_proxy')

Configuração de proxy no Mechanize

Mechanize é uma gem Ruby que simplifica o web scraping emulando um navegador. Ela é construída sobre Net::HTTP e oferece uma API de nível mais alto para lidar com proxies.

Parâmetros diretos de proxy

O Mechanize permite definir os dados do proxy durante a inicialização do agente ou chamando o método set_proxy.

require 'mechanize'

# Dados do proxy
proxy_host = 'your_proxy_host.com'
proxy_port = 8080
proxy_user = 'proxy_username'
proxy_pass = 'proxy_password'

# Método 1: inicializar o Mechanize com os parâmetros do 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: passar os parâmetros do proxy direto para Mechanize.new (mais simples para uso pontual)
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://httpbin.org/ip')
  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

Rotação de proxies com Mechanize

Em cenários que exigem troca frequente de IP, como coleta de dados em larga escala, a rotação de proxies é essencial. O método set_proxy do Mechanize pode ser chamado várias vezes para trocar o proxy ao longo do ciclo de vida do agente.

require 'mechanize'

proxies = [
  { host: 'proxy1.example.com', port: 8080, user: 'user1', pass: 'pass1' },
  { host: 'proxy2.example.com', port: 8080, user: 'user2', pass: 'pass2' },
  # ... mais 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://httpbin.org/ip')
    puts "Current IP: #{page.body.strip}"
    sleep(2) # Pausa para não sobrecarregar o alvo
  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

Comparação: Net::HTTP vs. Mechanize para proxies

Característica Net::HTTP Mechanize
Nível de abstração Cliente HTTP de baixo nível. Controle direto do socket. Biblioteca de web scraping de alto nível. Emula um navegador.
Configuração de proxy Argumentos do construtor ou Net::HTTP.start. Método set_proxy ou opções de Mechanize.new.
Facilidade de uso Mais verboso em tarefas complexas. Mais simples para navegar em sites e enviar formulários.
Recursos automáticos Nada além do HTTP básico. Gerenciamento de cookies, redirecionamentos, interpretação de JavaScript (limitada), gestão de user-agent.
Tratamento de erros Exceções de Net::HTTP (ex.: Net::OpenTimeout). Mechanize::Error, Mechanize::ResponseCodeError.
Melhor para Chamadas de API simples, requisições HTTP/S específicas. Web scraping, automação de navegador, navegação complexa.
Dependência Biblioteca padrão. Gem (mechanize).

Tipos de proxy e limitações

Net::HTTP (e, por extensão, o Mechanize) suporta principalmente proxies dos tipos HTTP e HTTPS. Esses proxies encaminham requisições HTTP/HTTPS.

  • Proxies HTTP: usados para tráfego HTTP não criptografado.
  • Proxies HTTPS (CONNECT): usados para tráfego HTTPS criptografado. O Net::HTTP estabelece um túnel CONNECT através do proxy até o host de destino.
  • Proxies SOCKS: Net::HTTP não suporta proxies SOCKS (SOCKS4, SOCKS5) de forma nativa. Para usar proxies SOCKS em Ruby, é necessária uma gem externa como socks-ruby. Essa gem se integra ao Net::HTTP sobrescrevendo a criação do socket.
# Exemplo de uso de proxy SOCKS com socks-ruby (requer a gem '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://httpbin.org/ip')

# Sobrescreve a criação do socket do Net::HTTP
Net::HTTP.class_eval do
  def connect
    if proxy_address
      # Lógica existente de proxy HTTP/HTTPS
      super
    elsif ENV['SOCKS_PROXY'] # Variável de ambiente 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

# Define uma variável de ambiente personalizada para o 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 # Essencial para HTTPS
http.verify_mode = OpenSSL::SSL::VERIFY_PEER # Recomendado por segurança

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') # Limpeza

Tratamento de erros e timeouts

Ao usar proxies, problemas de rede, configurações incorretas do proxy ou falhas do servidor proxy são comuns. Um tratamento de erros robusto é fundamental.

Erros comuns

  • Net::OpenTimeout: a conexão com o proxy ou com o servidor de destino expirou antes de ser estabelecida.
  • Net::ReadTimeout: o servidor (proxy ou destino) não enviou dados dentro do tempo limite especificado.
  • Errno::ECONNREFUSED: o servidor proxy recusou ativamente a conexão.
  • Net::HTTPBadResponse: o servidor proxy ou o destino retornou uma resposta HTTP inválida.
  • Mechanize::ResponseCodeError: erro específico do Mechanize quando o servidor de destino retorna um código de status HTTP que não seja 2xx (ex.: 403 Forbidden, 404 Not Found, 500 Internal Server Error).

Configuração de timeouts

Definir timeouts adequados evita que os scripts fiquem travados 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 # Timeout para estabelecer a conexão (segundos)
http.read_timeout = 10 # Timeout para leitura de dados da conexão (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

# O Mechanize também suporta timeouts
# agent = Mechanize.new
# agent.set_proxy(proxy_host, proxy_port)
# agent.open_timeout = 5
# agent.read_timeout = 10

Boas práticas

  • Strings de User-Agent: ao fazer scraping, sempre defina um cabeçalho User-Agent realista. Muitos sites bloqueiam requisições sem ele ou com valores genéricos. O user_agent_alias do Mechanize simplifica isso.
  • Cabeçalhos Referer: em alguns sites, um cabeçalho Referer válido é necessário para imitar o comportamento de um navegador legítimo.
  • Gerenciamento de cookies: o Mechanize trata cookies automaticamente, o que é essencial para manter sessões através de um proxy. Com Net::HTTP, o gerenciamento manual de cookies é necessário.
  • Tratamento de erros e retentativas: implemente lógica de retry com backoff exponencial para erros de rede transitórios ou problemas do proxy.
  • Verificação de saúde dos proxies: antes de usar um proxy, considere um teste rápido contra um endpoint conhecido (ex.: https://api.ipify.org) para verificar seu funcionamento e o endereço IP.
  • Gerenciamento de recursos: garanta que as conexões Net::HTTP sejam fechadas corretamente, principalmente quando não estiver usando o bloco start, para evitar vazamento de recursos. O Mechanize gerencia as conexões internamente.
Atualizado: 03.03.2026
Voltar à categoria

Leia também

Experimente nossos proxies

20,000+ proxies em 100+ países do mundo

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