Как установить прокси с аутентификацией в Селен Chromeriver Python?

Я создаю сценарий, который сканирует один веб-сайт для сбора некоторых данных, но проблема в том, что они заблокировали меня после слишком большого количества запросов, но с помощью прокси я могу отправить больше запросов, чем в настоящее время. Я интегрировал прокси с хромированной опцией --proxy-server

options.add_argument('--proxy-server={}'.format('http://ip:port'))

но я использую платный прокси, поэтому он требует аутентификации и, как показано на скриншоте ниже, он выдает окно предупреждения для имени пользователя и пароля

Затем я попытался использовать его с именем пользователя и паролем

options.add_argument('--proxy-server={}'.format('http://username:password@ip:port'))

Но это также не похоже на работу. Я искал решение и нашел ниже решение, и я использовал его с автоматической аутентификацией прокси расширения Chrome и без расширения Chrome

proxy = {'address': settings.PROXY,
             'username': settings.PROXY_USER,
             'password': settings.PROXY_PASSWORD}

capabilities = dict(DesiredCapabilities.CHROME)
capabilities['proxy'] = {'proxyType': 'MANUAL',
                             'httpProxy': proxy['address'],
                             'ftpProxy': proxy['address'],
                             'sslProxy': proxy['address'],
                             'noProxy': '',
                             'class': "org.openqa.selenium.Proxy",
                             'autodetect': False,
                             'socksUsername': proxy['username'],
                             'socksPassword': proxy['password']}
options.add_extension(os.path.join(settings.DIR, "extension_2_0.crx")) # proxy auth extension

но ни один из вышеперечисленных не работал должным образом, кажется, работает, потому что после вышеприведенного кода предупреждение аутентификации прокси исчезло, и когда я проверил свой IP, найдя мой IP, и подтвердил, что он не работает.

Пожалуйста, кто-нибудь, кто может помочь мне аутентифицировать прокси-сервер на chromedriver.

12 ответов

Решение

Проверка подлинности Selenium Chrome Proxy

Настройка прокси для chromedriver с помощью Selenium с использованием Python

