微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

百度总监一文快速教会你Selenium如何设置代理实现抓取HTTPS请求

起因
Selenium本身是不支持HTTP请求抓取的,因为其团队认为这个不是selenium要解决的问题(确实也是)。所以推荐使用一个相关联的项目 – browserMobProxy。
具体项目首页见相关GitHub。

尝试
因为项目需要,所以就研究了下browserMobProxy。它其实是一个java实现的开源代理项目,它与普通的代理不同之处在于:

支持REST API接口(可以通过http请求来动态创建代理服务)
认启动的是一个代理Manager,它会管理N多个代理服务(我们真正使用的就是这个代理服务)
可以支持动态的代理配置
一张图看懂browserMobProxy的业务逻辑。

在这里插入图片描述

即在使用代理之前,需要先启动代理Manager;而这个Manager提供了REST API接口,支持动态创建代理服务。(它会维护一批申请过的代理服务)之后我们使用的其实都是新申请的代理服务。(所以它并不是一个代理实例,而是一个代理管理服务)
在这里向大家推荐一个学习资料群:175317069

使用
要使用browserMobProxy首先你需要启动它的代理Manager。有3种方式:

直接通过bin目录下的脚本文件启动(如:browsermob-proxy.bat)
在程序中动态执行脚本文件
JAVA项目可以导入到项目中通过SDK启动
browserMobProxy的代理Manager启动后,就可以向它申请具体的代理服务了。主要有2种方式:

REST API方式
JAVA的SDK方式
由于这里是讲Python相关的,所以后面只讲REST API方式。启动代理Manager和申请代理服务的代码如下:

broWSERMOBPROXY = r"D:\browsermob-proxy-2.1.1\bin\browsermob-proxy.bat"
server = browsermobproxy.Server(broWSERMOBPROXY, {'port': 8080})    # 初始化一个代理Manager服务,并监听8080端口
server.start()                                      # 启动代理Manager服务
proxy = server.create_proxy()                       # 向代理Manager服务申请一个代理服务,会使用认端口8081
print(proxy.port)

上述代码是在程序中执行了browserMobProxy的启动脚本,然后申请了一个代理服务。当然,你还可以先手动启动browserMobProxy,接着在程序中就可以直接申请代理服务即可。(也可以是远程服务器上的地址)

proxy = browsermobproxy.Client('http://localhost:8080')     # 向已有代理Manager服务申请一个代理服务
DEMO

光有上面的代码还不够,我们需要和Selenium代理整合之后,才能知道是否可以满足我们的需求。在具体执行代码之前你需要安装2个前提库:

    pip install selenium
    pip install browsermob

然后就可以执行如下代码了。

def set_proxy_for_ff():
    profile = webdriver.FirefoxProfile()
    driver = webdriver.Firefox(firefox_profile=profile, proxy=proxy.selenium_proxy())   # 配置selenium使用指定的代理服务
    proxy.new_har("test", options={'captureContent': True, 'captureHeaders': True})     # 开启代理监控,如果不监控会拿不到请求内容
    driver.get("http://www.baidu.cn")           # 访问页面
    # Todo:其它页面操作
    proxy.wait_for_traffic_to_stop(1000, 6000)  # 停止代理监控
    print(proxy.har)                            # 打印请求日志信息
 
 
def set_proxy_for_chrome():
    dc = webdriver.DesiredCapabilities
    proxy.add_to_capabilities(dc)
    driver = webdriver.Chrome(desired_capabilities=dc)   # 配置selenium使用指定的代理服务
    proxy.new_har("test", options={'captureContent': True, 'captureHeaders': True})     # 开启代理监控,如果不监控会拿不到请求内容
    driver.get("http://www.baidu.cn")           # 访问页面
    # Todo:其它页面操作
    proxy.wait_for_traffic_to_stop(1000, 6000)  # 停止代理监控
    print(proxy.har)                            # 打印请求日志信息
 
 
def set_proxy_for_phantomjs():
    dc = webdriver.DesiredCapabilities
    proxy.add_to_capabilities(dc)
    driver = webdriver.PhantomJS(desired_capabilities=dc)   # 配置selenium使用指定的代理服务
    proxy.new_har("test", options={'captureContent': True, 'captureHeaders': True})     # 开启代理监控,如果不监控会拿不到请求内容
    driver.get("http://www.baidu.cn")           # 访问页面
    # Todo:其它页面操作
    proxy.wait_for_traffic_to_stop(1000, 6000)  # 停止代理监控
    print(proxy.har)    

如果一切正常的话,这3个函数都是可以执行的。前提是对应的Webdriver和浏览器得先配置好了。如果你是在远程服务器上启动的代理Manager,记得关掉防火墙。

填坑
这个是针对Python用户的,如果你是java用户则没有这样的苦恼,因为这些功能jar包的SDK中都已经支持了。

启动代理Manager时指定参数
由于支持browserMobProxy的Python库只有一个在pypi上。而该库虽然可以支持基本的使用,但是如果你希望配置更多的参数,则需要自己动手来解决。因为在Python的browsermobproxy库中启动代理Manager时未提供指定启动参数的选项,所以如果你需要在程序里启动代理Manager时带上参数,则有3种方式可以实现:

