العودة إلى المدونة

إعداد البروكسي في روبي عبر Net::HTTP وFaraday: دليل كامل لـ Rails والبرامج المستقلة

كيفية إعداد البروكسي بشكل صحيح في مشاريع Ruby عبر Net::HTTP و Faraday - مع أمثلة لـ Rails والبرامج المستقلة، وتدوير IP وتجاوز الحظر.

📅٣٠ صفر ١٤٤٨ هـ
```html

إذا كنت تكتب محللًا، أو تدمج واجهة برمجة تطبيقات خارجية، أو تقوم بأتمتة جمع البيانات في روبي - عاجلاً أم آجلاً ستواجه حجبًا على مستوى IP. تقوم Wildberries وOzon وInstagram وعشرات الخدمات الأخرى بقطع الطلبات من عنوان واحد بعد بضع مئات من الاستفسارات. الحل هو البروكسي. في هذه المقالة، سنستعرض كيفية توصيل البروكسي بمشروع روبي عبر Net::HTTP وعميل HTTP الشهير Faraday، وكيفية إعداد تدوير IP ومعالجة الأخطاء بشكل صحيح - سواء في تطبيق Rails أو في السكريبتات البسيطة.

لماذا يحتاج مطور روبي للبروكسي: السيناريوهات الرئيسية

يتم استخدام روبي بشكل نشط للمهام التي لا يمكن الاستغناء فيها عن البروكسي. قبل الانتقال إلى الكود، من المهم فهم في أي حالات تحتاج إليها - سيساعدك ذلك في اختيار النوع الصحيح وهندسة الحل.

تحليل وجمع البيانات. هذا هو السيناريو الأكثر شيوعًا. أنت تكتب سكريبتًا بلغة روبي يتجاوز صفحات Wildberries أو Ozon أو Avito، ويجمع الأسعار وخصائص المنتجات. بدون بروكسي، سيتم حظر هذا السكريبت على مستوى IP في غضون دقائق. ترى المواقع مئات الطلبات من عنوان واحد وتقوم تلقائيًا بتفعيل الحماية - CAPTCHA، حظر مؤقت أو رفض كامل للخدمة.

التكامل مع واجهات برمجة التطبيقات المعتمدة على الموقع. تقوم بعض الخدمات الخارجية بإرجاع محتوى مختلف اعتمادًا على بلد الطلب. إذا كان تطبيق Rails الخاص بك يتصل بواجهة برمجة تطبيقات مثل هذه، فإن البروكسي يسمح بمحاكاة الطلبات من المنطقة المطلوبة. على سبيل المثال، للتحقق من نتائج محركات البحث لدول مختلفة أو الحصول على أسعار محدثة لسوق معين.

الاختبار وضمان الجودة. يستخدم المطورون البروكسي لاختبار سلوك التطبيق عند الطلبات من عناوين IP ودول مختلفة. هذا مهم بشكل خاص للخدمات التي تحتوي على حجب جغرافي أو تحديد معدل على مستوى IP.

أتمتة التسويق. غالبًا ما تستخدم سكريبتات روبي لمراقبة الحملات الإعلانية، والتحقق من المراكز في النتائج أو تتبع نشاط المنافسين. هنا تحتاج البروكسي لتوزيع الحمل وتجاوز القيود.

العمل مع عدة حسابات. إذا كان سكريبتك يدير عدة حسابات على منصة واحدة، يجب أن يعمل كل حساب عبر IP منفصل - وإلا ستكتشف المنصة بسهولة العلاقة وتقوم بحظر الجميع دفعة واحدة.

أي نوع من البروكسي يجب اختياره لمهام روبي

ليست جميع البروكسيات مناسبة بنفس القدر لمهام مختلفة. يؤثر اختيار النوع بشكل مباشر على نجاح عمل سكريبتك. دعونا نستعرض الخيارات الرئيسية المتعلقة بتطوير روبي.

نوع البروكسي أفضل المهام في روبي السرعة تجاوز الحمايات
بروكسي مراكز البيانات تحليل بدون حماية صارمة، طلبات API، اختبار عالية متوسطة
بروكسي سكنية تحليل مواقع محمية، العمل مع الشبكات الاجتماعية، الأسواق متوسطة عالية
بروكسي موبايل Facebook، Instagram، TikTok API، العمل مع الحسابات متوسطة قصوى

بروكسي مراكز البيانات - الخيار الأسرع والأرخص. مناسب لتحليل المواقع بدون حماية عدوانية، طلبات API الجماعية، واختبارات التحميل. ومع ذلك، فإن المنصات الكبيرة (Facebook، Google، Cloudflare) يمكنها التعرف عليها بسهولة من خلال ASN مراكز البيانات.

بروكسي سكنية تستخدم IP لمستخدمين حقيقيين من المنازل. بالنسبة لسكريبتات روبي التي تحلل Wildberries أو Ozon أو تعمل مع مواقع محمية - هذا هو الخيار الأمثل. ترى المواقع مستخدمًا عاديًا، وليس خادمًا.

بروكسي موبايل تعمل عبر IP لمشغلي الهواتف المحمولة (4G/5G). هذه هي العناوين الأكثر ثقة من وجهة نظر المنصات - يمكن لمئات المستخدمين الحقيقيين استخدام IP موبايل واحد في نفس الوقت، لذا فإن الحجب عليه نادر جدًا. إذا كان سكريبت روبي الخاص بك يعمل مع الشبكات الاجتماعية أو منصات الإعلانات - ستقلل بروكسي الموبايل من خطر الحجب إلى الحد الأدنى.

البروكسي في Net::HTTP: الإعداد الأساسي

Net::HTTP - مكتبة قياسية في روبي لطلبات HTTP، وهي جزء من التوزيعة القياسية للغة. تدعم البروكسي "من الصندوق" عبر طريقة خاصة Net::HTTP::Proxy.

أبسط طريقة هي إنشاء فئة بروكسي واستخدامها بدلاً من Net::HTTP العادية:

require 'net/http'
require 'uri'

# بيانات البروكسي
proxy_host = 'proxy.example.com'
proxy_port = 8080

# إنشاء فئة البروكسي
proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port)

# تنفيذ الطلب عبر البروكسي
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

تأخذ طريقة Net::HTTP::Proxy أربعة معلمات: مضيف البروكسي، المنفذ، اسم المستخدم وكلمة المرور. الأولان إلزاميان، بينما الأخيران اختياريان للبروكسيات بدون مصادقة.

طريقة بديلة هي تمرير معلمات البروكسي مباشرة إلى طريقة 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 إذا بدون مصادقة)
  nil                    # proxy_pass
)

http.use_ssl = true

response = http.get(uri.path)
puts response.body

هذه الطريقة مريحة عندما تحتاج إلى إعادة استخدام نفس كائن HTTP لعدة طلبات إلى نفس المضيف. لاحظ: يتم تمرير معلمات البروكسي كوسيطين ثالث ورابع، وليس عبر طريقة منفصلة.

المصادقة وHTTPS عبر Net::HTTP

تتطلب معظم البروكسيات التجارية المصادقة - اسم المستخدم وكلمة المرور. بالإضافة إلى ذلك، عند العمل مع مواقع HTTPS، تحتاج إلى إعداد إضافي لـ SSL. دعونا نستعرض كلا الحالتين.

بروكسي مع اسم المستخدم وكلمة المرور:

require 'net/http'
require 'uri'

proxy_host = 'proxy.example.com'
proxy_port = 8080
proxy_user = 'your_username'
proxy_pass = 'your_password'

# إنشاء فئة البروكسي مع المصادقة
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|
  # إيقاف التحقق من SSL (فقط للاختبار!)
  # 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

نقطة مهمة: عند استخدام بروكسي HTTPS (نفق عبر CONNECT) يقوم Net::HTTP تلقائيًا بإنشاء اتصال SSL مع الخادم الهدف عبر نفق البروكسي. هذا يعمل بشكل صحيح لمعظم خوادم البروكسي.

الإعداد عبر متغيرات البيئة. من الممارسات الجيدة عدم تضمين بيانات البروكسي في الكود، بل قراءتها من متغيرات البيئة:

require 'net/http'
require 'uri'

# قراءة إعدادات البروكسي من 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

يمكن تعيين متغير البيئة بتنسيق HTTP_PROXY=http://user:[email protected]:8080. تتيح لك هذه الطريقة تغيير البروكسي دون تغيير الكود - يكفي تحديث المتغير في ملف .env أو في إعدادات الخادم.

توصيل البروكسي عبر Faraday

Faraday - واحدة من أشهر عملاء HTTP في نظام روبي البيئي. يتم استخدامها في العديد من تطبيقات Rails بفضل نهج middleware المريح ودعمها لمختلف المحولات (Net::HTTP، HTTParty، Typhoeus وغيرها). إعداد البروكسي في Faraday يختلف قليلاً حسب المحول المستخدم.

الإعداد الأساسي للبروكسي في Faraday:

require 'faraday'

# إنشاء اتصال Faraday مع البروكسي
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}"

تأخذ المعلمة faraday.proxy هاشًا بمفاتيح uri، user وpassword. يمكنك أيضًا تمرير سلسلة URI مباشرة، إذا كان البروكسي لا يتطلب مصادقة.

Faraday مع محول Net::HTTP وإعدادات موسعة:

require 'faraday'

conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
  faraday.proxy = 'http://user:[email protected]:8080'
  
  # إعدادات المهلات الزمنية
  faraday.options.timeout = 30
  faraday.options.open_timeout = 10
  
  # Middleware لتسجيل الدخول (مفيد أثناء التصحيح)
  faraday.response :logger
  
  # إعادة المحاولة عند حدوث أخطاء في الاتصال
  faraday.request :retry, max: 3, interval: 1
  
  # المحول
  faraday.adapter :net_http
end

begin
  response = conn.get('/ip')
  puts response.body
rescue Faraday::ConnectionFailed => e
  puts "خطأ في الاتصال: #{e.message}"
rescue Faraday::TimeoutError => e
  puts "مهلة: #{e.message}"
end

Middleware :retry مفيدة بشكل خاص عند العمل مع البروكسي - إذا كان عنوان واحد غير متاح مؤقتًا، سيقوم Faraday تلقائيًا بإعادة الطلب. هذا أمر حاسم لعمل السكريبت بشكل موثوق في الإنتاج.

Faraday مع محول Typhoeus (للطلبات المتوازية):

# 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

# طلبات متوازية عبر البروكسي
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 }

تدوير البروكسي: تغيير IP تلقائي

عنوان بروكسي واحد، حتى لو كان سكنيًا، سيتعرض عاجلاً أم آجلاً للقيود عند التحليل المكثف. الحل هو التدوير: تغيير IP تلقائيًا بعد كل طلب أو عبر فترات معينة. دعونا ننفذ تدويرًا بسيطًا لسكريبتات روبي.

تدوير بسيط يعتمد على مصفوفة البروكسيات:

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

# قائمة البروكسيات بتنسيق [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)

# تحليل قائمة URL عبر بروكسيات مختلفة
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[0]}"
    end
  rescue => e
    puts "خطأ مع البروكسي #{proxy[0]}: #{e.message}"
    # الانتقال إلى البروكسي التالي تلقائيًا
  end
  
  sleep(rand(0.5..2.0)) # تأخير عشوائي بين الطلبات
end

التأخير العشوائي بين الطلبات (sleep(rand(0.5..2.0))) هو عنصر مهم. نمط الطلبات بفواصل زمنية ثابتة يمكن اكتشافه بسهولة من قبل أنظمة مكافحة الروبوتات. التأخيرات العشوائية تحاكي سلوك المستخدم الحقيقي.

تدوير عبر Faraday مع 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)
    # اختيار بروكسي عشوائي لكل طلب
    proxy_uri = URI(PROXIES.sample)
    
    env[:request][:proxy] = {
      uri: proxy_uri,
      user: proxy_uri.user,
      password: proxy_uri.password
    }
    
    @app.call(env)
  end
end

# تسجيل 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

دمج البروكسي في تطبيق Rails

في تطبيق Rails، غالبًا ما تكون البروكسيات مطلوبة للطلبات HTTP الخارجية: التكامل مع واجهات برمجة التطبيقات، المهام الخلفية للتحليل أو الويب هوكس. دعونا نستعرض بعض الأنماط العملية.

النمط 1: كائن خدمة مع Faraday. إنشاء فئة خدمة أساسية تقوم بجميع الطلبات HTTP الخارجية عبر البروكسي:

# app/services/http_client.rb
class HttpClient
  def self.connection(base_url)
    Faraday.new(url: base_url) do |faraday|
      # البروكسي من متغيرات البيئة في 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

# الاستخدام في وحدة التحكم أو الخدمة:
# client = HttpClient.connection('https://api.example.com')
# response = client.get('/products', { category: 'electronics' })

النمط 2: الإعداد عبر بيانات اعتماد Rails. لاستخدام بيانات البروكسي، استخدم بيانات الاعتماد المشفرة في Rails:

# config/credentials.yml.enc (يتم تحريره عبر 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

النمط 3: المهام الخلفية مع Sidekiq. إذا كانت عمليات التحليل أو طلبات API تتم في عمال خلفية، فإن إعداد البروكسي يبقى كما هو، ولكن من المهم مراعاة التنافس:

# app/workers/price_parser_worker.rb
class PriceParserWorker
  include Sidekiq::Worker
  
  sidekiq_options retry: 3, queue: :parsers
  
  def perform(product_url)
    # إنشاء اتصال جديد لكل عامل
    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 "حالة غير متوقعة #{response.code} لـ #{product_url}"
      end
    end
  rescue Net::OpenTimeout, Net::ReadTimeout => e
    Rails.logger.error "مهلة لـ #{product_url}: #{e.message}"
    raise # Sidekiq سيعيد محاولة المهمة
  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)
    # منطق التحليل...
  end
end

معالجة الأخطاء والمهل الزمنية

العمل عبر البروكسي يضيف طبقة إضافية، قد تولد أخطاء محددة. المعالجة الجيدة للاستثناءات هي الفرق بين سكريبت سيفشل بعد 5 دقائق وسكريبت يعمل لساعات دون تدخل.

أنواع الأخطاء الرئيسية عند العمل مع البروكسي في روبي:

استثناء السبب ماذا تفعل
Net::OpenTimeout البروكسي لا يستجيب تغيير البروكسي، إعادة المحاولة
Net::ReadTimeout البروكسي بطيء أو الموقع لا يستجيب زيادة المهلة الزمنية أو تغيير البروكسي
Errno::ECONNREFUSED خادم البروكسي رفض الاتصال التحقق من بيانات البروكسي
OpenSSL::SSL::SSLError مشكلة مع SSL عبر البروكسي التحقق من إعدادات SSL
HTTP 407 اسم المستخدم/كلمة المرور للبروكسي غير صحيحة التحقق من بيانات الاعتماد
HTTP 403/429 IP محظور من قبل الموقع تغيير البروكسي، إضافة فترة توقف

معالجة الأخطاء بشكل شامل مع تغيير البروكسي تلقائيًا:

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 "فشلت مصادقة البروكسي لـ #{proxy[0]}"
        when 403, 429
          rotate_proxy!
          raise "IP محظور (#{response.code})، يتم تدوير البروكسي"
        else
          raise "حالة HTTP غير متوقعة: #{response.code}"
        end
      end

    rescue *RETRIABLE_ERRORS => e
      Rails.logger.warn "خطأ في الاتصال (محاولة #{attempt}/#{retries}): #{e.message}"
      rotate_proxy!
      retry if attempt < retries
      raise "فشل بعد #{retries} محاولات: #{e.message}"

    rescue RuntimeError => e
      Rails.logger.warn "خطأ HTTP (محاولة #{attempt}/#{retries}): #{e.message}"
      retry if attempt < retries
      raise
    end
  end

  private

  def current_proxy
    @proxies.first || raise("لا توجد بروكسيات متاحة!")
  end

  def rotate_proxy!
    failed = @proxies.shift
    @failed_proxies << failed
    Rails.logger.info "تم تدوير البروكسي. المتبقي: #{@proxies.length}"
  end
end

بروكسي SOCKS5 في روبي: الإعداد عبر socksify

لا يدعم Net::HTTP بروكسي SOCKS5 بشكل أصلي - فقط بروكسي HTTP/HTTPS. للعمل مع SOCKS5، تحتاج إلى مكتبة إضافية. الخيار الأكثر شعبية هو الجيم socksify.

لماذا قد يكون SOCKS5 مفضلًا على بروكسي HTTP؟ يعمل بروتوكول SOCKS5 على مستوى أدنى - حيث يقوم بتمرير أي حركة مرور TCP، وليس فقط HTTP. بالإضافة إلى ذلك، يدعم SOCKS5 المصادقة وينقل معلومات أقل حول الطلب، مما يجعله أقل وضوحًا لأنظمة اكتشاف الروبوتات.

# Gemfile
# gem 'socksify'

require 'socksify'
require 'socksify/http'
require 'net/http'
require 'uri'

# إعداد بروكسي SOCKS5 عالمي
TCPSocket::socks_server = 'proxy.example.com'
TCPSocket::socks_port = 1080

# اختياري: المصادقة (SOCKS5 username/password)
# TCPSocket::socks_username = 'your_user'
# TCPSocket::socks_password = 'your_pass'

# الآن جميع طلبات Net::HTTP تمر عبر SOCKS5
uri = URI('https://httpbin.org/ip')
response = Net::HTTP.get_response(uri)
puts response.body

لاحظ: عند استخدام socksify، يتم تطبيق الإعداد عالميًا على جميع اتصالات TCP في العملية. إذا كنت بحاجة إلى إعداد أكثر مرونة - استخدم Net::HTTP.SOCKSProxy من نفس الجيم:

require 'socksify/http'

# إنشاء فئة بروكسي SOCKS5 (مماثلة لـ Net::HTTP::Proxy لبروكسي 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

بالنسبة لـ Faraday مع SOCKS5، ستحتاج إلى محول يدعم هذا البروتوكول. خيار جيد هو faraday-net_http بالتعاون مع socksify، أو استخدام المحول القائم على curl faraday-typhoeus، الذي يدعم SOCKS5 بشكل أصلي عبر libcurl.

💡 نصيحة لاختيار البروتوكول

لمعظم مهام التحليل والعمل مع واجهات برمجة التطبيقات، يكفي استخدام بروكسي HTTP/HTTPS - فهي أسهل في الإعداد وتدعم بشكل أصلي. يجب استخدام SOCKS5 عندما تحتاج إلى تمرير حركة مرور غير HTTP، أو عندما يتم اكتشاف بروكسي HTTP بسهولة من قبل الخدمة المستهدفة. تتوفر بروكسيات موبايل وسكنية في كلا البروتوكولين.

الخاتمة والتوصيات

إعداد البروكسي في روبي لا يتطلب مكتبات معقدة - يدعم Net::HTTP بروكسي HTTP "من الصندوق"، بينما يجعل Faraday التكامل أكثر سهولة بفضل بنية middleware. النقاط الرئيسية من هذا الدليل:

  • لـ Net::HTTP استخدم Net::HTTP::Proxy - هذه طريقة مدمجة وموثوقة.
  • لـ Faraday تأخذ المعلمة faraday.proxy سلسلة URI أو هاش مع بيانات الاعتماد.
  • احتفظ ببيانات البروكسي في متغيرات البيئة أو بيانات اعتماد Rails - لا تقم بتضمينها في الكود.
  • نفذ تدوير البروكسي ومعالجة الأخطاء لضمان عمل موثوق في الإنتاج.
  • أضف تأخيرات عشوائية وتدوير User-Agent لمحاكاة سلوك الإنسان.
  • لـ SOCKS5 استخدم الجيم socksify.

يعتمد اختيار نوع البروكسي على المهمة. إذا كنت تكتب محللًا لـ Wildberries أو Ozon - ستوفر البروكسيات السكنية أفضل توازن بين السرعة وتجاوز الحمايات: IPs الحقيقية لمستخدمي المنازل نادرًا ما تقع في قوائم الحظر. بالنسبة للمهام ذات الحمل العالي مع حجم كبير من الطلبات إلى مصادر أقل حماية، تناسب بروكسي مراكز البيانات - فهي أسرع وأرخص لكل طلب. إذا كان سكريبت روبي الخاص بك يعمل مع الشبكات الاجتماعية أو واجهات برمجة التطبيقات الإعلانية - انتبه إلى البروكسيات الموبايل: عناوين IP الخاصة بها تتمتع بأعلى مستوى من الثقة على معظم المنصات.

```