java使用htmlunit + jsoup 爬网站图片案例(爬虫学习)

news2024/11/25 1:48:15

申明

该文章用于自己学习爬虫使用

案例分析

目的: 从百度图片中搜索"风景"并下载图片到本地
思路: 使用htmlunit进行模拟用户操作, 并使用jsoup对数据进行解析,获取到需要的数据后,再下载到本地保存
htmlunit官网
jsoup官网

操作步骤

  1. 使用谷歌浏览器打开百度图片网站 https://image.baidu.com
    在这里插入图片描述
  2. 输入"风景", 点击"百度一下"按钮
    在这里插入图片描述
  3. 页面进行跳转
    在这里插入图片描述
  4. 对当前页面页面中的图片地址进行获取, 并保存到本地
  5. 需要进行鼠标滚轮向下滑动

找网页中对应标签的方式

通过F12
在这里插入图片描述

引入依赖

<dependency>
          <!-- jsoup HTML parser library @ https://jsoup.org/ -->
          <groupId>org.jsoup</groupId>
          <artifactId>jsoup</artifactId>
          <version>1.16.1</version>
        </dependency>

        <dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.41.0</version>
        </dependency>

代码

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * desc:
 *
 * @author qts
 * @date 2023/7/20 0020
 */
public class CrawlerTest {

    public static void main(String[] args) throws IOException {

        // ======== htmlunit 操作 start ============
        
        // 创建htmlunit 客户端, 指定浏览器(当前为谷歌浏览器)
        WebClient webClient = new WebClient(BrowserVersion.CHROME);

        // 设置客户端配置
        webClient.getOptions().setCssEnabled(false);//(屏蔽)css 因为css并不影响我们抓取数据 反而影响网页渲染效率
        webClient.getOptions().setThrowExceptionOnScriptError(false);//(屏蔽)异常
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//(屏蔽)日志
        webClient.getOptions().setJavaScriptEnabled(true);//加载js脚本
        webClient.getOptions().setTimeout(5000);//设置超时时间
        webClient.getOptions().setRedirectEnabled(true); //允许重定向
        webClient.getCookieManager().setCookiesEnabled(true);//允许cookie
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax

        // 请求网站获取HtmlPage
        HtmlPage htmlPage = webClient.getPage("https://image.baidu.com/");
        // 获取输入框对应的表单
        HtmlForm homeSearchForm = (HtmlForm) htmlPage.getElementById("homeSearchForm");
        // 获取对应输入框
        HtmlTextInput searchInput = (HtmlTextInput) homeSearchForm.getElementsByAttribute("input", "id", "kw").get(0);
        // 设置输入框内容"风景"
        searchInput.setValueAttribute("风景");

        // 获取搜索按钮"百度一下"
        HtmlSubmitInput searchSubmitInput = htmlPage.querySelector("input.s_newBtn");
        // 点击按钮
        HtmlPage resultHome = searchSubmitInput.click();

        // 执行js 向下滚屏(因为页面的图片是通过滚屏进行刷新的,不滚屏后面的图片没有对应的地址数据) 
        // window.scrollTo(0, document.documentElement.scrollHeight) 滑动到底部,可以在页面F12控制台中执行代码测试
        resultHome.executeJavaScript("window.scrollTo(0,6000)");// 执行js 向下滚屏,自行设置对应值,当前仅做测试使用
		
        //主线程休眠10秒 让客户端有时间执行js代码
        webClient.waitForBackgroundJavaScript(10000);

        // ======== htmlunit 操作 end ============

        // ======== jsoup 解析 start ============

        // 解析html页面得到 Document
        Document doc = Jsoup.parse(resultHome.asXml());

        // 获取图片 img元素
        Elements elements = doc.select("img[class='main_img img-hover']");


        // 处理图片
        for (int i = 0; i < elements.size(); i++) {
            Element element = elements.get(i);
            String url = element.attr("src");

            if (!url.startsWith("http")) {
                // 有些广告是用的base64数据,进行排除
                continue;
            }

            InputStream inputStream = getFileInputStream(url);

            if (inputStream != null) {
                FileUtil.writeBytes(readBytes(inputStream),"D:\\baidu_pic\\pic_"+i+".png");
            }
        }

        // ======== jsoup 解析 end ============
    }

