【java爬虫】selenium+browsermob入门实战

news2025/2/25 21:45:07

在爬虫领域,selenium几乎是最无所不能的一个框架了,在传统的爬虫无能为力的时候,我们可以使用selenium来请求动态页面获取信息。

当然,只有selenium还是不够的,因为使用selenium我们只能获取页面上展示的数据,但是无法获取Network请求和响应结果,有些网页并不会将从接口接收到的所有数据都展示到页面上,为了捕捉到这些信息,我们就需要引入到browsermob。这两个框架的强强联合,几乎可以解决我们99%的需求。

使用selenium接管已开启的浏览器

一般情况下使用selenium都是重新开一个浏览器,但是这样会产生一些问题,比如有一些网站你需要登录后才能查询到信息,如果每次都重新开一个浏览器的话,我们就需要重复进行登录的操作,这样非常繁琐。为了适应这样的场景,我们可以打开一个浏览器,然后让selenium将浏览器接管,这样浏览器就会保留我们的登录信息,selenium可以很方便地开始工作。

为了能让selenium顺利接管浏览器,我们首先需要指定端口号来打开浏览器。

首先找到 chrome.exe 快捷方式指向的具体地址,然后将这个地址加入到环境变量

 

添加完环境变量后,我们就可以使用某个指定的端口打开一个chrome客户端

 

 接着我们在selenium中使用配置信息启动Chrome就可以接管客户端了

使用selenium爬取百度热搜信息

在selenium接管浏览器后,我们就可以进行响应操作。我们这边简单地爬取一下百度首页的热搜信息来熟悉一下操作。

首先介绍一下本文会用到的jar包。

      <dependency>
            <!-- fastjson -->
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>


        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.6.5</version>
        </dependency>


        <dependency>
            <groupId>net.lightbody.bmp</groupId>
            <artifactId>browsermob-core</artifactId>
            <version>2.1.5</version>
        </dependency>

        <dependency>
            <groupId>net.lightbody.bmp</groupId>
            <artifactId>browsermob-legacy</artifactId>
            <version>2.1.5</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.1.1</version>
        </dependency>


        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.0.1-jre</version>
        </dependency>

百度热搜是放在一个<ul>标签下的,并且id为hotsearch-content-wrapper,使用这个id可以找到这个元素,然后逐个遍历其中的<li>就能得到首页的6个热搜信息。

不难发现,每个<li>标签里面都有一个<a>标签用来表示url地址,还有一个<span>标签用来表示热搜的标题,我们主要关注这个两个元素对应的信息

 

 这里简单贴一下selenium中findElement的api

  • findElement(By.id())
  • findElement(By.name())
  • findElement(By.className())
  • findElement(By.tagName())
  • findElement(By.linkText())
  • findElement(By.partialLinkText())
  • findElement(By.xpath())
  • findElement(By.cssSelector())

基本上以上的几个方法就可以解决我们的需求了。

代码非常简单

    @Override
    public void startSelenium() {
        log.debug("开启浏览器");
        System.setProperty("webdriver.chrome.driver", DRIVER_PATH);
        ChromeOptions options = new ChromeOptions();
        options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
        WebDriver driver = new ChromeDriver(options);
        log.debug("浏览器启动成功");
        driver.get("http://www.baidu.com");
        log.debug("开始获取热搜信息");
        WebElement element = driver.findElement(By.id("hotsearch-content-wrapper"));
        List<WebElement> element_lis = element.findElements(By.tagName("li"));
        for(WebElement el : element_lis) {
            String url = el.findElement(By.tagName("a")).getAttribute("href");
            String title = el.findElement(By.className("title-content-title")).getText();
            log.info(title + "=>" + url);
        }

    }

运行一下代码得到如下信息就代表大功告成啦

使用browsermob获取Network数据

大部分网站使用selenium都可以获取数据,但是有一些网站并不会将所有获取的数据都进行展示,或者说,我们直接读取接口返回的数据会更快速的获取数据,我们这里以淘宝联盟举例。

淘宝联盟的url如下,需要进行登录

