Java爬虫系列四:使用selenium-java爬取js异步请求的数据[通俗易懂]

在之前的系列文章中介绍了如何使用httpclient抓取页面html以及如何用jsoup分析html源文件内容得到我们想要的数据,但是有时候通过这两种方式不能正常抓取到我们想要的数据,比如看如下例子。

大家好,又见面了,我是全栈君。

在之前的系列文章中介绍了如何使用httpclient抓取页面html以及如何用jsoup分析html源文件内容得到我们想要的数据,但是有时候通过这两种方式不能正常抓取到我们想要的数据,比如看如下例子。

1.需求场景:

想要抓取股票的最新价格,页面F12信息如下:
Java爬虫系列四:使用selenium-java爬取js异步请求的数据[通俗易懂]
按照前面的方式,爬取的代码如下:

/**
 * @description: 爬取股票的最新股价
 * @author: JAVA开发老菜鸟
 * @date: 2021-10-16 21:47
 */
public class StockPriceSpider {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    public static void main(String[] args) {

        StockPriceSpider stockPriceSpider = new StockPriceSpider();
        String html = stockPriceSpider.httpClientProcess();
        stockPriceSpider.jsoupProcess(html);
    }

    private String httpClientProcess() {
        String html = "";
        String uri = "http://quote.eastmoney.com/sh600036.html";
        //1.生成httpclient,相当于该打开一个浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        //2.创建get请求,相当于在浏览器地址栏输入 网址
        HttpGet request = new HttpGet(uri);
        try {
            request.setHeader("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36");
            request.setHeader("accept", "application/json, text/javascript, */*; q=0.01");

//            HttpHost proxy = new HttpHost("3.211.17.212", 80);
//            RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
//            request.setConfig(config);

            //3.执行get请求,相当于在输入地址栏后敲回车键
            response = httpClient.execute(request);

            //4.判断响应状态为200,进行处理
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //5.获取响应内容
                HttpEntity httpEntity = response.getEntity();
                html = EntityUtils.toString(httpEntity, "utf-8");
                logger.info("访问{} 成功,返回页面数据{}", uri, html);
            } else {
                //如果返回状态不是200,比如404(页面不存在)等,根据情况做处理,这里略
                logger.info("访问{},返回状态不是200", uri);
                logger.info(EntityUtils.toString(response.getEntity(), "utf-8"));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //6.关闭
            HttpClientUtils.closeQuietly(response);
            HttpClientUtils.closeQuietly(httpClient);
        }
        return html;
    }

    private void jsoupProcess(String html) {
        Document document = Jsoup.parse(html);
        Element price = document.getElementById("price9");
        logger.info("股价为:>>> {}", price.text());
    }

}

运行结果:
Java爬虫系列四:使用selenium-java爬取js异步请求的数据[通俗易懂]

纳尼,股价为”-” ?不可能。
之所以爬不到正确的结果,是因为这个值在网站上是通过异步加载渲染的,因此不能正常获取。

2.java爬取异步加载的数据的方法

那如何爬取异步加载的数据呢?通常有两种做法:

2.1内置浏览器内核

内置浏览器就是在抓取的程序中启动一个浏览器内核,使我们获取到 js 渲染后的页面就和静态页面一样。常用的内核有

  • Selenium
  • PhantomJs
  • HtmlUnit

这里我选了Selenium,它是一个模拟浏览器,是进行自动化测试的工具,它提供一组 API 可以与真实的浏览器内核交互。当然,爬虫也可以用它。
具体做法如下:

  • 引入pom依赖
<dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-java</artifactId>
   <version>3.141.59</version>
