Ruby'de Net::HTTP ve Mechanize, nesne oluşturulurken veya bağlantı kurulurken proxy host, port ve kimlik doğrulama bilgilerinin doğrudan yapılandırılmasına izin vererek proxy kullanımını kolaylaştırır. Bu kütüphaneler, Ruby uygulamalarının ağ isteklerini aracı proxy sunucular üzerinden yönlendirmesini sağlar; böylece IP rotasyonu, geo-targeting ve rate limit aşma gibi senaryolar desteklenir.
Net::HTTP proxy yapılandırması
Net::HTTP, Ruby'nin HTTP istekleri için standart kütüphanesidir. Proxy ayarları dahil olmak üzere bağlantı parametreleri üzerinde doğrudan kontrol sunar.
Doğrudan proxy parametreleri
Bir Net::HTTP isteği için proxy yapılandırmak üzere, Net::HTTP nesnesini oluştururken veya bağlantıyı başlatırken proxy host, port, kullanıcı adı ve parolayı belirtin.
require 'net/http'
require 'uri'
# Proxy bilgileri
proxy_host = 'your_proxy_host.com'
proxy_port = 8080
proxy_user = 'proxy_username'
proxy_pass = 'proxy_password'
# Hedef URL
uri = URI('http://example.com/data')
# Yöntem 1: proxy parametrelerini Net::HTTP.new içinde belirtin
http = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port, proxy_user, proxy_pass)
http.use_ssl = (uri.scheme == 'https') # HTTPS için gerekli
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? # Bağlantının kapatıldığından emin olun
end
# Yöntem 2: proxy parametrelerini Net::HTTP.start bloğunda belirtin
uri_https = URI('https://httpbin.org/ip') # IP kontrolü için basit bir endpoint
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}" # Proxy'nin IP'sini göstermeli
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
Ortam değişkenleri
Net::HTTP, proxy ayarlarını ortam değişkenlerinden otomatik olarak algılayabilir. Bu yaklaşım, kodu değiştirmeden sistem geneli veya uygulama geneli proxy yapılandırması için uygundur.
http_proxy: HTTP istekleri için (örn.http://user:[email protected]:8080)https_proxy: HTTPS istekleri için (örn.https://user:[email protected]:8080)no_proxy: proxy'yi atlaması gereken host adlarının virgülle ayrılmış listesi.
require 'net/http'
require 'uri'
# Ortam değişkenlerini ayarlayın (örnek; genellikle betiğin dışında yapılır)
# 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' # Not: https_proxy bir http proxy de olabilir
# ENV['no_proxy'] = 'localhost,127.0.0.1'
uri = URI('http://example.com/data')
http = Net::HTTP.new(uri.host, uri.port) # Açık proxy parametresi yok
request = Net::HTTP::Get.new(uri.request_uri)
# http_proxy/https_proxy tanımlıysa Net::HTTP bunları kullanır.
begin
response = http.request(request)
puts "Env Var Response Status: #{response.code}"
rescue StandardError => e
puts "An error occurred: #{e.message}"
end
# Programatik olarak ayarlandıysa kullanımdan sonra ortam değişkenlerini temizleyin
# ENV.delete('http_proxy')
# ENV.delete('https_proxy')
Mechanize proxy yapılandırması
Mechanize, bir web tarayıcısını taklit ederek web scraping'i basitleştiren bir Ruby gem'idir. Net::HTTP üzerine kuruludur ve proxy yönetimi için daha üst seviye bir API sunar.
Doğrudan proxy parametreleri
Mechanize, proxy bilgilerinin agent oluşturulurken veya set_proxy metodu çağrılarak ayarlanmasına izin verir.
require 'mechanize'
# Proxy bilgileri
proxy_host = 'your_proxy_host.com'
proxy_port = 8080
proxy_user = 'proxy_username'
proxy_pass = 'proxy_password'
# Yöntem 1: Mechanize'ı proxy parametreleriyle başlatın
agent = Mechanize.new do |a|
a.set_proxy(proxy_host, proxy_port, proxy_user, proxy_pass)
a.user_agent_alias = 'Mac Safari' # Web scraping için önerilir
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
# Yöntem 2: proxy parametrelerini doğrudan Mechanize.new'e geçirin (tek seferlik kullanım için daha basit)
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
Mechanize ile proxy rotasyonu
Büyük ölçekli veri toplama gibi sık IP değişimi gerektiren senaryolarda proxy rotasyonu şarttır. Mechanize'ın set_proxy metodu, agent'ın yaşam döngüsü boyunca proxy'yi değiştirmek için birden çok kez çağrılabilir.
require 'mechanize'
proxies = [
{ host: 'proxy1.example.com', port: 8080, user: 'user1', pass: 'pass1' },
{ host: 'proxy2.example.com', port: 8080, user: 'user2', pass: 'pass2' },
# ... daha fazla proxy
]
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) # Hedefi aşırı yüklememek için bekleyin
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
Karşılaştırma: proxy için Net::HTTP ve Mechanize
| Özellik | Net::HTTP | Mechanize |
|---|---|---|
| Soyutlama seviyesi | Düşük seviyeli HTTP istemcisi. Doğrudan socket kontrolü. | Üst seviyeli web scraping kütüphanesi. Tarayıcıyı taklit eder. |
| Proxy yapılandırması | Constructor argümanları veya Net::HTTP.start. |
set_proxy metodu veya Mechanize.new seçenekleri. |
| Kullanım kolaylığı | Karmaşık görevlerde daha fazla kod gerektirir. | Sitelerde gezinme ve form gönderme için daha basit. |
| Otomatik özellikler | Temel HTTP dışında yok. | Cookie yönetimi, yönlendirmeler, JavaScript yorumlama (sınırlı), user-agent yönetimi. |
| Hata yönetimi | Net::HTTP istisnaları (örn. Net::OpenTimeout). |
Mechanize::Error, Mechanize::ResponseCodeError. |
| En uygun kullanım | Basit API çağrıları, belirli HTTP/S istekleri. | Web scraping, tarayıcı otomasyonu, karmaşık gezinme. |
| Bağımlılık | Standart kütüphane. | Gem (mechanize). |
Proxy türleri ve sınırlamalar
Net::HTTP (ve dolayısıyla Mechanize) temel olarak HTTP ve HTTPS proxy türlerini destekler. Bu proxy'ler HTTP/HTTPS isteklerini iletir.
- HTTP proxy'ler: şifrelenmemiş HTTP trafiği için kullanılır.
- HTTPS proxy'ler (CONNECT): şifreli HTTPS trafiği için kullanılır.
Net::HTTP, proxy üzerinden hedef host'a birCONNECTtüneli kurar. - SOCKS proxy'ler:
Net::HTTP, SOCKS proxy'leri (SOCKS4, SOCKS5) yerel olarak desteklemez. Ruby'de SOCKS proxy kullanmak içinsocks-rubygibi harici bir gem gereklidir. Bu gem, socket oluşturmayı override ederekNet::HTTPile entegre olur.
# socks-ruby ile SOCKS proxy kullanım örneği ('socks-ruby' gem'i gerekir)
# 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')
# Net::HTTP'nin socket oluşturmasını override edin
Net::HTTP.class_eval do
def connect
if proxy_address
# Mevcut HTTP/HTTPS proxy mantığı
super
elsif ENV['SOCKS_PROXY'] # SOCKS için özel ortam değişkeni
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
# SOCKS proxy için özel bir ortam değişkeni tanımlayın
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 # HTTPS için zorunlu
http.verify_mode = OpenSSL::SSL::VERIFY_PEER # Güvenlik için önerilir
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') # Temizlik
Hata yönetimi ve zaman aşımları
Proxy kullanırken ağ sorunları, hatalı proxy yapılandırmaları veya proxy sunucu arızaları sık görülür. Sağlam bir hata yönetimi kritik önemdedir.
Sık karşılaşılan hatalar
Net::OpenTimeout: proxy'ye veya hedef sunucuya bağlantı kurulamadan zaman aşımına uğradı.Net::ReadTimeout: sunucu (proxy veya hedef) belirtilen zaman aşımı süresi içinde veri göndermedi.Errno::ECONNREFUSED: proxy sunucu bağlantıyı aktif olarak reddetti.Net::HTTPBadResponse: proxy sunucu veya hedef geçersiz bir HTTP yanıtı döndürdü.Mechanize::ResponseCodeError: hedef sunucu 2xx dışında bir HTTP durum kodu döndürdüğünde oluşan Mechanize'a özgü hata (örn. 403 Forbidden, 404 Not Found, 500 Internal Server Error).
Zaman aşımı yapılandırması
Uygun zaman aşımları belirlemek, betiklerin süresiz olarak takılı kalmasını önler.
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 # Bağlantı kurma zaman aşımı (saniye)
http.read_timeout = 10 # Bağlantıdan veri okuma zaman aşımı (saniye)
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 de zaman aşımlarını destekler
# agent = Mechanize.new
# agent.set_proxy(proxy_host, proxy_port)
# agent.open_timeout = 5
# agent.read_timeout = 10
En iyi uygulamalar
- User-Agent dizeleri: scraping yaparken her zaman gerçekçi bir
User-Agentbaşlığı ayarlayın. Birçok site, bu başlık olmayan veya genel değer taşıyan istekleri engeller. Mechanize'ınuser_agent_aliasözelliği bunu kolaylaştırır. - Referer başlıkları: bazı sitelerde, meşru tarayıcı davranışını taklit etmek için geçerli bir
Refererbaşlığı gereklidir. - Cookie yönetimi: Mechanize cookie'leri otomatik olarak yönetir; bu, proxy üzerinden oturumları sürdürmek için kritiktir.
Net::HTTPile cookie yönetimini elle yapmanız gerekir. - Hata yönetimi ve yeniden denemeler: geçici ağ hataları veya proxy sorunları için üstel geri çekilmeli (exponential backoff) yeniden deneme mantığı uygulayın.
- Proxy sağlık kontrolleri: bir proxy'yi kullanmadan önce, çalışıp çalışmadığını ve IP adresini doğrulamak için bilinen bir endpoint'e (örn.
https://api.ipify.org) hızlı bir kontrol yapmayı düşünün. - Kaynak yönetimi: özellikle
startbloğunu kullanmadığınızda, kaynak sızıntısını önlemek içinNet::HTTPbağlantılarının düzgün kapatıldığından emin olun. Mechanize bağlantıları kendi içinde yönetir.