Если вам нужно использовать прокси с Python и библиотеку Selenium с chromedriver, вы обычно используете следующий код (без имени пользователя и пароля:

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--proxy-server=%s' % hostname + ":" + port)
driver = webdriver.Chrome(chrome_options=chrome_options)

Работает нормально, если прокси не требует аутентификации. если прокси-сервер требует, чтобы вы вошли в систему с именем пользователя и паролем, он не будет работать. В этом случае вам придется использовать более хитрое решение, которое объясняется ниже. Кстати, если вы заносите в белый список IP-адрес вашего сервера от прокси-провайдера или сервера, он не должен запрашивать учетные данные прокси.

Проверка подлинности прокси HTTP с помощью Chromedriver в Selenium

Для настройки прокси-аутентификации мы сгенерируем специальный файл и динамически загрузим его в chromedriver, используя следующий код ниже. Этот код настраивает селен с помощью chromedriver для использования HTTP-прокси, который требует аутентификации с парой пользователь / пароль.

import os
import zipfile

from selenium import webdriver

PROXY_HOST = '192.168.3.2'  # rotating proxy or host
PROXY_PORT = 8080 # port
PROXY_USER = 'proxy-user' # username
PROXY_PASS = 'proxy-password' # password


manifest_json = """
{
    "version": "1.0.0",
    "manifest_version": 2,
    "name": "Chrome Proxy",
    "permissions": [
        "proxy",
        "tabs",
        "unlimitedStorage",
        "storage",
        "<all_urls>",
        "webRequest",
        "webRequestBlocking"
    ],
    "background": {
        "scripts": ["background.js"]
    },
    "minimum_chrome_version":"22.0.0"
}
"""

background_js = """
var config = {
        mode: "fixed_servers",
        rules: {
        singleProxy: {
            scheme: "http",
            host: "%s",
            port: parseInt(%s)
        },
        bypassList: ["localhost"]
        }
    };

chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

function callbackFn(details) {
    return {
        authCredentials: {
            username: "%s",
            password: "%s"
        }
    };
}

chrome.webRequest.onAuthRequired.addListener(
            callbackFn,
            {urls: ["<all_urls>"]},
            ['blocking']
);
""" % (PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS)


def get_chromedriver(use_proxy=False, user_agent=None):
    path = os.path.dirname(os.path.abspath(__file__))
    chrome_options = webdriver.ChromeOptions()
    if use_proxy:
        pluginfile = 'proxy_auth_plugin.zip'

        with zipfile.ZipFile(pluginfile, 'w') as zp:
            zp.writestr("manifest.json", manifest_json)
            zp.writestr("background.js", background_js)
        chrome_options.add_extension(pluginfile)
    if user_agent:
        chrome_options.add_argument('--user-agent=%s' % user_agent)
    driver = webdriver.Chrome(
        os.path.join(path, 'chromedriver'),
        chrome_options=chrome_options)
    return driver

def main():
    driver = get_chromedriver(use_proxy=True)
    #driver.get('https://www.google.com/search?q=my+ip+address')
    driver.get('https://httpbin.org/ip')

if __name__ == '__main__':
    main()

Функция get_chromedriver возвращает настроенный селеновый веб-драйвер, который вы можете использовать в своем приложении. Этот код протестирован и работает просто отлично.

Используйте селеновую проволоку.

Пример кода из документации:

      options = {
   'proxy': {
        'http': 'socks5://user:pass@192.168.10.100:8888',
        'https': 'socks5://user:pass@192.168.10.100:8888',
        'no_proxy': 'localhost,127.0.0.1'
    }
}
driver = webdriver.Chrome(seleniumwire_options=options)

Вот быстрое, креативное решение, которое не требует изменения параметров селена или загрузки файла в chromedriver. Он использует pyautogui (может использовать любой пакет python, имитирующий нажатие клавиш) для ввода деталей аутентификации прокси. Он также использует многопоточность для учета всплывающего окна проверки подлинности Chrome, которое в противном случае приостановило бы выполнение сценария.

import time
from threading import Thread
import pyautogui
from selenium.webdriver.chrome.options import Options
from selenium import webdriver

hostname = "HOST_NAME"
port = "PORT"
proxy_username = "USERNAME"
proxy_password = "PASSWORD"

chrome_options = Options()
chrome_options.add_argument('--proxy-server={}'.format(hostname + ":" + port))
driver = webdriver.Chrome(options=chrome_options)


def enter_proxy_auth(proxy_username, proxy_password):
    time.sleep(1)
    pyautogui.typewrite(proxy_username)
    pyautogui.press('tab')
    pyautogui.typewrite(proxy_password)
    pyautogui.press('enter')


def open_a_page(driver, url):
    driver.get(url)


Thread(target=open_a_page, args=(driver, "http://www.example.com/")).start()
Thread(target=enter_proxy_auth, args=(proxy_username, proxy_password)).start()

ПРИМЕЧАНИЕ. Для любого серьезного проекта или набора тестов я бы рекомендовал выбрать более надежное решение. Однако, если вы только экспериментируете и вам требуется быстрое и эффективное решение, это вариант.

Я искал тот же ответ, но только для кода Java, так что вот мой вариант кода @itsmnthn Python.

Не забудьте изменить поля String класса MainTest на свой IP, порт, логин, пароль и путь chromeDriver.

      import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class MainTest {
    private static final String PROXY_HOST = "127.0.0.1";
    private static final String PROXY_PORT = "8080";
    private static final String PROXY_USER = "login";
    private static final String PROXY_PASS = "password";
    private static final String CHROMEDRIVER_PATH = "chromeDriverPath";
    private static final String PROXY_OPTION_TEMPLATE = "--proxy-server=http://%s";

    public static void main(String[] args) throws IOException {
        System.setProperty("webdriver.chrome.driver", CHROMEDRIVER_PATH);
        ChromeOptions options = new ChromeOptions();
        String manifest_json = "{\n" +
                "  \"version\": \"1.0.0\",\n" +
                "  \"manifest_version\": 2,\n" +
                "  \"name\": \"Chrome Proxy\",\n" +
                "  \"permissions\": [\n" +
                "    \"proxy\",\n" +
                "    \"tabs\",\n" +
                "    \"unlimitedStorage\",\n" +
                "    \"storage\",\n" +
                "    \"<all_urls>\",\n" +
                "    \"webRequest\",\n" +
                "    \"webRequestBlocking\"\n" +
                "  ],\n" +
                "  \"background\": {\n" +
                "    \"scripts\": [\"background.js\"]\n" +
                "  },\n" +
                "  \"minimum_chrome_version\":\"22.0.0\"\n" +
                "}";

        String background_js = String.format("var config = {\n" +
                "  mode: \"fixed_servers\",\n" +
                "  rules: {\n" +
                "    singleProxy: {\n" +
                "      scheme: \"http\",\n" +
                "      host: \"%s\",\n" +
                "      port: parseInt(%s)\n" +
                "    },\n" +
                "    bypassList: [\"localhost\"]\n" +
                "  }\n" +
                "};\n" +
                "\n" +
                "chrome.proxy.settings.set({value: config, scope: \"regular\"}, function() {});\n" +
                "\n" +
                "function callbackFn(details) {\n" +
                "return {\n" +
                "authCredentials: {\n" +
                "username: \"%s\",\n" +
                "password: \"%s\"\n" +
                "}\n" +
                "};\n" +
                "}\n" +
                "\n" +
                "chrome.webRequest.onAuthRequired.addListener(\n" +
                "callbackFn,\n" +
                "{urls: [\"<all_urls>\"]},\n" +
                "['blocking']\n" +
                ");", PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS);

        FileOutputStream fos = new FileOutputStream("proxy_auth_plugin.zip");
        ZipOutputStream zipOS = new ZipOutputStream(fos);

        createFile("manifest.json", manifest_json);
        createFile("background.js", background_js);

        File file = new File("proxy_auth_plugin.zip");
        writeToZipFile("manifest.json", zipOS);
        writeToZipFile("background.js", zipOS);
        zipOS.close();
        fos.close();
        options.addExtensions(file);

        WebDriver driver = new ChromeDriver(options);
        try {
            driver.get("https://2ip.ru");
        } finally {
            driver.close();
        }

    }

    public static void writeToZipFile(String path, ZipOutputStream zipStream) throws FileNotFoundException, IOException {
        System.out.println("Writing file : '" + path + "' to zip file");
        File aFile = new File(path);
        FileInputStream fis = new FileInputStream(aFile);
        ZipEntry zipEntry = new ZipEntry(path);
        zipStream.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipStream.write(bytes, 0, length);
        }
        zipStream.closeEntry();
        fis.close();
    }

    public static void createFile(String filename, String text) throws FileNotFoundException {
        try (PrintWriter out = new PrintWriter(filename)) {
            out.println(text);
        }
    }


}