    /*读取网络文件*/
    public static InputStream getFileInputStream(String path) {
        URL url;
        try {
            url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置超时间为3秒
            conn.setConnectTimeout(3 * 1000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            return conn.getInputStream();
        } catch (Exception e) {
            Console.error("读取网络文件异常:" + path);
        }
        return null;
    }

    /**
     * 读取输入流到字节数组
     *
     * @param in
     * @return
     * @throws IOException
     */
    public static byte[] readBytes(InputStream in) throws IOException {
        //读取字节的缓冲
        byte[] buffer = new byte[1024];
        //最终的数据
        byte[] result = new byte[0];
        int size = 0;
        while ((size = in.read(buffer)) != -1) {
            int oldLen = result.length;
            byte[] tmp = new byte[oldLen + size];
            if (oldLen > 0) {//copy 旧字节
                System.arraycopy(result, 0, tmp, 0, oldLen);
            }
            //copy 新字节
            System.arraycopy(buffer, 0, tmp, oldLen, size);

            result = tmp;
        }
        return result;
    }

}

htmlunit使用参考: https://blog.csdn.net/weixin_44787678/article/details/106994485

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

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

相关文章

用html+javascript打造公文一键排版系统8:附件及标题排版

最近工作有点忙&#xff0c;所 以没能及时完善公文一键排版系统&#xff0c;现在只好熬夜更新一下。 有时公文有包括附件&#xff0c;招照公文排版规范&#xff1a; 附件应当另面编排&#xff0c;并在版记之前&#xff0c;与公文正文一起装订。“附件”二字及附件顺序号用3号黑…

Mysql适用于初学者的前期入门资料

文章目录 前言一、SQL语句分类二、SQL语句的书写规范三.数据库操作四、MySQL字符集1、问题① 五、UTF8和UTF8MB4的区别六、数据库对象七、数据类型八、表的基本创建1、创建表2、查看表3、删除表4、修改表结构5、复制表的结构 九、数据库字典十、表的约束1、非空约束(NOT NULL)2…

matplotlib从起点出发(4)_Tutorial_4_Lifecycle

1 一幅图像的生命周期 本教程旨在揭示使用matplotlib绘制的一幅图像的生命周期&#xff0c;包括它的开始、中间和结束。我们将从一些原始数据开始&#xff0c;最后保存自定义可视化的图形。在此过程中&#xff0c;我们尝试使用matplotlib突出一些简洁的功能和最佳实践。 2 关…

【Matlab】基于粒子群优化算法优化BP神经网络的时间序列预测(Excel可直接替换数据)

【Matlab】基于粒子群优化算法优化BP神经网络的时间序列预测&#xff08;Excel可直接替换数据&#xff09; 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码5.1 fun.m5.2 main.m 6.完整代码6.1 fun.m6.2 main.m 7.运行结果 1.模型原理 基于粒子群优化算法&#xff08;Pa…

【LeetCode 75】第九题(443)压缩字符串

目录 题目: 示例: 分析: 题目: 示例: 分析: 给一个字符串,如果该字符有连续的相同的字符,则只保留一个字符,并在该字符后加上该字符连续的数量.例如原数组为 [a,a,a],则因为字符a连续了三次,因此可以压缩为[a,3],我们需要注意的是数字也需要是字符,则如果字符连续次数不止有…

SpringCloud学习路线(13)——分布式搜索ElasticSeach集群

前言 单机ES做数据存储&#xff0c;必然面临两个问题&#xff1a;海量数据的存储&#xff0c;单点故障。 如何解决这两个问题&#xff1f; 海量数据的存储问题&#xff1a; 将索引库从逻辑上拆分为N个分片&#xff08;shard&#xff09;&#xff0c;存储到多个节点。单点故障…

C++笔记之memset分析

C笔记之memset分析 code review! 文章目录 C\笔记之memset分析1.介绍2.误区总结3.代码一&#xff0c;char数组和uint8_t使用memset4.代码三&#xff0c;int数组使用memset 1.介绍 2.误区总结 参考文章&#xff1a;Cmemset踩坑 3.代码一&#xff0c;char数组和uint8_t使用mem…

2023年河北省研究生数学建模竞赛D题中国钢铁工业低碳转型与高质量发展路径优化研究思路和代码

D题中国钢铁工业低碳转型与高质量发展路径优化研究 目前已写出D题初步代码&#xff0c;下载地址&#xff1a;【2023年河北省研究生数学建模竞赛D题初步思路和代码-哔哩哔哩】 https://b23.tv/g2ATbX5 随着我国工业化、城镇化进程的加快和消费结构持续升级&#xff0c;能源需求…

tty(五)串口的打开过程

一、字符设备完成注册 我们知道&#xff0c;在serial核心层提供了2个重要接口 uart_register_driver uart_add_one_port 上者通过调用tty核心的接口&#xff0c;完成了tty_driver的动态分配和注册&#xff0c;然而此时并没有看到创建字符设备&#xff0c; 通过对uart_add_one…

货拉拉基于 Flink 计算引擎的应用与优化实践

摘要&#xff1a;本文整理自货拉拉实时研发平台负责人王世涛&#xff0c;在Flink Forward Asia 2022 平台建设专场的分享。本篇内容主要分为六个部分&#xff1a; Flink 在货拉拉的使用现状Flink 平台化性能优化主题数据准确性主题稳定性主题未来展望 点击查看原文视频 & 演…

【leetcode】链表的中间节点|链表中倒数第k个节点

目录 1.链表的中间节点 2.链表中倒数第k个节点 1.链表的中间节点 思路1&#xff1a;遍历链表&#xff0c;统计节点个数count&#xff0c;返回第count/2 1个节点 &#x1f4d6;Note:注意循环条件为--mid&#xff0c;--mid循环执行mid-1次&#xff0c;mid--循环mid次&#xf…

SpringBoot 8种异步实现方式

前言&#xff1a;异步执行对于开发者来说并不陌生&#xff0c;在实际的开发过程中&#xff0c;很多场景多会使用到异步&#xff0c;相比同步执行&#xff0c;异步可以大大缩短请求链路耗时时间&#xff0c;比如&#xff1a;「发送短信、邮件、异步更新等」&#xff0c;这些都是…

采用串级控制和超高精度PID调节器的微张力精密控制技术

摘要&#xff1a;采用当前的各种涂布机很难适用气体扩散层这类脆性材料的涂布工艺&#xff0c;需要控制精度更高的微张力控制系统。为此本文基于串级控制原理&#xff0c;提出了采用双闭环PID控制模式和超高精度PID张力控制器的解决方案&#xff0c;一方面形成浮动摆棍闭环和主…

python机器学习(五)逻辑回归、决策边界、代价函数、梯度下降法实现线性和非线性逻辑回归

线性回归所解决的问题是把数据集的特征传入到模型中&#xff0c;预测一个值使得误差最小&#xff0c;预测值无限接近于真实值。比如把房子的其他特征传入到模型中&#xff0c;预测出房价&#xff0c; 房价是一系列连续的数值&#xff0c;线性回归解决的是有监督的学习。有很多场…

kafka权威指南学习以及kafka生产配置

0、kafka常用命令 Kafka是一个分布式流处理平台&#xff0c;它具有高度可扩展性和容错性。以下是Kafka最新版本中常用的一些命令&#xff1a; 创建一个主题&#xff08;topic&#xff09;&#xff1a; bin/kafka-topics.sh --create --topic my-topic --partitions 3 --replic…

【论文阅读22】Label prompt for multi-label text classification

论文相关 论文标题&#xff1a;Label prompt for multi-label text classification&#xff08;基于提示学习的多标签文本分类&#xff09; 发表时间&#xff1a;2023 领域&#xff1a;多标签文本分类 发表期刊&#xff1a;Applied Intelligence&#xff08;SCI二区&#xff0…

生态系统景观指数-聚集度指数AI计算

景观指数是景观生态学的常见指标&#xff0c;可用于不同生态系统的特征识别。景观指数是反映景观结构与空间格局的定量指标&#xff0c;目前已成为景观生态学领域常用的分析景观格局、度量空间异质性的重要方法。不同水平下的指数结果往往代表不同含义&#xff0c;应在把握指数…

git冲突“accept theirs”和“accept yours”

Accept Yours 就是直接选取本地的代码&#xff0c;覆盖掉远程仓库的 Accept Theirs 是直接选取远程仓库的&#xff0c;覆盖掉自己本地的 我们选择Merge,自己手动行进选择、修改。 这里左边部分是你本地仓库的代码&#xff0c;右边部分是远程仓库的代码&#xff0c;中间的res…

uniapp WIFI上下班打卡

大纲 &#x1f959; uniapp官网&#xff1a;uni-app官网 &#x1f959; WIFI功能模块&#xff1a; 1、下载 wifi 插件 uni-WiFi 2、在 manifest.json 中 App权限配置中 配置权限 1. ACCESS_WIFI_STATE &#xff08;访问权限状态&#xff09; 2. CHANGE_WIFI_STATE&#xff…

13.Netty源码之Netty中的类与API

highlight: arduino-light ServerBootstrap Bootstrap 意思是引导&#xff0c;一个 Netty 应用通常由一个 Bootstrap 开始&#xff0c;主要作用是配置整个 Netty 程序&#xff0c;串联各个组件&#xff0c;Netty 中ServerBootstrap 是服务端启动引导类。 java //泛型 AbstractB…