Python+Selenium+Browsermob-Proxy 爬虫-获取浏览器Network请求和响应

1.问题     

        自从发现 Selenium 这块新大陆后,许多异步加载、js加密、动态Cookie等问题都变得非常简单,大大简化了爬虫的难度。但是有些时候使用 Selenium 仍然有一些缺陷,比如现在很多网站数据都是通过json结构的接口来交互,通过分析报文的方式直接发包可以直接拿到json数据,数据不但全而且还很好解析,这比解析html网页容易多了。另一个非常重要的问题就是,很多时候一些接口返回的关键信息是不在html网页上显示的,通过 Selenium 拿到的 page_source 便没有这些字段。

        那么如何解决这些问题呢?我们在做爬虫开发的时候经常用到浏览器的开发者工具,分析网页元素,查看资源加载(Network)等。Selenium + Webdriver 虽然能够定位DOM元素、操作页面、获取网页等。但是 Selenium 终归只能处理“结果”,它无法得知浏览器请求的数据接口信息。如果我们能像浏览器Network那样获取到所有接口的请求和返回信息,那么问题不都解决了么。例如下图:

        而本文介绍的解决方案是:使用 webdriver 通过proxy访问网络,再收集proxy端的请求和返回内容,从而获取到数据,而这个proxy就类似于 fiddler 抓包软件。而文本介绍使用的是 Browsermob-Proxy

2.Browsermob-Proxy

       Browsermob-Proxy是一个开源的Java编写的基于LittleProxy的代理服务。Browsermob-Proxy的具体流程有点类似与Flidder或Charles。即开启一个端口并作为一个标准代理存在,当HTTP客户端(浏览器等)设置了这个代理,则可以抓取所有的请求细节并获取返回内容。

安装

       直接到项目的github上下载打好的压缩包即可:https://github.com/lightbody/browsermob-proxy/releases ,支持Linux和Windows。

安装对应的python包:

pip install browsermob-proxy

        这里以抓取情咖主播列表为例,目标url:http://www.liuyanlin.cn/ht_list3.html,使用Selenium + Webdriver + Browsermob-Proxy 获取接口返回的数据。

开启Proxy

下载好browsermob-proxy之后,放在指定一个目录,例如我这里是 D:\apk\browsermob-proxy-2.1.4-bin\browsermob-proxy-2.1.4这个路径下,所以下面示例代码如:

from browsermobproxy import Server

server = Server("D:\\apk\lyl\\browsermob-proxy-2.1.4\\bin\\browsermob-proxy.bat")
server.start()
proxy = server.create_proxy()

配置Proxy启动WebDriver

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))

driver = webdriver.Chrome(chrome_options=chrome_options)

获取返回内容

#要访问的地址
base_url = "http://www.liuyanlin.cn/ht_list3.html"
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']
    print(_url)
    # # 根据URL找到数据接口,这里要找的是 http://git.liuyanlin.cn/get_ht_list 这个接口
    if "http://git.liuyanlin.cn/get_ht_list" in _url:
        _response = entry['response']
        _content = _response['content']
        # 获取接口返回内容
        print(_content)

server.stop()
driver.quit()

下面是完整代码:

from browsermobproxy import Server
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

server = Server("D:\\apk\lyl\\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 = "http://www.liuyanlin.cn/ht_list3.html"
proxy.new_har("ht_list2", options={ 'captureContent': True})

driver.get(base_url)
#此处最好暂停几秒等待页面加载完成,不然会拿不到结果
time.sleep(3)
result = proxy.har

for entry in result['log']['entries']:
    _url = entry['request']['url']
    print(_url)
    # # 根据URL找到数据接口,这里要找的是 http://git.liuyanlin.cn/get_ht_list 这个接口
    if "http://git.liuyanlin.cn/get_ht_list" in _url:
        _response = entry['response']
        _content = _response['content']
        # 获取接口返回内容
        print(_response)

server.stop()
driver.quit()

运行结果如图所示,可以看到,成功拿到数据:

补充知识点:

由于Browsermob-Proxy本身自己就是一个代理服务,那么有时候我们有这种需求,比如某个网站封ip封得厉害,这时候就需要使用代理ip了,那么怎么将Browsermob-Proxy的出口ip改成一个买的代理ip了,也就是所谓的实现二级代理。例如我这里有个代理ip是可以用的:61.155.141.13:20345  接下来我要将这个代理ip挂到Browsermob-Proxy服务上,其实很简单,只需要在创建server的时候带上一个参数,例如下面的代码:

proxy = server.create_proxy({"httpProxy":"61.155.141.13:20345"})
发布了130 篇原创文章 · 获赞 84 · 访问量 94万+

猜你喜欢

转载自blog.csdn.net/qq_32502511/article/details/101536325
今日推荐