在启动脚本中添加固定参数
修改Python库支持指定参数
提供一个带参数的命令
接着,就来逐一看下如何去实现。如果是第一种则需修改对应的启动脚本(linux或windows),并设置固定的参数。

@REM -- Regular WinNT shell
set CMD_LINE_ARGS=%* -proxyPortRange 9000-9999 -ttl 600
goto WinNTGetScriptDir
上面是windows启动脚本browsermob-proxy.bat的修改之处,在第二行内容后追加了 -proxyPortRange 9000-9999 -ttl 600参数。如果是linux系统,则修改browsermob-proxy文件,具体修改内容如下:

exec "$JAVACMD" $JAVA_OPTS \
  $EXTRA_JVM_ARGUMENTS \
  -classpath "$CLAsspATH" \
  -Dapp.name="browsermob-proxy" \
  -Dapp.pid="$$" \
  -Dapp.repo="$REPO" \
  -Dbasedir="$BASEDIR" \
  net.lightbody.bmp.proxy.Main \
  "$@" -proxyPortRange 9000-9999 -ttl 600
 

同样是在最后一行追加了指定的参数内容。如果选择第二种方式则需要修改Python的browsermobproxy库(这里不建议),因为第三种方式可以更好的解决这个问题。即把启动字符串修改一个列表即可。

# 原来的启动脚本路径
broWSERMOBPROXY = r"D:\browsermob-proxy-2.1.1\bin\browsermob-proxy.bat"
# 修改为如下
broWSERMOBPROXY = [r"D:\browsermob-proxy-2.1.1\bin\browsermob-proxy.bat", '-proxyPortRange 9000-9999', '-ttl 600']
 

申请代理服务时指定参数
可以指定代理Manager的启动参数后,还需要可以指定代理的启动参数。比如:忽略HTTPS的认证错误。而这里就真的需要修改Python库了。具体的代码修改如下:

# browsermobproxy\client.py 第32行
resp = requests.post('%s/proxy%s' % self.host, urlparams)
# 修改为
resp = requests.post('%s/proxy' % self.host, data=params)

这个可能是作者开发的失误,因为POST正常是不支持URL参数接收。作者可能是希望能打印出来,所以拼接成url串,只是在POST时忘记转回了。

完整代码
from selenium import webdriver
import browsermobproxy

required:
pip install selenium
pip install browsermob

broWSERMOBPROXY = r"D:\browsermob-proxy-2.1.1\bin\browsermob-proxy.bat"

server = browsermobproxy.Server(broWSERMOBPROXY, {‘port’: 8080}) # 初始化一个代理Manager服务,并监听8080端口
server.start() # 启动代理Manager服务
proxy = server.create_proxy() # 向代理Manager服务申请一个代理服务,会使用认端口8081
print(proxy.port)

#proxy = browsermobproxy.Client(‘http://localhost:8080’) # 向已有代理Manager服务申请一个代理服务

def set_proxy_for_ff():
profile = webdriver.FirefoxProfile()
driver = webdriver.Firefox(firefox_profile=profile, proxy=proxy.selenium_proxy()) # 配置selenium使用指定的代理服务
proxy.new_har(“test”, options={‘captureContent’: True, ‘captureHeaders’: True}) # 开启代理监控,如果不监控会拿不到请求内容
driver.get(“http://www.baidu.cn”) # 访问页面
# Todo:其它页面操作
proxy.wait_for_traffic_to_stop(1000, 6000) # 停止代理监控
print(proxy.har) # 打印请求日志信息

def set_proxy_for_chrome():
dc = webdriver.DesiredCapabilities
proxy.add_to_capabilities(dc)
driver = webdriver.Chrome(desired_capabilities=dc) # 配置selenium使用指定的代理服务
proxy.new_har(“test”, options={‘captureContent’: True, ‘captureHeaders’: True}) # 开启代理监控,如果不监控会拿不到请求内容
driver.get(“http://www.baidu.cn”) # 访问页面
# Todo:其它页面操作
proxy.wait_for_traffic_to_stop(1000, 6000) # 停止代理监控
print(proxy.har) # 打印请求日志信息

def set_proxy_for_phantomjs():
dc = webdriver.DesiredCapabilities
proxy.add_to_capabilities(dc)
driver = webdriver.PhantomJS(desired_capabilities=dc) # 配置selenium使用指定的代理服务
proxy.new_har(“test”, options={‘captureContent’: True, ‘captureHeaders’: True}) # 开启代理监控,如果不监控会拿不到请求内容
driver.get(“http://www.baidu.cn”) # 访问页面
# Todo:其它页面操作
proxy.wait_for_traffic_to_stop(1000, 6000) # 停止代理监控
print(proxy.har) # 打印请求日志信息

if ‘main’ == name:
set_proxy_for_ff()
set_proxy_for_chrome()
set_proxy_for_phantomjs()

在这里推荐一个我自己创建的软件测试交流群 ,QQ:642830685,群中会不定期的分享软件测试资源,测试面试题以及行业资讯,大家可以在群中积极交流技术。风里雨里我在群中等你。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