In Ruby erleichtern Net::HTTP und Mechanize die Proxy-Nutzung, indem sie die direkte Konfiguration von Proxy-Host, -Port und Authentifizierungsdaten während der Objektinitialisierung oder des Verbindungsaufbaus ermöglichen. Diese Bibliotheken erlauben Ruby-Anwendungen, Netzwerkanfragen über zwischengeschaltete Proxy-Server zu leiten, was Anwendungsfälle wie IP-Rotation, Geo-Targeting und die Umgehung von Ratenbegrenzungen unterstützt.
Net::HTTP Proxy-Konfiguration
Net::HTTP ist Rubys Standardbibliothek für HTTP-Anfragen. Sie bietet direkte Kontrolle über Verbindungsparameter, einschließlich Proxy-Einstellungen.
Direkte Proxy-Parameter
Um einen Proxy für eine Net::HTTP-Anfrage zu konfigurieren, geben Sie den Proxy-Host, -Port, -Benutzernamen und das -Passwort beim Erstellen des Net::HTTP-Objekts oder beim Starten der Verbindung an.
require 'net/http'
require 'uri'
# Proxy details
proxy_host = 'your_proxy_host.com'
proxy_port = 8080
proxy_user = 'proxy_username'
proxy_pass = 'proxy_password'
# Target URL
uri = URI('http://example.com/data')
# Method 1: Specify proxy parameters in 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') # Required for 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? # Ensure connection is closed
end
# Method 2: Specify proxy parameters in Net::HTTP.start block
uri_https = URI('https://api.ipify.org?format=json') # A simple endpoint to check 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}" # Should show proxy's IP
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
Umgebungsvariablen
Net::HTTP kann Proxy-Einstellungen automatisch aus Umgebungsvariablen erkennen. Dieser Ansatz eignet sich für systemweite oder anwendungsweite Proxy-Konfigurationen, ohne den Code ändern zu müssen.
http_proxy: Für HTTP-Anfragen (z.B.http://user:pass@proxy.example.com:8080)https_proxy: Für HTTPS-Anfragen (z.B.https://user:pass@proxy.example.com:8080)no_proxy: Eine durch Kommas getrennte Liste von Hostnamen, die den Proxy umgehen sollen.
require 'net/http'
require 'uri'
# Set environment variables (example, typically done outside the 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' # Note: https_proxy can also be an http proxy
# ENV['no_proxy'] = 'localhost,127.0.0.1'
uri = URI('http://example.com/data')
http = Net::HTTP.new(uri.host, uri.port) # No explicit proxy parameters
request = Net::HTTP::Get.new(uri.request_uri)
# If http_proxy/https_proxy are set, Net::HTTP will use them.
begin
response = http.request(request)
puts "Env Var Response Status: #{response.code}"
rescue StandardError => e
puts "An error occurred: #{e.message}"
end
# Clear environment variables after use if set programmatically
# ENV.delete('http_proxy')
# ENV.delete('https_proxy')
Mechanize Proxy-Konfiguration
Mechanize ist ein Ruby-Gem, das das Web-Scraping durch die Emulation eines Webbrowsers vereinfacht. Es baut auf Net::HTTP auf und bietet eine höhere API-Ebene für die Handhabung von Proxys.
Direkte Proxy-Parameter
Mechanize ermöglicht das Festlegen von Proxy-Details während der Agenteninitialisierung oder durch Aufrufen der Methode set_proxy.
require 'mechanize'
# Proxy details
proxy_host = 'your_proxy_host.com'
proxy_port = 8080
proxy_user = 'proxy_username'
proxy_pass = 'proxy_password'
# Method 1: Initialize Mechanize with proxy parameters
agent = Mechanize.new do |a|
a.set_proxy(proxy_host, proxy_port, proxy_user, proxy_pass)
a.user_agent_alias = 'Mac Safari' # Recommended for 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
# Method 2: Pass proxy parameters directly to Mechanize.new (simpler for one-off)
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
Proxy-Rotation mit Mechanize
Für Szenarien, die häufige IP-Änderungen erfordern, wie z.B. die groß angelegte Datenerfassung, ist die Proxy-Rotation unerlässlich. Die set_proxy-Methode von Mechanize kann mehrmals aufgerufen werden, um den Proxy während des Lebenszyklus eines Agenten zu ändern.
require 'mechanize'
proxies = [
{ host: 'proxy1.example.com', port: 8080, user: 'user1', pass: 'pass1' },
{ host: 'proxy2.example.com', port: 8080, user: 'user2', pass: 'pass2' },
# ... more 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) # Pause to avoid overwhelming the target
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
Vergleich: Net::HTTP vs. Mechanize für Proxys
| Feature | Net::HTTP | Mechanize |
|---|---|---|
| Abstraktionsebene | Low-Level HTTP-Client. Direkte Socket-Kontrolle. | High-Level Web-Scraping-Bibliothek. Emuliert Browser. |
| Proxy-Konfiguration | Konstruktorargumente oder Net::HTTP.start. |
set_proxy-Methode oder Mechanize.new-Optionen. |
| Benutzerfreundlichkeit | Ausführlicher für komplexe Aufgaben. | Einfacher für Website-Navigation, Formularübermittlung. |
| Automatische Funktionen | Keine über grundlegendes HTTP hinaus. | Cookie-Behandlung, Weiterleitungen, JavaScript-Interpretation (begrenzt), User-Agent-Verwaltung. |
| Fehlerbehandlung | Net::HTTP-Ausnahmen (z.B. Net::OpenTimeout). |
Mechanize::Error, Mechanize::ResponseCodeError. |
| Am besten für | Einfache API-Aufrufe, spezifische HTTP/S-Anfragen. | Web-Scraping, Browser-Automatisierung, komplexe Navigation. |
| Abhängigkeit | Standardbibliothek. | Gem (mechanize). |
Proxy-Typen und Einschränkungen
Net::HTTP (und damit Mechanize) unterstützt hauptsächlich HTTP- und HTTPS-Proxy-Typen. Diese Proxys leiten HTTP/HTTPS-Anfragen weiter.
- HTTP-Proxys: Werden für unverschlüsselten HTTP-Verkehr verwendet.
- HTTPS-Proxys (CONNECT): Werden für verschlüsselten HTTPS-Verkehr verwendet.
Net::HTTPstellt einenCONNECT-Tunnel über den Proxy zum Zielhost her. - SOCKS-Proxys:
Net::HTTPunterstützt SOCKS-Proxys (SOCKS4, SOCKS5) nicht nativ. Um SOCKS-Proxys in Ruby zu verwenden, ist ein externes Gem wiesocks-rubyerforderlich. Dieses Gem kann durch Überschreiben der Socket-Erstellung inNet::HTTPintegriert werden.
# Example of SOCKS proxy usage with socks-ruby (requires 'socks-ruby' gem)
# 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')
# Override Net::HTTP's socket creation
Net::HTTP.class_eval do
def connect
if proxy_address
# Existing HTTP/HTTPS proxy logic
super
elsif ENV['SOCKS_PROXY'] # Custom environment variable for 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
# Set a custom environment variable for SOCKS proxy
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 # Essential for HTTPS
http.verify_mode = OpenSSL::SSL::VERIFY_PEER # Recommended for security
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') # Clean up
Fehlerbehandlung und Timeouts
Bei der Verwendung von Proxys sind Netzwerkprobleme, Fehlkonfigurationen des Proxys oder Ausfälle des Proxy-Servers häufig. Eine robuste Fehlerbehandlung ist entscheidend.
Häufige Fehler
Net::OpenTimeout: Die Verbindung zum Proxy oder Zielserver wurde nicht innerhalb des Zeitlimits hergestellt.Net::ReadTimeout: Der Server (Proxy oder Ziel) hat innerhalb des angegebenen Zeitlimits keine Daten gesendet.Errno::ECONNREFUSED: Der Proxy-Server hat die Verbindung aktiv verweigert.Net::HTTPBadResponse: Der Proxy-Server oder das Ziel hat eine ungültige HTTP-Antwort zurückgegeben.Mechanize::ResponseCodeError: Mechanize-spezifischer Fehler, wenn der Zielserver einen HTTP-Statuscode ungleich 2xx zurückgibt (z.B. 403 Forbidden, 404 Not Found, 500 Internal Server Error).
Timeout-Konfiguration
Das Festlegen geeigneter Timeouts verhindert, dass Skripte unbegrenzt hängen bleiben.
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 for establishing the connection (seconds)
http.read_timeout = 10 # Timeout for reading data from the connection (seconds)
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 also supports timeouts
# agent = Mechanize.new
# agent.set_proxy(proxy_host, proxy_port)
# agent.open_timeout = 5
# agent.read_timeout = 10
Best Practices
- User-Agent-Strings: Beim Scraping sollte immer ein realistischer
User-Agent-Header gesetzt werden. Viele Websites blockieren Anfragen ohne oder mit generischen User-Agents.user_agent_aliasvon Mechanize vereinfacht dies. - Referer-Header: Für einige Websites ist ein gültiger
Referer-Header notwendig, um legitimes Browserverhalten zu imitieren. - Cookie-Management: Mechanize handhabt Cookies automatisch, was entscheidend ist, um Sitzungen über einen Proxy aufrechtzuerhalten. Mit
Net::HTTPist ein manuelles Cookie-Management erforderlich. - Fehlerbehandlung und Wiederholungen: Implementieren Sie eine Wiederholungslogik mit exponentiellem Backoff für vorübergehende Netzwerkfehler oder Proxy-Probleme.
- Proxy-Gesundheitsprüfungen: Vor der Verwendung eines Proxys sollte eine schnelle Überprüfung gegen einen bekannten Endpunkt (z.B.
https://api.ipify.org) in Betracht gezogen werden, um dessen Funktionalität und IP-Adresse zu verifizieren. - Ressourcenmanagement: Stellen Sie sicher, dass
Net::HTTP-Verbindungen ordnungsgemäß geschlossen werden, insbesondere wenn derstart-Block nicht verwendet wird, um Ressourcenlecks zu vermeiden. Mechanize verwaltet Verbindungen intern.