После нескольких часов копания с той же проблемой, что и у вас, я наткнулся на этот веб-сайт https://botproxy.net/docs/how-to/setting-chromedriver-proxy-auth-with-selenium-using-python/. Я проверил это и отлично сработал.

import os
import zipfile

from selenium import webdriver

PROXY_HOST = 'x.botproxy.net'  # rotating proxy
PROXY_PORT = 8080
PROXY_USER = 'proxy-user'
PROXY_PASS = 'proxy-password'


manifest_json = """
{
    "version": "1.0.0",
    "manifest_version": 2,
    "name": "Chrome Proxy",
    "permissions": [
        "proxy",
        "tabs",
        "unlimitedStorage",
        "storage",
        "<all_urls>",
        "webRequest",
        "webRequestBlocking"
    ],
    "background": {
        "scripts": ["background.js"]
    },
    "minimum_chrome_version":"22.0.0"
}
"""

background_js = """
var config = {
        mode: "fixed_servers",
        rules: {
          singleProxy: {
            scheme: "http",
            host: "%s",
            port: parseInt(%s)
          },
          bypassList: ["localhost"]
        }
      };

chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

function callbackFn(details) {
    return {
        authCredentials: {
            username: "%s",
            password: "%s"
        }
    };
}

chrome.webRequest.onAuthRequired.addListener(
            callbackFn,
            {urls: ["<all_urls>"]},
            ['blocking']
);
""" % (PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS)


def get_chromedriver(use_proxy=False, user_agent=None):
    path = os.path.dirname(os.path.abspath(__file__))
    chrome_options = webdriver.ChromeOptions()
    if use_proxy:
        pluginfile = 'proxy_auth_plugin.zip'

        with zipfile.ZipFile(pluginfile, 'w') as zp:
            zp.writestr("manifest.json", manifest_json)
            zp.writestr("background.js", background_js)
        chrome_options.add_extension(pluginfile)
    if user_agent:
        chrome_options.add_argument('--user-agent=%s' % user_agent)
    driver = webdriver.Chrome(
        os.path.join(path, 'chromedriver'),
        chrome_options=chrome_options)
    return driver

