signed

QiShunwang

“诚信为本、客户至上”

Selenium3 Python WebDriver API源码探析(13)FireFox设置代理

2021/3/21 0:33:59   来源:

数据采集过程中经常需要用到代理,Selenium也支持代理功能,selenium\webdriver\common\proxy.py提供了代理数据结构的实现。Selenium实现代理的方法有很多种,不同WebDriver实现实现代理的方法也不尽相同。由于经常使用FireFox浏览器,因此,以geckodriver作为案例来演示代理功能。

官方文档推荐使用Capabilities

根据《Selenium3 Python WebDriver API源码探析(11)WebDriver Capabilities(驱动功能)概述,FirefoxOptions》可知,'proxy'是标准Capabilities对象的其中一项,值类型为JSON。
因此,可通过Capabilities设置代理。这也是官方文档使用的方式,使用起来比较简洁。

案例:通过Capabilities设置代理

from selenium import webdriver
# 初始化FirefoxOptions
options = webdriver.FirefoxOptions()

# 代理
PROXY = '15.207.201.85:80'
# 通过`Capabilities`设置代理
webdriver.DesiredCapabilities.FIREFOX['proxy'] = {
    "httpProxy": PROXY,
    "ftpProxy": PROXY,
    "sslProxy": PROXY,
    "proxyType": "MANUAL",

}
# 加载自定义功能
driver = webdriver.Firefox()
# 在结果中看到orgin的值为15.207.201.85:80,说明代理设置成功
driver.get("http://httpbin.org/get")
print(driver.capabilities)

通过首选项成功设置

通过首选项设置代理也是一个可行的办法。通过Optionsprofile等对象均可设置首选项。

from selenium import webdriver
from selenium.webdriver.common.proxy import ProxyType,Proxy
# 初始化FirefoxOptions
options =webdriver.FirefoxOptions()
options.set_preference("network.proxy.type", 1)
# ip及其端口号配置为 http 协议代理
options.set_preference("network.proxy.http", "15.207.201.85")
options.set_preference("network.proxy.http_port", 80)

# 所有协议共用一种 ip 及端口,如果单独配置,不必设置该项,因为其默认为 False
options.set_preference("network.proxy.share_proxy_settings", True)
# 加载自定义选项
driver=webdriver.Firefox(options=options)
driver.get("http://httpbin.org/get")
print(driver.capabilities )

失败案例

WebDriver实例化时提供proxy参数

根据文档可知,在WebDriver实例化时可提供proxy参数,参数值为Proxy对象。按照这种方式,最终代理未成功设置。
查询Stack Overflow等网站得知,该问题是一个历史悠久的BUG……

from selenium import webdriver
from selenium.webdriver.common.proxy import *

myProxy = '15.207.201.85:80'
proxy = Proxy({
                'proxyType': ProxyType.MANUAL,
                'httpProxy': myProxy,
                'sslProxy': myProxy,
                'ftpProxy': myProxy,
                'noProxy':''})

driver = webdriver.Firefox(proxy=proxy)
driver.get("http://httpbin.org/get")
print(driver.capabilities )

利用opitons.proxy()方法设置

根据selenium\webdriver\firefox\options.py中的Options类源码可知,Options类的proxy( value)可设置代理,参数值为Proxy对象。按照这种方式,最终代理未成功设置。

案例

from selenium import webdriver
from selenium.webdriver.common.proxy import ProxyType,Proxy


# 代理
PROXY = '15.207.201.85:80'
# 代理格式
proxy1 = Proxy({
'proxyType': ProxyType.MANUAL, 
'httpProxy': PROXY, 
'ftpProxy': PROXY, 
'sslProxy': PROXY, 
'noProxy': ''
})

# 初始化FirefoxOptions
options =webdriver.FirefoxOptions()
print(options is not None)
options.proxy(proxy1)
driver=webdriver.Firefox(options=options)

driver.get("http://httpbin.org/get")
print(driver.capabilities )
True
Traceback (most recent call last):
  File "proxy4.py", line 19, in <module>
    options.proxy(proxy1)
TypeError: 'NoneType' object is not callable

解析

输入提示 options'NoneType',但是options不为None
原因可能如下:options在实例化时,options._proxyoptions.proxy默认值为None

@property
def proxy(self):
    """ returns Proxy if set otherwise None."""
    return self._proxy

@proxy.setter
def proxy(self, value):
    if not isinstance(value, Proxy):
        raise InvalidArgumentException("Only Proxy objects can be passed in.")
    self._proxy = value