selenium结合Browsermob-Proxy获取浏览器Network请求和响应

python 2020-03-10 pythion selenium browsermobproxy network 774

有些时候使用 Selenium 有一些不足,比如现在很多网站数据都是通过json结构的接口来交互,通过分析报文的方式直接发包可以直接拿到json数据,数据不但全而且还很好解析,这比解析html网页容易多了。另一个非常重要的问题就是,很多时候一些接口返回的关键信息是不在html网页上显示的,通过 Selenium 拿到的 page_source 便没有这些字段。
那么如何解决这些问题呢?我们在做爬虫开发的时候经常用到浏览器的开发者工具,分析网页元素,查看资源加载(Network)等。Selenium + Webdriver 虽然能够定位DOM元素、操作页面、获取网页等。但是 Selenium 终归只能处理“结果”,它无法得知浏览器请求的数据接口信息。如果我们能像浏览器Network那样获取到所有接口的请求和返回信息,那么问题不都解决了么。

Network

Web测试的时候,我们经常用到浏览器的开发者工具,分析网页元素,样式(Elements),查看资源加载性能(Network),查看控制台信息(Console)甚至client端源码(Sources)等。

Selenium Webdriver能够定位DOM元素,与之交互,读取样式以进行验证等。但是Selenium只处理“结果”,它无法得知浏览器的网络控制台的信息。如果浏览器在渲染出页面之前,从某个站点加载大量资源信息,Selenium无法知道。

解决方案是,可以使webdriver通过proxy访问网络,再收集proxy端的HAR内容,以分析web应用的行为。

Browsermob-Proxy
Browsermob-Proxy是一个开源的Java编写的基于LittleProxy的代理服务。Browsermob-Proxy的具体流程有点类似与Flidder或Charles。即开启一个端口并作为一个标准代理存在,当HTTP客户端(浏览器等)设置了这个代理,则可以抓取所有的请求细节并获取返回内容。
Browsermob-Proxy安装
直接到项目的github上下载打好的压缩包即可:
https://github.com/lightbody/browsermob-proxy/releases
支持Linux和Windows。
安装对应的python包:

pip install browsermob-proxy

启停Proxy

from browsermobproxy import Server
 
base_url='https://www.baidu.com/'
server = Server(r'<path-to-browsermob-proxy>\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat')
server.start()
proxy = server.create_proxy()

配置并启动Selenium webdriver

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
 
chrome_options = Options()
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))
chrome_options.add_argument('--disable-gpu')
 
chrome_driver = r'<path-to-chromedriver.exe>\chromedriver.exe'
 
driver = webdriver.Chrome(executable_path=chrome_driver, chrome_options = chrome_options)

以目标URL配置一个新的HAR并获取HAR内容

proxy.new_har(base_url)
driver.get(base_url)


分析HAR内容

result = proxy.har
 
for entry in result['log']['entries']:
    print(entry['request']['url'])
 
server.stop()
driver.quit()


例子:这里以抓取抖音用户视频为例,目标url:https://www.iesdouyin.com/share/user/63174596206 ,使用Selenium + Webdriver + Browsermob-Proxy 获取接口返回的数据。

通过har就能获取浏览器所有的请求,然后过滤出数据接口就OK,而且拿到的结构和在浏览器开发者模式Network中看到的是一样的。

通过har获取浏览器所有的请求

from selenium import webdriver
from browsermobproxy import Server
 
from selenium.webdriver.chrome.options import Options
 
server = Server(r'Browsermob-Proxy下载包解压路径\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat')
server.start()
proxy = server.create_proxy()
 
chrome_options = Options()
chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))
 
driver = webdriver.Chrome(chrome_options=chrome_options)
 
base_url = "https://www.iesdouyin.com/share/user/63174596206"
proxy.new_har("douyin", options={'captureHeaders': True, 'captureContent': True})
driver.get(base_url)
 
 
result = proxy.har
 
for entry in result['log']['entries']:
    _url = entry['request']['url']
    # 根据URL找到数据接口
    if "/api/v2/aweme/post" in _url:
        _response = entry['response']
        _content = _response['content']['text']
        # 获取接口返回内容
        print(_content)
 
server.stop()
driver.quit()