def main():
    driver = get_chromedriver(use_proxy=True)
    #driver.get('https://www.google.com/search?q=my+ip+address')
    driver.get('https://httpbin.org/ip')

if __name__ == '__main__':
    main()

Поскольку не представляется возможным напрямую настроить Chromedriver для использования прокси-сервера, требующего аутентификации, вы можете использовать локальный нисходящий прокси-сервер, который не требует аутентификации. Затем этот локальный прокси-сервер отправляет все запросы на ваш «настоящий» прокси-сервер, который вы хотели использовать в первую очередь, с необходимой аутентификацией.

Для этого я использовал tinyproxy . Вы можете добавить следующую строку в конфигурацию tinyproxy (tinyproxy.conf):

      upstream http user:pass@host:port

Обязательно замените пользователя, пароль, хост и порт значениями прокси-сервера, который вы хотите использовать.

Затем вы можете настроить свой Chromedriver для использования tinyproxy, как уже описано в предыдущих ответах. Tinyprox по умолчанию работает на порту 8888, поэтому вы можете связаться с ним по адресу 127.0.0.1:8888. Как уже упоминалось в этом ответе , довольно просто использовать прокси без аутентификации:

      chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--proxy-server=127.0.0.1:8888')
driver = webdriver.Chrome(chrome_options=chrome_options)

У меня была та же проблема - и разве нельзя объединить функцию selenium-wire с функцией headless из опций - например, для меня этот код работал - что-то не так?

      from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options
import os, sys, time
from dotenv import load_dotenv, find_dotenv

path = os.path.abspath (os.path.dirname (sys.argv[0]))
cd = '/chromedriver.exe'
load_dotenv(find_dotenv()) 
PROXY_CHEAP_USER = os.environ.get("PROXY_CHEAP_USER")
PROXY_CHEAP_PW= os.environ.get("PROXY_CHEAP_PW")
PROXY_HOST = 'proxyhost.com'  # rotating proxy or host
PROXY_PORT = port # port
PROXY_USER = PROXY_CHEAP_USER # username
PROXY_PASS = PROXY_CHEAP_PW # password

options = Options()
options.add_argument('--headless')
options.add_argument("--window-size=1920x1080")
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')

options_seleniumWire = {
    'proxy': {
        'https': f'https://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}',
    }
}
 
driver = webdriver.Chrome (path + cd, options=options, seleniumwire_options=options_seleniumWire)
driver.get("https://ifconfig.co/")

Думаю, это решение тоже работает в безголовом режиме.

Есть более простой способ, как сделать аутентификацию на прокси с помощью селена! Не знаю с какой версии работает, но в selenium-api-4.5.3 для java есть интерфейсHasAuthentication. Вы можете использоватьregisterметод после инициализации драйвера для установки пользователя и пароля для всего браузера.

Это сработало для меня с хромом:

      ((ChromiumDriver) driver).register(() -> new UsernameAndPassword("USER", "PASS"));

и установите прокси в настройках

      ChromeOptions options = new ChromeOptions();
options.setCapability("proxy", initProxy());
new ChromeDriver(options);

у меня тоже работает в безголовом режиме.

Вот манифест версии 3, сопровождающий последние версии решения Chrome и @itsmnthn.

      {
    "version": "1.0.0",
    "manifest_version": 3,
    "name": "Chrome Proxy",
    "permissions": [
        "proxy",
        "tabs",
        "unlimitedStorage",
        "storage",
        "webRequest",
        "webRequestAuthProvider"
        ],
    "host_permissions": [
        "<all_urls>"
    ],
    "background": {
        "service_worker": "background.js"
    },
    "minimum_chrome_version":"22.0.0"
}

И класс С#, который решает эту проблему (опять же, на основе решения @itsmnthn)

      public class ProxiedChromeClient : IDisposable
{
    private const string MANIFEST_JSON = @"
    {
        ""version"": ""1.0.0"",
        ""manifest_version"": 3,
        ""name"": ""Chrome Proxy"",
        ""permissions"": [
            ""proxy"",
            ""tabs"",
            ""unlimitedStorage"",
            ""storage"",
            ""webRequest"",
            ""webRequestAuthProvider""
            ],
        ""host_permissions"": [
            ""<all_urls>""
        ],
        ""background"": {
            ""service_worker"": ""background.js""
        },
        ""minimum_chrome_version"":""22.0.0""
    }";