阿里妈妈https://pub.alimama.com/portal/v2/pages/promo/goods/index.htm进入到页面后,我们可以发现获取数据的接口是 union.pub.entry,我们可以直接从这个接口获取数据,这样就不需要到页面中去找了。

在编码的时候发现了一个问题,就是使用selenium+browsermob的时候没办法对已经打开的浏览器配置代理信息,所以如果使用selenium接管已经打开的浏览器是拿不到Network数据的,所以本文只能退而求其次,让selenium打开新的浏览器,然后进行登录。

browsermob-proxy +selenium使用 - 知乎browsermob-proxy 一个浏览器的代理 在调试浏览器或者爬取数据的时候,需要使用浏览器的开发者模式,尤其是动态网页,在使用selenium的时候,想要知道到底调用了哪些接口 ##安装 pip install browsermob-proxy这里…https://zhuanlan.zhihu.com/p/363008064我们首先需要实例化browsermob的代理,然后将代理添加到selenium的参数中,接着再实例化selenium,打开chrome浏览器。使用browsermob获取网络请求的方法就是设置两个回调函数,一个是请求的回调函数,一个是响应的回调函数。回调函数的意思就是,有请求或者响应信息的时候,就会执行我们回调函数里面编写的代码。

    public void startSelenium() {

        // 实例化BrowserMob代理
        System.setProperty("webdriver.chrome.driver", DRIVER_PATH);
        BrowserMobProxy browserMobProxy = new BrowserMobProxyServer();
        browserMobProxy.start();
        browserMobProxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
        browserMobProxy.setHarCaptureTypes(CaptureType.RESPONSE_CONTENT);
        browserMobProxy.newHar("kk");
        Proxy seleniumProxy = ClientUtil.createSeleniumProxy(browserMobProxy);

        // 实例化Selenium
        ChromeOptions options = new ChromeOptions();
        options.setProxy(seleniumProxy);
        options.setAcceptInsecureCerts(true);
        //options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
        WebDriver driver = new ChromeDriver(options);


        // 网络请求回调函数
        browserMobProxy.addRequestFilter(new RequestFilter() {
            @Override
            public HttpResponse filterRequest(HttpRequest httpRequest, HttpMessageContents httpMessageContents, HttpMessageInfo httpMessageInfo) {
                // 打印请求信息
                // log.info("request=>" + httpMessageInfo.getUrl());
                return null;
            }
        });

        // 网络响应回调函数
        browserMobProxy.addResponseFilter(new ResponseFilter() {
            @Override
            public void filterResponse(HttpResponse httpResponse, HttpMessageContents httpMessageContents, HttpMessageInfo httpMessageInfo) {
                // 这里获取打印的信息
                log.info(httpMessageInfo.getUrl());
                if(httpMessageInfo.getUrl().equals("https://pub.alimama.com/openapi/param2/1/gateway.unionpub/union.pub.entry")) {
                    // 格式化输出
                    String str = JSONObject.toJSONString(httpMessageContents.getTextContents(), true);
                    System.out.println(str);
                    // 将数据写到文件中
                    try {
                        FileWriter writer = new FileWriter("output.txt");
                        writer.write(str);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        // 打开网页
        driver.get("https://pub.alimama.com/portal/v2/pages/promo/goods/index.htm?pageNum=2");


    }

执行上述代码,打开浏览器并且登录后,我们就可以拿到相应接口的响应信息了,在项目的根目录看到output.txt就代表数据获取成功,可以发现这个接口的响应数据非常大,里面包含的信息非常多。

总结

到这里,本文的主要内容就介绍完了。使用selenium+browsermob可以非常方便地进行网络数据收集,不过我感觉有一个缺点就是运行起来非常慢,在爬下批量数据的情况下可以使用,但是如果要快速爬取大批量数据的话,还是直接用http去请求接口,对于反爬虫机制比较好的接口,可以去研究一下js逆向,selenium相对于直接去请求接口的一大优势就是不用花时间去研究js逆向,直接写代码去获取数据就完事了。

那么本文就到此结束,如果你有什么想和我交流讨论欢迎评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/679561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux驱动入门(四)——内核进程管理

文章目录 前言进程进程描述符及任务结构分配进程描述符进程描述符的存放进程状态设置当前进程状态进程上下文进程家族树 进程创建写时拷贝fork()vfork() 线程在Linux中的实现创建线程内核线程 进程终结删除进程描述符孤儿进程造成的进退维谷 总结 前言 进程是Unix操作系统抽象…

Vue--》Vue3打造可扩展的项目管理系统后台的完整指南(七)

今天开始使用 vue3 ts 搭建一个项目管理的后台&#xff0c;因为文章会将项目的每一个地方代码的书写都会讲解到&#xff0c;所以本项目会分成好几篇文章进行讲解&#xff0c;我会在最后一篇文章中会将项目代码开源到我的GithHub上&#xff0c;大家可以自行去进行下载运行&…

驱动开发:摘除InlineHook内核钩子

在笔者上一篇文章《驱动开发&#xff1a;内核层InlineHook挂钩函数》中介绍了通过替换函数头部代码的方式实现Hook挂钩&#xff0c;对于ARK工具来说实现扫描与摘除InlineHook钩子也是最基本的功能&#xff0c;此类功能的实现一般可在应用层进行&#xff0c;而驱动层只需要保留一…

idea如何使用git指令

&#xff08;1&#xff09;、打开setting,直接搜git (2)、点一下text 如果显示成功就不用管了&#xff0c;但如果失败就要重新设置一下目录&#xff1a; &#xff08;3&#xff09;、找到自己设置gitee ssh目录&#xff1a; 这里我们是不需要用.git对.idea进行管理的&#xff…

vue3原理和源码分析 - VirtualDOM和DOMDIFF

目录 VUE3的h/createVNode函数【vue的概念模型】 Virtual DOM&#xff08;组件化的概念模型&#xff09; VirtualDOM更新 WHY DOM-DIFF&#xff1f; DOM-DIFF原理 DOM-DIFF伪代码 DOM-DIFF分类讨论&#xff1a;属性变更 DOM-DIFF分类讨论&#xff1a;节点类型不同 DOM-…

正负整数小数在内存的存储

目录 补码引入 整数在内存的存储 小数十进制与二进制相互转化 小数的内存存储 本节会主要学习正负的整数小数在内存的存储方式 补码引入 补码在计算机有着重要的地位&#xff0c;计算机本身只能完成的加法&#xff0c;移位运算&#xff0c;减法&#xff0c;乘法&#xff0…

深入解析多人共享云盘:便捷文件协作与分享的全新模式

在当今数字化时代&#xff0c;云盘已成为许多人存储和共享文件的首选方式。但是&#xff0c;传统的个人云盘服务在多人协作方面存在一些限制。为了解决这个问题&#xff0c;多人共享云盘应运而生。什么是多人共享云盘&#xff1f; 多人共享云盘是一种允许多个用户同时访问、编辑…

【数据库六】存储过程

存储过程 1.存储过程概述1.1 存储过程定义1.2 存储过程优点1.3 创建存储过程 2. 存储过程参数2.1 输入参数2.2 输出参数2.3 输入输出参数2.4 存储过程参数总结 3. 删除存储过程4.存储过程的控制语句4.1 条件语句if --else4.2 循环语句4.3 存储过程控制语句总结 1.存储过程概述 …

Qt 实现SQLite全部语法(增删改查、内置函数、高级语法)

Qt 实现SQLite全部语法 【1】SQLite Qt界面设计【2】SQLite Qt数据库创建、打开、关闭、删除【3】SQLite Qt表格的创建【4】SQLite Qt表格的插入【5】SQLite Qt表格的查询【6】SQLite Qt表格的删除【7】SQLite Qt表格的更新【8】SQLite Qt表格的结构【9】SQLite Qt表格的修改【…

Python 教程:从零到大师

首先, 什么是Python? 用python作者Guido van Rossum自己的话来说&#xff0c;Python是这样的一门语言&#xff1a; "它是一门高级编程语言, 它的核心设计理念是让所有代码变得更易阅读&#xff0c;并给开发者们提供一种“仅仅几行代码就能编写编程逻辑”的语法。 那么&am…

SD/StableDiffusion部署图文教程,ai绘画教程,实现谷歌云端零成本部署,中文UI

目录 一、前言 二、准备前提 三、教程说明 四、开始搭建 1、第一步&#xff0c;下载ipynb脚本文件 2、第二步&#xff0c;上传一键脚本文件到谷歌云盘 3、选择该.ipynb文件--右键--打开方式--关联更多应用 4、输入框搜索Colaboratory找到该应用&#xff0c;安装 5、安…

【瑞萨RA6系列】RASC+Keil开发环境搭建和GPIO点灯指南

瑞萨RASCKeil开发环境搭建 一、简单开箱二、资料下载三、芯片简介四、开发环境搭建4.1 安装RASC4.2 安装Keil MDK4.3 安装RA6E1的MDK支持包 五、GPIO点灯指南5.1 创建RASC项目5.2 查阅开发板原理图5.3 设置LED1引脚为输出3.4 编写LED1闪烁的代码5.5 编译Keil项目5.6 修改Keil调…

产品设计.B端设计师不可忽视的产品和用户

B端产品与C端产品不同&#xff0c;前者强调客户价值&#xff0c;企业决策链路长&#xff0c;用户难获得的同时也相对难流失。而作为B端产品设计师&#xff0c;就需要根据B端产品业务特点&#xff0c;从用户、产品等角度进行考量&#xff0c;以求做出符合市场和用户的设计方案。…

【HTTP 协议】

一、HTTP 协议简介 在真实的网络环境中采用 TCP/IP 五层网络传输模型这样的结构传输. 物理层 -> 数据链路层 -> 网络层 -> 传输层 -> 应用层 1. 应用层: 应用层是模型的最顶层&#xff0c;它为用户提供了一种与网络进行通信的方法。应用层包含了各种应用程序&…

【Linux基础及shell脚本】在VMware16中安装CentOS7.6

文章目录 1. Linux和CentOS2. 虚拟机3. 为什么选择在VMware上安装CentOS&#xff1f;4. 准备工作5. 创建新的虚拟机6. 安装CentOS 7.67. 初次启动和设置 在我们了解如何在VMware16中安装CentOS 7.6之前&#xff0c;让我们首先对Linux、CentOS以及虚拟机有一些基本的认识。 1. …

【性能测试一】性能测试概述

目录 &#x1f31f;一、性能测试的基础概念 &#x1f308;1、生活中软件相关的性能问题&#xff1f; &#x1f308;2、性能测试的概念 &#x1f308;3、性能测试与功能测试的区别&#xff1f; &#x1f308;4、什么样的软件属于性能好&#xff1f;什么样的软件属于性能不好…

搭建Vue项目以及项目的常见知识

前言&#xff1a;使用脚手架搭建vue项目&#xff0c;使用脚手架可以开发者能够开箱即用快速地进行应用开发而开发。 搭建 #创建一个基于 webpack 模板的新项目 vue init webpack my-project #选择所需要的选项如图&#xff1a; cd my-project npm run dev访问localhost:808…

分布式数据库架构

分布式数据库架构 1、MySQL常见架构设计 对于mysql架构&#xff0c;一定会使用到读写分离&#xff0c;在此基础上有五种常见架构设计&#xff1a;一主一从或多从、主主复制、级联复制、主主与级联复制结合。 1.1、主从复制 这种架构设计是使用的最多的。在读写分离的基础上…

SpringBoot源码分析(三):SpringBoot的事件分发机制

文章目录 通过源码明晰的几个问题Spring 中的事件Springboot 是怎么做到事件监听的另外两种注册的Listener 源码解析加载listenerSpringApplicationRunListenerEventPublishingRunListenerSimpleApplicationEventMulticaster判断 listener 是否可以接收事件Java 泛型获取 整体流…

【前端|HTML系列第1篇】HTML的基础介绍与初次尝试

大家好&#xff0c;欢迎来到前端入门系列的第一篇博客。在这个系列中&#xff0c;我们将一起学习前端开发的基础知识&#xff0c;从零开始构建网页和Web应用程序。本篇博客将为大家介绍HTML&#xff08;超文本标记语言&#xff09;的基础概念和标签&#xff0c;帮助你快速入门。…