</dependency>
  • 配置对应浏览器的驱动
    要使用selenium,需要下载浏览器的驱动,根据不同的浏览器要下载的驱动程序也不一样,下载地址为:https://npm.taobao.org/mirrors/chromedriver/
    我用的是谷歌浏览器,因此下载了对应版本的windows和linux驱动。
    Java爬虫系列四:使用selenium-java爬取js异步请求的数据[通俗易懂]
    Java爬虫系列四:使用selenium-java爬取js异步请求的数据[通俗易懂]

    下载后需要配置进java环境变量里面,指定驱动的目录:

    System.getProperties().setProperty(“webdriver.chrome.driver”, “F:/download/chromedriver_win32_1/chromedriver.exe”);

  • 代码实现:

    Logger logger = LoggerFactory.getLogger(this.getClass());
    
      public static void main(String[] args) {
    
          StockPriceSpider stockPriceSpider = new StockPriceSpider();
          stockPriceSpider.seleniumProcess();
      }
    
      private void seleniumProcess() {
    
          String uri = "http://quote.eastmoney.com/sh600036.html";
    
          // 设置 chromedirver 的存放位置
          System.getProperties().setProperty("webdriver.chrome.driver", "F:/download/chromedriver_win32_1/chromedriver.exe");
    
          // 设置浏览器参数
          ChromeOptions chromeOptions = new ChromeOptions();
          chromeOptions.addArguments("--no-sandbox");//禁用沙箱
          chromeOptions.addArguments("--disable-dev-shm-usage");//禁用开发者shm
          chromeOptions.addArguments("--headless"); //无头浏览器,这样不会打开浏览器窗口
          WebDriver webDriver = new ChromeDriver(chromeOptions);
    
          webDriver.get(uri);
          WebElement webElements = webDriver.findElement(By.id("price9"));
          String stockPrice = webElements.getText();
          logger.info("最新股价为 >>> {}", stockPrice);
          webDriver.close();
      }
    

    执行结果:
    Java爬虫系列四:使用selenium-java爬取js异步请求的数据[通俗易懂]

    爬取成功!

2.2反向解析法

反向解析法就是通过F12查找到 Ajax 异步获取数据的链接,直接调用该链接得到json结果,然后直接解析json结果获取想要的数据。
这个方法的关键就在于找到这个Ajax链接。这种方式我没有去研究,感兴趣的可以百度下。这里略。

3.结束语

以上即为如何通过selenium-java爬取异步加载的数据的方法。通过本方法,我写了一个小工具:
持仓市值通知系统,他会每日根据自己的持仓配置,自动计算账户总市值,并邮件通知到指定邮箱。
用到的技术如下:

相关代码已经上传到我的码云,感兴趣可以看下。

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

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/120869.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • “DropDownList1“有一个无效 SelectedValue,因为它不在项目列表中。

    “DropDownList1“有一个无效 SelectedValue,因为它不在项目列表中。今天用FormView做一个网页,其中用到了DropDownList控件,代码是这样写的:写好之后怎么弄也不行,后来google了一下,找到了很多答案,看完之后我认为DataValueField的值必须从零开始,于是我就改了改sql语句,但是还是不行。又想了一会,茅塞顿开原来是SelectedValue和DataValueField的类型必须一致,困扰我好长时间的问题终于解决正确代码:

  • Nginx命令大全[通俗易懂]

    nginx #打开nginxnginx-t   #测试配置文件是否有语法错误nginx-sreopen #重启Nginxnginx-sreload  #重新加载Nginx配置文件,然后以优雅的方式重启Nginxnginx-sstop  #强制停止Nginx服务nginx-squit  #优雅地停止Nginx服务…

  • 今天的学习[通俗易懂]

    今天的学习[通俗易懂]今天的学习

  • Cubieboard2 debian

    Cubieboard2 debian环境准备本文所使用的主机环境为kubuntu12.10,然而一般情况下,下面涉及到的命令对基于Debian的(X)ubuntu系列都应该适用。为不引起混淆,我们作如下约定:工作目录为$WORK_DIR,目标系统rootfs目录为$WORK_DIR/$ROOTFS_DIR命令均以root用户执行笔者的设定如下:WORK_DIR=/home/itv

  • Decorator 单一职责模式[通俗易懂]

    Decorator 单一职责模式[通俗易懂]单一职责模式动机模式定义案例结构要点总结笔记动机在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多的子类的膨胀如何使“对象功能的扩展”能够根据需要来动态实现?同时避免”扩展功能的增多“带来的子类膨胀问题?从而使得任何任何”功能扩展变化“所导致的影响将为最低?模式定义动态(组合)地给一个对象增加一些额外的职责。就增加功能而言Decorator模式比生成子类

  • 内存泄露检測及cvClone造成的泄露

    内存泄露检測及cvClone造成的泄露

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号