    private const string BACKGROUND_JS = @"
    var config = {{
        mode: ""fixed_servers"",
        rules: {{
            singleProxy: {{
                scheme: ""{0}"",
                host: ""{1}"",
                port: parseInt({2})
            }},
            bypassList: [""localhost""]
        }}
    }};

    chrome.proxy.settings.set({{value: config, scope: ""regular""}}, function() {{}});

    function callbackFn(details) {{
        return {{
            authCredentials: {{
                username: ""{3}"",
                password: ""{4}""
            }}
        }};
    }}

    chrome.webRequest.onAuthRequired.addListener(
        callbackFn,
        {{urls: [""<all_urls>""]}},
        ['blocking']
    );";

    protected ProxiedChromeClient(ProxyInfo proxy = null)
    {
        var options = new ChromeOptions();
        if (proxy != null)
        {
            extensionPath = CreateProxyExtension(proxy);
            options.AddExtension(extensionPath);
        }

        chromeDriverInstance = new ChromeDriver(options);
    }


    protected readonly ChromeDriver chromeDriverInstance;
    private readonly object @lock = new();
    private readonly string extensionPath;

    private static string CreateProxyExtension(ProxyInfo proxy)
    {
        // per https://stackoverflow.com/a/55582859/307584
        var tempFile = Path.GetTempFileName();
        using var z = new ZipArchive(new FileStream(tempFile, FileMode.Create), ZipArchiveMode.Create);
        var entry = z.CreateEntry("manifest.json");
        using (var writer = new StreamWriter(entry.Open()))
        {
            writer.Write(MANIFEST_JSON);
        }

        entry = z.CreateEntry("background.js");
        var url = new Uri(proxy.Url);
        using (var writer = new StreamWriter(entry.Open()))
        {
            writer.Write(BACKGROUND_JS, url.Scheme, url.Host, url.Port, proxy.User, proxy.Password);
        }

        return tempFile;
    }

    public void Dispose()
    {
        lock (@lock)
        {
            chromeDriverInstance.Quit();
            if (extensionPath != null)
            {
                File.Delete(extensionPath);
            }
        }
    }
}

Попутно в обновлениях решение, использующее расширение, не работает (по крайней мере, windows), в то время как mac и linux работают. Думаю это был chromedriver v2.44 последняя рабочая версия с расширениями

Мы создали общедоступное решение с открытым исходным кодом для решения именно этого случая, объединив эти замечательные ответы в этой теме и некоторые другие ответы о том, как правильно включить его в Chrome. Начиная с версии 114, в манифест.json были внесены некоторые существенные изменения. Пакет pypi устраняет все трудности, связанные с аутентификацией прокси-серверов в Selenium. Мы планируем поддерживать его, поскольку в значительной степени полагаемся на него для корпоративных приложений.

Просто беги

      pip install selenium-authenticated-proxy

Вот как вы можете настроить его с помощью веб-драйвера:

      from selenium import webdriver
from selenium_authenticated_proxy import SeleniumAuthenticatedProxy

# Initialize Chrome options
chrome_options = webdriver.ChromeOptions()

# Initialize SeleniumAuthenticatedProxy
proxy_helper = SeleniumAuthenticatedProxy(proxy_url="http://username:password@proxy-server.com")

# Enrich Chrome options with proxy authentication
proxy_helper.enrich_chrome_options(chrome_options)

# Start WebDriver with enriched options
driver = webdriver.Chrome(chrome_options=chrome_options)

# Your automation or scraping code here

Вы можете указать собственную папку для временного хранения созданных расширений Chrome.

      proxy_helper = SeleniumAuthenticatedProxy(proxy_url="http://username:password@proxy-server.com", tmp_folder="/path/to/tmp/folder")

Есть несколько обходных путей для этой проблемы, но в настоящее время невозможно разрешить диалоговое окно аутентификации в Selenium. Смотрите этот выпуск:

В настоящее время нет способа обрабатывать запросы HTTP-аутентификации при переходе на страницу, работает только предварительная аутентификация с именем пользователя/паролем в URL-адресе (и, по-видимому, не без обходных путей в некоторых браузерах, таких как IE).

Другие вопросы по тегам