Используем Proxi в Selenium
Привет, Хабр. Вряд ли эта статья откроет Америку для прожженных разработчиков «парсеров» или тестировщиков, но должна помочь тем, кто работает с Selenium время от времени.
Если вы иногда занимаетесь автоматизированным сбором информации с веб-ресурсов (т.н. веб-скрапинг или парсинг), то однозначно сталкивались с проблемой, что некоторые ресурсы недоступны из некоторых регионов, по разным причинам. Сейчас этой проблемы стало даже чуточку больше. И для преодоления этого препятствия нам помогают прокси-серверы (промежуточные серверы). Однако, если в части библиотек для работы с запросами использование прокси является очевидным решением, идущим из коробки, то такой инструмент как Selenium очевидного встроенного решения или не имеет, или я не смог его обнаружить. Я не смог его обнаружить, в том числе, и на Хабре, поэтому решил это исправить.
Далее приведу некоторые примеры с использованием Python, но привязки к языку не будет. Решение универсальное, связанное с написанием расширения для веб-драйвера.
В Python для работы с HTTP-запросами любого уровня сложности вполне достаточно встроенной библиотеки Requests. А для использования прокси с библиотекой, достаточно всего лишь передать данные о сервере в качестве аргумента. Например, так:
import requests
proxies = {
'http': 'http://login:password@ip:port',
'https': 'http://login:password@ip:port'
}
url = "https://badsite.com/"
response = requests.get(url, proxies=proxies)
Но для работы со многими современными веб-ресурсами этой библиотеки недостаточно. Например, она не поддерживает JS и нужные данные просто не всегда подгружаются, а ответ приходит неполный. В таких случаях и нужна связка с Selenium, который автоматизирует браузер, может обработать любую веб-страницу, обойти защиту от роботов и так далее.
Разумеется, если вы попробуете открыть с помощью Selenium ресурс, который недоступен из вашего региона, ничего не выйдет. Можно придумать много вариантов решения, но как по мне, самый удобный способ настройки прокси в Selenium- это написать прокси-расширение. В моем случае это будет расширение для веб-драйвера Chrome.
Допустим, у вас есть проект с логикой работы Selenium для получения HTML в отдельном файле main.py. Теперь в директории проекта создадим папку proxi_extension и добавим в неё два файла:
manifest.json с таким наполнением:
{
"version": "1.0.0",
"manifest_version": 2,
"name": "Chrome Proxy",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
},
"minimum_chrome_version": "22.0.0"
}
background.js с таким наполнением:
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "http",
host: "ip_address",
port: parseInt("8000")
},
bypassList: ["localhost"]
}
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
return {
authCredentials: {
username: "login",
password: "password"
}
};
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: [""]},
['blocking']
);
В background.js необходимо лишь заменить значения host, port, username и password на нужные.
Далее возвращаемся к файлу main.py и подключаем к веб-драйверу написанное расширение, указав путь к нему в соответствующем аргументе:
from loggers import logger # уже настроенный логгер
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def get_html(url: str) -> str:
"""
Возвращает HTML.
"""
chrome_options = Options()
chrome_options.add_argument(f"--load-extension={'/home/username/my_project/proxi_extension'}") # подключаем расширение с прокси
driver = webdriver.Chrome(options=chrome_options)
driver.set_page_load_timeout(5)
try:
driver.get(url)
except Exception as e:
logger.error(e)
finally:
html = driver.page_source
driver.quit()
return html
Вот и весь способ. Теперь автоматизированный Chrome будет открывать всё, что не заблокировано в регионе, в котором установлен прокси-сервер.
Надеюсь, что я не побаловал вас диким баяном и кому-то, да помог. Хорошего дня.