Nếu bạn đang viết một parser, tích hợp API bên ngoài hoặc tự động hóa việc thu thập dữ liệu trên Ruby - sớm hay muộn bạn sẽ gặp phải các chặn theo IP. Wildberries, Ozon, Instagram và hàng chục dịch vụ khác cắt giảm các yêu cầu từ một địa chỉ sau vài trăm lần truy cập. Giải pháp duy nhất là - proxy. Trong bài viết này, chúng ta sẽ tìm hiểu cách kết nối proxy vào dự án Ruby thông qua Net::HTTP tiêu chuẩn và HTTP client phổ biến Faraday, thiết lập xoay vòng IP và xử lý lỗi một cách chính xác - như trong ứng dụng Rails, cũng như trong các script đơn giản.
Tại sao lập trình viên Ruby cần proxy: các kịch bản chính
Ruby được sử dụng rộng rãi cho các tác vụ mà không có proxy thì không thể thực hiện. Trước khi đi vào mã, bạn nên hiểu trong những tình huống nào chúng cần thiết - điều này sẽ giúp bạn chọn loại và kiến trúc giải pháp phù hợp.
Phân tích và thu thập dữ liệu. Đây là kịch bản phổ biến nhất. Bạn viết một script trên Ruby, truy cập các trang của Wildberries, Ozon hoặc Avito, thu thập giá cả và thông số kỹ thuật của sản phẩm. Nếu không có proxy, script như vậy sẽ bị chặn theo IP chỉ sau vài phút. Các trang web thấy hàng trăm yêu cầu từ một địa chỉ và tự động kích hoạt bảo vệ - captcha, cấm tạm thời hoặc từ chối hoàn toàn dịch vụ.
Tích hợp với API phụ thuộc vào địa lý. Một số dịch vụ bên ngoài trả về nội dung khác nhau tùy thuộc vào quốc gia gửi yêu cầu. Nếu ứng dụng Rails của bạn truy cập một API như vậy, proxy cho phép giả lập các yêu cầu từ khu vực cần thiết. Ví dụ, kiểm tra kết quả tìm kiếm cho các quốc gia khác nhau hoặc nhận giá cả phù hợp cho thị trường cụ thể.
Kiểm tra và QA. Các lập trình viên sử dụng proxy để kiểm tra hành vi của ứng dụng khi nhận yêu cầu từ các địa chỉ IP và quốc gia khác nhau. Điều này đặc biệt quan trọng đối với các dịch vụ có chặn địa lý hoặc giới hạn tần suất theo IP.
Tự động hóa marketing. Các script Ruby thường được sử dụng để theo dõi các chiến dịch quảng cáo, kiểm tra vị trí trong kết quả tìm kiếm hoặc theo dõi hoạt động của đối thủ. Ở đây, proxy cần thiết để phân phối tải và vượt qua các hạn chế.
Quản lý nhiều tài khoản. Nếu script của bạn quản lý nhiều tài khoản trên một nền tảng, mỗi tài khoản phải hoạt động qua một IP riêng biệt - nếu không, nền tảng sẽ dễ dàng phát hiện mối liên hệ và chặn tất cả ngay lập tức.
Chọn loại proxy nào cho các tác vụ Ruby
Không phải tất cả các proxy đều phù hợp cho các tác vụ khác nhau. Việc chọn loại proxy ảnh hưởng trực tiếp đến sự thành công của script của bạn. Hãy cùng xem xét các tùy chọn chính liên quan đến phát triển Ruby.
| Loại proxy | Tác vụ tốt nhất trong Ruby | Tốc độ | Vượt qua bảo vệ |
|---|---|---|---|
| Proxy trung tâm dữ liệu | Phân tích mà không có bảo vệ nghiêm ngặt, yêu cầu API, kiểm tra | Cao | Trung bình |
| Proxy cư trú | Phân tích các trang web bảo mật, làm việc với mạng xã hội, thị trường | Trung bình | Cao |
| Proxy di động | Facebook, Instagram, TikTok API, làm việc với tài khoản | Trung bình | Tối đa |
Proxy trung tâm dữ liệu - là lựa chọn nhanh nhất và rẻ nhất. Phù hợp cho việc phân tích các trang web không có bảo vệ nghiêm ngặt, yêu cầu API hàng loạt và kiểm tra tải. Tuy nhiên, các nền tảng lớn (Facebook, Google, Cloudflare) dễ dàng nhận diện chúng qua ASN của trung tâm dữ liệu.
Proxy cư trú sử dụng IP của người dùng thực. Đối với các script Ruby phân tích Wildberries, Ozon hoặc làm việc với các trang web bảo mật - đây là lựa chọn tối ưu. Các trang web thấy một người dùng bình thường, không phải là máy chủ.
Proxy di động hoạt động qua IP của các nhà mạng di động (4G/5G). Đây là những địa chỉ đáng tin cậy nhất từ góc độ các nền tảng - một IP di động có thể được hàng trăm người dùng thực sử dụng đồng thời, do đó việc chặn theo IP này rất hiếm. Nếu script Ruby của bạn làm việc với mạng xã hội hoặc các nền tảng quảng cáo - proxy di động sẽ giảm thiểu nguy cơ bị chặn đến mức tối thiểu.
Proxy trong Net::HTTP: thiết lập cơ bản
Net::HTTP - thư viện tiêu chuẩn của Ruby cho các yêu cầu HTTP, được bao gồm trong bản phân phối tiêu chuẩn của ngôn ngữ. Nó hỗ trợ proxy "ngay từ đầu" thông qua phương thức đặc biệt Net::HTTP::Proxy.
Cách đơn giản nhất là tạo một lớp proxy và sử dụng nó thay cho Net::HTTP thông thường:
require 'net/http'
require 'uri'
# Dữ liệu proxy
proxy_host = 'proxy.example.com'
proxy_port = 8080
# Tạo lớp proxy
proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port)
# Thực hiện yêu cầu qua proxy
uri = URI('https://httpbin.org/ip')
proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.body
end
Phương thức Net::HTTP::Proxy nhận bốn tham số: máy chủ proxy, cổng, tên người dùng và mật khẩu. Hai tham số đầu tiên là bắt buộc, hai tham số cuối cùng là tùy chọn cho các proxy không yêu cầu xác thực.
Cách thay thế là truyền các tham số proxy trực tiếp vào phương thức Net::HTTP.new:
require 'net/http'
uri = URI('https://httpbin.org/ip')
http = Net::HTTP.new(
uri.host,
uri.port,
'proxy.example.com', # proxy_addr
8080, # proxy_port
nil, # proxy_user (nil nếu không có xác thực)
nil # proxy_pass
)
http.use_ssl = true
response = http.get(uri.path)
puts response.body
Cách tiếp cận này thuận tiện khi bạn cần tái sử dụng cùng một đối tượng HTTP cho nhiều yêu cầu đến một máy chủ. Lưu ý: các tham số proxy được truyền dưới dạng tham số thứ ba và thứ tư, không thông qua một phương thức riêng biệt.
Xác thực và HTTPS qua Net::HTTP
Hầu hết các proxy thương mại yêu cầu xác thực - tên đăng nhập và mật khẩu. Hơn nữa, khi làm việc với các trang web HTTPS cần có cấu hình SSL bổ sung. Hãy cùng xem xét cả hai trường hợp.
Proxy có tên đăng nhập và mật khẩu:
require 'net/http'
require 'uri'
proxy_host = 'proxy.example.com'
proxy_port = 8080
proxy_user = 'your_username'
proxy_pass = 'your_password'
# Tạo lớp proxy với xác thực
proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass)
uri = URI('https://httpbin.org/ip')
proxy_class.start(uri.host, uri.port, use_ssl: true) do |http|
# Tắt xác thực SSL (chỉ để thử nghiệm!)
# http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri)
request['User-Agent'] = 'Mozilla/5.0 (compatible; MyBot/1.0)'
response = http.request(request)
puts "IP: #{response.body}"
puts "Status: #{response.code}"
end
Một điểm quan trọng: khi sử dụng proxy HTTPS (tunneling qua CONNECT) Net::HTTP tự động thiết lập kết nối SSL với máy chủ đích qua proxy tunnel. Điều này hoạt động chính xác cho hầu hết các máy chủ proxy.
Cấu hình qua biến môi trường. Một thực hành tốt là không mã hóa dữ liệu proxy trong mã, mà đọc chúng từ các biến môi trường:
require 'net/http'
require 'uri'
# Đọc cấu hình proxy từ ENV
proxy_uri = URI(ENV.fetch('HTTP_PROXY', 'http://proxy.example.com:8080'))
proxy_class = Net::HTTP::Proxy(
proxy_uri.host,
proxy_uri.port,
proxy_uri.user,
proxy_uri.password
)
target_uri = URI('https://httpbin.org/ip')
proxy_class.start(target_uri.host, target_uri.port, use_ssl: true) do |http|
response = http.get(target_uri.path)
puts response.body
end
Biến môi trường có thể được đặt ở định dạng HTTP_PROXY=http://user:[email protected]:8080. Cách tiếp cận này cho phép thay đổi proxy mà không cần thay đổi mã - chỉ cần cập nhật biến trong .env hoặc trong cài đặt máy chủ.
Kết nối proxy qua Faraday
Faraday - một trong những HTTP client phổ biến nhất trong hệ sinh thái Ruby. Nó được sử dụng trong nhiều ứng dụng Rails nhờ vào cách tiếp cận middleware tiện lợi và hỗ trợ nhiều adapter khác nhau (Net::HTTP, HTTParty, Typhoeus và nhiều hơn nữa). Thiết lập proxy trong Faraday hơi khác nhau tùy thuộc vào adapter đang sử dụng.
Thiết lập cơ bản proxy trong Faraday:
require 'faraday'
# Tạo kết nối Faraday với proxy
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.proxy = {
uri: 'http://proxy.example.com:8080',
user: 'your_username',
password: 'your_password'
}
faraday.headers['User-Agent'] = 'Mozilla/5.0 (compatible; MyBot/1.0)'
faraday.adapter Faraday.default_adapter
end
response = conn.get('/ip')
puts response.body
puts "Status: #{response.status}"
Tham số faraday.proxy nhận một hash với các khóa uri, user và password. Bạn cũng có thể truyền một chuỗi URI trực tiếp nếu proxy không yêu cầu xác thực.
Faraday với adapter Net::HTTP và cài đặt mở rộng:
require 'faraday'
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.proxy = 'http://user:[email protected]:8080'
# Cài đặt thời gian chờ
faraday.options.timeout = 30
faraday.options.open_timeout = 10
# Middleware cho việc ghi log (tiện lợi khi gỡ lỗi)
faraday.response :logger
# Retry khi có lỗi kết nối
faraday.request :retry, max: 3, interval: 1
# Adapter
faraday.adapter :net_http
end
begin
response = conn.get('/ip')
puts response.body
rescue Faraday::ConnectionFailed => e
puts "Lỗi kết nối: #{e.message}"
rescue Faraday::TimeoutError => e
puts "Thời gian chờ: #{e.message}"
end
Middleware :retry đặc biệt hữu ích khi làm việc với proxy - nếu một địa chỉ tạm thời không khả dụng, Faraday sẽ tự động lặp lại yêu cầu. Điều này rất quan trọng cho việc hoạt động đáng tin cậy của script trong môi trường sản xuất.
Faraday với adapter Typhoeus (cho các yêu cầu song song):
# Gemfile: gem 'typhoeus'
require 'faraday'
require 'typhoeus/adapters/faraday'
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.proxy = 'http://user:[email protected]:8080'
faraday.adapter :typhoeus
end
# Các yêu cầu song song qua proxy
responses = []
conn.in_parallel do
responses << conn.get('/ip')
responses << conn.get('/headers')
responses << conn.get('/user-agent')
end
responses.each { |r| puts r.body }
Xoay vòng proxy: tự động thay đổi IP
Một địa chỉ proxy, ngay cả khi là cư trú, sớm hay muộn cũng sẽ bị giới hạn khi phân tích dữ liệu một cách liên tục. Giải pháp là - xoay vòng: tự động thay đổi IP sau mỗi yêu cầu hoặc qua các khoảng thời gian nhất định. Chúng ta sẽ triển khai một bộ xoay vòng đơn giản cho các script Ruby.
Bộ xoay vòng đơn giản dựa trên mảng proxy:
require 'net/http'
require 'uri'
class ProxyRotator
def initialize(proxies)
@proxies = proxies
@index = 0
@mutex = Mutex.new
end
def next_proxy
@mutex.synchronize do
proxy = @proxies[@index % @proxies.length]
@index += 1
proxy
end
end
def random_proxy
@proxies.sample
end
end
# Danh sách proxy ở định dạng [host, port, user, pass]
proxies = [
['proxy1.example.com', 8080, 'user1', 'pass1'],
['proxy2.example.com', 8080, 'user2', 'pass2'],
['proxy3.example.com', 8080, 'user3', 'pass3'],
]
rotator = ProxyRotator.new(proxies)
# Phân tích danh sách URL qua các proxy khác nhau
urls = [
'https://httpbin.org/ip',
'https://httpbin.org/headers',
'https://httpbin.org/user-agent'
]
urls.each do |url|
proxy = rotator.next_proxy
proxy_class = Net::HTTP::Proxy(proxy[0], proxy[1], proxy[2], proxy[3])
uri = URI(url)
begin
proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.read_timeout = 15
response = http.get(uri.path)
puts "#{url} -> Status: #{response.code}, Proxy: #{proxy[0]}"
end
rescue => e
puts "Lỗi với proxy #{proxy[0]}: #{e.message}"
# Tự động chuyển sang proxy tiếp theo
end
sleep(rand(0.5..2.0)) # Thời gian trễ ngẫu nhiên giữa các yêu cầu
end
Thời gian trễ ngẫu nhiên giữa các yêu cầu (sleep(rand(0.5..2.0))) - là một yếu tố quan trọng. Mô hình yêu cầu với các khoảng thời gian cố định dễ dàng bị phát hiện bởi các hệ thống chống bot. Thời gian trễ ngẫu nhiên mô phỏng hành vi của người dùng thực.
Xoay vòng qua Faraday với middleware:
require 'faraday'
class ProxyMiddleware < Faraday::Middleware
PROXIES = [
'http://user1:[email protected]:8080',
'http://user2:[email protected]:8080',
'http://user3:[email protected]:8080',
].freeze
def call(env)
# Chọn một proxy ngẫu nhiên cho mỗi yêu cầu
proxy_uri = URI(PROXIES.sample)
env[:request][:proxy] = {
uri: proxy_uri,
user: proxy_uri.user,
password: proxy_uri.password
}
@app.call(env)
end
end
# Đăng ký middleware
Faraday::Middleware.register_middleware proxy_rotator: ProxyMiddleware
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.use :proxy_rotator
faraday.adapter :net_http
end
5.times do
response = conn.get('/ip')
puts response.body
end
Tích hợp proxy vào ứng dụng Rails
Trong ứng dụng Rails, proxy thường cần thiết cho các yêu cầu HTTP bên ngoài: tích hợp với API, các tác vụ phân tích nền hoặc webhook. Hãy xem xét một số mẫu thực tiễn.
Mẫu 1: Đối tượng dịch vụ với Faraday. Tạo một lớp dịch vụ cơ bản, mà tất cả các yêu cầu HTTP bên ngoài đều thực hiện qua proxy:
# app/services/http_client.rb
class HttpClient
def self.connection(base_url)
Faraday.new(url: base_url) do |faraday|
# Proxy từ các biến môi trường Rails
if Rails.env.production? && ENV['PROXY_URL'].present?
faraday.proxy = ENV['PROXY_URL']
end
faraday.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
faraday.options.timeout = 30
faraday.options.open_timeout = 10
faraday.request :retry, max: 3, interval: 2,
exceptions: [Faraday::ConnectionFailed, Faraday::TimeoutError]
faraday.response :raise_error
faraday.adapter :net_http
end
end
end
# Sử dụng trong controller hoặc dịch vụ:
# client = HttpClient.connection('https://api.example.com')
# response = client.get('/products', { category: 'electronics' })
Mẫu 2: Cấu hình qua Rails credentials. Để lưu trữ dữ liệu proxy, hãy sử dụng credentials được mã hóa của Rails:
# config/credentials.yml.enc (chỉnh sửa qua rails credentials:edit)
# proxy:
# host: proxy.example.com
# port: 8080
# username: your_user
# password: your_pass
# app/services/proxy_service.rb
class ProxyService
def self.faraday_proxy_config
creds = Rails.application.credentials.proxy
return nil unless creds
{
uri: "http://#{creds[:host]}:#{creds[:port]}",
user: creds[:username],
password: creds[:password]
}
end
def self.net_http_proxy
creds = Rails.application.credentials.proxy
return Net::HTTP::Proxy(nil, nil) unless creds
Net::HTTP::Proxy(
creds[:host],
creds[:port],
creds[:username],
creds[:password]
)
end
end
Mẫu 3: Các tác vụ nền với Sidekiq. Nếu việc phân tích hoặc yêu cầu API được thực hiện trong các worker nền, cấu hình proxy vẫn giữ nguyên, nhưng cần lưu ý đến tính cạnh tranh:
# app/workers/price_parser_worker.rb
class PriceParserWorker
include Sidekiq::Worker
sidekiq_options retry: 3, queue: :parsers
def perform(product_url)
# Tạo một kết nối mới cho mỗi worker
proxy = ProxyService.net_http_proxy
uri = URI(product_url)
proxy.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.read_timeout = 20
request = Net::HTTP::Get.new(uri)
request['User-Agent'] = random_user_agent
response = http.request(request)
if response.code == '200'
parse_and_save(response.body, product_url)
else
Rails.logger.warn "Trạng thái không mong đợi #{response.code} cho #{product_url}"
end
end
rescue Net::OpenTimeout, Net::ReadTimeout => e
Rails.logger.error "Thời gian chờ cho #{product_url}: #{e.message}"
raise # Sidekiq sẽ lặp lại tác vụ
end
private
def random_user_agent
agents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
]
agents.sample
end
def parse_and_save(html, url)
# Logic phân tích...
end
end
Xử lý lỗi và thời gian chờ
Làm việc qua proxy thêm một lớp bổ sung, có thể tạo ra các lỗi đặc thù. Xử lý ngoại lệ một cách khôn ngoan - đó là sự khác biệt giữa một script sẽ ngừng hoạt động sau 5 phút và một script hoạt động hàng giờ mà không cần can thiệp.
Các loại lỗi chính khi làm việc với proxy trong Ruby:
| Ngoại lệ | Nguyên nhân | Phải làm gì |
|---|---|---|
Net::OpenTimeout |
Proxy không phản hồi | Thay đổi proxy, lặp lại |
Net::ReadTimeout |
Proxy chậm hoặc trang web không phản hồi | Tăng thời gian chờ hoặc thay đổi proxy |
Errno::ECONNREFUSED |
Máy chủ proxy từ chối kết nối | Kiểm tra dữ liệu proxy |
OpenSSL::SSL::SSLError |
Vấn đề với SSL qua proxy | Kiểm tra cài đặt SSL |
| HTTP 407 | Tên đăng nhập/mật khẩu proxy không đúng | Kiểm tra credentials |
| HTTP 403/429 | IP bị chặn bởi trang web | Thay đổi proxy, thêm thời gian nghỉ |
Xử lý lỗi toàn diện với việc tự động thay đổi proxy:
require 'net/http'
require 'uri'
class RobustHttpClient
MAX_RETRIES = 3
RETRIABLE_ERRORS = [
Net::OpenTimeout,
Net::ReadTimeout,
Errno::ECONNREFUSED,
Errno::ECONNRESET,
OpenSSL::SSL::SSLError
].freeze
def initialize(proxies)
@proxies = proxies.dup
@failed_proxies = []
end
def get(url, retries: MAX_RETRIES)
uri = URI(url)
attempt = 0
begin
attempt += 1
proxy = current_proxy
proxy_class = Net::HTTP::Proxy(*proxy)
proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.open_timeout = 10
http.read_timeout = 20
request = Net::HTTP::Get.new(uri)
request['User-Agent'] = 'Mozilla/5.0 (compatible; RubyBot/1.0)'
response = http.request(request)
case response.code.to_i
when 200..299
response
when 407
raise "Xác thực proxy thất bại cho #{proxy[0]}"
when 403, 429
rotate_proxy!
raise "IP bị chặn (#{response.code}), đang xoay vòng proxy"
else
raise "Trạng thái HTTP không mong đợi: #{response.code}"
end
end
rescue *RETRIABLE_ERRORS => e
Rails.logger.warn "Lỗi kết nối (cố gắng #{attempt}/#{retries}): #{e.message}"
rotate_proxy!
retry if attempt < retries
raise "Thất bại sau #{retries} lần thử: #{e.message}"
rescue RuntimeError => e
Rails.logger.warn "Lỗi HTTP (cố gắng #{attempt}/#{retries}): #{e.message}"
retry if attempt < retries
raise
end
end
private
def current_proxy
@proxies.first || raise("Không có proxy nào khả dụng!")
end
def rotate_proxy!
failed = @proxies.shift
@failed_proxies << failed
Rails.logger.info "Đã xoay vòng proxy. Số lượng còn lại: #{@proxies.length}"
end
end
Proxy SOCKS5 trong Ruby: thiết lập qua socksify
Net::HTTP tiêu chuẩn không hỗ trợ SOCKS5 một cách tự nhiên - chỉ hỗ trợ proxy HTTP/HTTPS. Để làm việc với SOCKS5, cần một thư viện bổ sung. Lựa chọn phổ biến nhất là gem socksify.
Tại sao SOCKS5 có thể được ưa chuộng hơn proxy HTTP? Giao thức SOCKS5 hoạt động ở mức thấp hơn - nó proxy bất kỳ lưu lượng TCP nào, không chỉ HTTP. Hơn nữa, SOCKS5 hỗ trợ xác thực và truyền ít siêu dữ liệu về yêu cầu, khiến nó ít bị phát hiện hơn bởi các hệ thống phát hiện bot.
# Gemfile
# gem 'socksify'
require 'socksify'
require 'socksify/http'
require 'net/http'
require 'uri'
# Cài đặt toàn cầu cho proxy SOCKS5
TCPSocket::socks_server = 'proxy.example.com'
TCPSocket::socks_port = 1080
# Tùy chọn: xác thực (SOCKS5 username/password)
# TCPSocket::socks_username = 'your_user'
# TCPSocket::socks_password = 'your_pass'
# Bây giờ tất cả các yêu cầu Net::HTTP đều đi qua SOCKS5
uri = URI('https://httpbin.org/ip')
response = Net::HTTP.get_response(uri)
puts response.body
Lưu ý: khi sử dụng socksify, cài đặt được áp dụng toàn cầu cho tất cả các kết nối TCP trong quá trình. Nếu bạn cần cài đặt linh hoạt hơn - hãy sử dụng Net::HTTP.SOCKSProxy từ gem đó:
require 'socksify/http'
# Tạo lớp proxy SOCKS5 (tương tự như Net::HTTP::Proxy cho HTTP)
socks_proxy = Net::HTTP.SOCKSProxy('proxy.example.com', 1080)
uri = URI('https://httpbin.org/ip')
socks_proxy.start(uri.host, uri.port, use_ssl: true) do |http|
response = http.get(uri.path)
puts response.body
end
Đối với Faraday với SOCKS5, bạn sẽ cần một adapter hỗ trợ giao thức này. Một lựa chọn tốt là faraday-net_http kết hợp với socksify, hoặc sử dụng adapter dựa trên curl faraday-typhoeus, mà hỗ trợ SOCKS5 một cách tự nhiên qua libcurl.
💡 Lời khuyên về việc chọn giao thức
Đối với hầu hết các tác vụ phân tích và làm việc với API, proxy HTTP/HTTPS là đủ - chúng dễ thiết lập và được hỗ trợ tự nhiên. SOCKS5 nên được sử dụng khi bạn cần proxy không chỉ lưu lượng HTTP, hoặc khi proxy HTTP dễ dàng bị phát hiện bởi dịch vụ mục tiêu. Proxy di động và cư trú có sẵn trong cả hai giao thức.
Kết luận và khuyến nghị
Thiết lập proxy trong Ruby không yêu cầu các thư viện phức tạp - Net::HTTP hỗ trợ proxy HTTP "ngay từ đầu", trong khi Faraday làm cho việc tích hợp trở nên thuận tiện hơn nhờ kiến trúc middleware. Những điểm chính từ hướng dẫn này:
- Đối với Net::HTTP, hãy sử dụng
Net::HTTP::Proxy- đây là cách tích hợp đáng tin cậy và tích hợp sẵn. - Đối với Faraday, tham số
faraday.proxynhận một chuỗi URI hoặc hash với credentials. - Lưu trữ dữ liệu proxy trong các biến môi trường hoặc credentials của Rails - không mã hóa trong mã.
- Triển khai xoay vòng proxy và xử lý lỗi để đảm bảo hoạt động đáng tin cậy trong môi trường sản xuất.
- Thêm thời gian trễ ngẫu nhiên và xoay vòng User-Agent để mô phỏng hành vi của con người.
- Đối với SOCKS5, hãy sử dụng gem
socksify.
Việc chọn loại proxy phụ thuộc vào tác vụ. Nếu bạn đang viết một parser cho Wildberries hoặc Ozon - proxy cư trú sẽ mang lại sự cân bằng tốt nhất giữa tốc độ và khả năng vượt qua bảo vệ: các IP thực của người dùng gia đình rất hiếm khi bị đưa vào danh sách chặn. Đối với các tác vụ có tải cao với khối lượng yêu cầu lớn đến các nguồn ít bảo vệ hơn, proxy trung tâm dữ liệu sẽ nhanh hơn và rẻ hơn tính theo yêu cầu. Nếu script Ruby của bạn làm việc với mạng xã hội hoặc API quảng cáo - hãy chú ý đến proxy di động: các địa chỉ IP của chúng có mức độ tin cậy cao nhất trên hầu hết các nền tảng.
```