Java爬虫-获取数据的方式之一

目录

一、jsoup的使用

1.概述

2.主要功能

3.快速入门

4.数据准备

二、Selenium

1.概述

2.使用

三、Selenium配合jsoup获取数据

四、爬虫准则

五、Selenium+jsoup+mybatis实现数据保存

1.筛选需要的数据

2.创建一个表,准备存储数据


手写?不存在的

一、jsoup的使用

1.概述

jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

2.主要功能

  • 从URL,文件或字符串中刮取并解析HTML

  • 查找和提取数据,使用DOM遍历或CSS选择器

  • 操纵HTML元素,属性和文本

  • 根据安全的白名单清理用户提交的内容,以防止XSS攻击

  • 输出整洁的HTML

3.快速入门

  • 引入jsoup坐标

  • 然后就可以直接开整了

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.17.2</version>
</dependency>

Java

public static void main(String[] args) throws IOException {
    Document doc = Jsoup.connect("https://www.baidu.com").get();
    String title = doc.title();
    System.out.println("Title is: " + title);
}

参数设置

Document doc = Jsoup.connect("http://example.com")
          .data("query", "Java")
          .userAgent("Mozilla")
          .cookie("auth", "token")
          .timeout(3000)
          .post();

结束,使用就是这么快

使用需要的知识

  • Java基础

  • html三剑客基础【知道是干啥的就行】(html/css/javascript)

  • jQuery基础

4.数据准备

我这里主要是为了获取数据,更深入的知识可自行网上查阅,我就不写了

Element类方法详解 - jsoup - 文档中心 - 技术客 (sunjs.com)

  • 首先准备一个网址:我用的jd的

笔记本 - 商品搜索 - 京东热卖 (jd.com)

  • 回到Java程序,运行一次,看看有数据不

       String s = "笔记本";
        final String encode = URLEncoder.encode(s);
​
        Document doc = null;
        try {
            doc = Jsoup.connect("https://re.jd.com/search?keyword="+encode)
                    .userAgent("Mozilla")
                    .timeout(5000)
                    .get();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(doc);

输出如下图即可:

  • 打开网页,f12或鼠标右键点击检查,选择要获取数据容器/元素的位置

  • 之后分析html代码,根据类名/标签名/id等缩小范围即可

  • 回到Java代码,选择一下标签输出看一下

final Element shopList = doc.getElementById("shop_list");
System.out.println(shopList);

  • 发现是个空数据,由于jsoup只能爬取静态页面,所以需要借助另外一个工具了

拓展:

数据并不是不存在,它只是在js里

如果不嫌麻烦的话可以使用data()方法获取到,但是后续处理很麻烦,就不写了

二、Selenium

这是测试方向的,但别说真好用,这个我没咋学过,只会一点,有时间研究研究~

1.概述

Selenium是一系列基于Web的自动化工具,提供一套测试函数,用于支持Web自动化测试。函数非常灵活,能够完成界面元素定位、窗口跳转、结果比较。

具有如下特点:

  • 多浏览器支持

    • 如IE、Firefox、Safari、Chrome、Android手机浏览器等。

  • 支持多语言

    • 如Java、C#、Python、Ruby、PHP等。

  • 支持多操作系统

    • 如Windows、Linux、IOS、Android等。

  • 开源免费

    • 官网:Selenium

2.使用

  • 引入Selenium依赖坐标

  • 根据不同浏览器下载不同的驱动(有些可能需要点魔法)

  • 设置浏览器驱动

    • 我的电脑–>属性–>系统设置–>高级–>环境变量–>系统变量–>Path,将“存放浏览器驱动”目录添加到Path的值中。

  • 验证浏览器是否能启动成功

<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.0.0</version>
</dependency>

验证浏览器

    public static void main(String[] args) {
//        WebDriver driver = new ChromeDriver();    //Chrome浏览器
//        WebDriver driver = new FirefoxDriver();   //Firefox浏览器
        WebDriver driver = new EdgeDriver();      //Edge浏览器
//        WebDriver driver = new InternetExplorerDriver();  // Internet Explorer浏览器
//        WebDriver driver = new OperaDriver();     //Opera浏览器
//        WebDriver driver = new PhantomJSDriver();   //PhantomJS
        System.out.println(driver);
    }

如果报错还会给最新的驱动下载地址,这很nice!

驱动版本一致后运行

开始挨个解决异常信息

首先第一个:访问给的网址

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See SLF4J Error Codes for further details.

翻译一下

添加依赖

   <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>

运行,第一个问题解决

第二个问题:

jdk11的有另外一种解决方案,我这用的jdk8的,11的可自行搜一下

        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        WebDriver driver = new EdgeDriver(edgeOptions);

之后,所有问题解决,开始使用~

测试代码:

        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        WebDriver driver = new EdgeDriver(edgeOptions);
        // 2.打开百度首页
        driver.get("https://www.baidu.com");
        // 3.获取输入框,输入selenium
        driver.findElement(By.id("kw")).sendKeys("selenium");
        // 4.获取“百度一下”按钮,进行搜索
        driver.findElement(By.id("su")).click();
        // 5.退出浏览器
        //driver.quit();

运行:完美,到这一步后后面就非常简单了~

三、Selenium配合jsoup获取数据

java代码

Scanner scanner = new Scanner(System.in);
System.out.println("请输入要搜索的内容");
final String s = "笔记本";
final String encode = URLEncoder.encode(s);
​
EdgeOptions edgeOptions = new EdgeOptions();
edgeOptions.addArguments("--remote-allow-origins=*");
//创建浏览器窗口
WebDriver edgeDriver = new EdgeDriver(edgeOptions);
​
edgeDriver.get("https://re.jd.com/search?keyword="+encode);
//动态网站数据填充比较慢,需要延迟才可以拿到数据,一般网不差3到5s就差不多了
Thread.sleep(5000);
//获取页面数据
final String pageSource = edgeDriver.getPageSource();
//将字符串转为document对象
final Document parse = Jsoup.parse(pageSource);
final Element shopList = parse.getElementById("shop_list");
//检查一下是否获得数据了
System.out.println(shopList.html());

数据有了~

推荐先直接把获取到的html数据持久化到本地~,爬的次数多了会被监视的~

四、爬虫准则

  • 爬虫访问频次要控制,别把对方服务器搞崩溃了
  • 涉及到个人隐私的信息不要也不能爬
  • 突破网站的反爬措施,后果很严重,如果你被监视了,最好不要尝试突破反爬措施
  • 遵守robot.txt----(Robots协议)

五、Selenium+jsoup+mybatis实现数据保存

1.筛选需要的数据

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要搜索的内容");
        final String s = "笔记本电脑";
        final String encode = URLEncoder.encode(s);

        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        //创建浏览器窗口
        WebDriver edgeDriver = new EdgeDriver(edgeOptions);

        edgeDriver.get("https://re.jd.com/search?keyword="+encode);
        //动态网站数据填充比较慢,需要延迟才可以拿到数据,一般网不差3到5s就差不多了
        Thread.sleep(5000);
        //获取页面数据
        final String pageSource = edgeDriver.getPageSource();

        //将字符串转为document对象
        final Document parse = Jsoup.parse(pageSource);
        final Element shopList = parse.getElementById("shop_list");

        final Elements li = shopList.children();
        System.out.println("----------------------------------------------------------------------------");

        // //div[@class='sear_container w']/div[2]/div/div/div/ul/li
        /*
        li.html()还有俩部分,一个是pic,一个是li_cen_bot
        li_cen_bot再分3个,commodity_info商品信息(价格);commodity_tit:商品标题;comment:评论
        */
        ArrayList<String> images = new ArrayList<>();
        ArrayList<String> prices = new ArrayList<>();
        ArrayList<String> titles = new ArrayList<>();
        ArrayList<String> comments = new ArrayList<>();
        //.get(1).attr("src").substring(2))
        li.forEach(inner -> {
            images.add("https:" + inner.getElementsByClass("img_k").attr("src"));
            titles.add(inner.getElementsByClass("commodity_tit").text());
            if (inner.getElementsByClass("price").text().length()==0){
                prices.add("预约");
            }else{
                prices.add(inner.getElementsByClass("price").text().substring(1));
            }
            comments.add(inner.getElementsByClass("praise praise-l").text());
        });

2.创建一个表,准备存储数据

先随便整一个吧~

加个img_url字段,字段长度如果太小了就自己再改改,有错误自己再调调,有基础这些错误都能自己调了

3.结果

mybatis配置啥的不写了,直接出结果代码了

public class DemoJ {
    public static void main(String[] args) throws InterruptedException, IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要搜索的内容");
        final String s = "笔记本电脑";
        final String encode = URLEncoder.encode(s);
​
        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        //创建浏览器窗口
        WebDriver edgeDriver = new EdgeDriver(edgeOptions);
​
        edgeDriver.get("https://re.jd.com/search?keyword="+encode);
        //动态网站数据填充比较慢,需要延迟才可以拿到数据,一般网不差3到5s就差不多了
        Thread.sleep(5000);
        //获取页面数据
        final String pageSource = edgeDriver.getPageSource();
​
        //将字符串转为document对象
        final Document parse = Jsoup.parse(pageSource);
        final Element shopList = parse.getElementById("shop_list");
​
        final Elements li = shopList.children();
        System.out.println("----------------------------------------------------------------------------");
​
        // //div[@class='sear_container w']/div[2]/div/div/div/ul/li
        /*
        li.html()还有俩部分,一个是pic,一个是li_cen_bot
        li_cen_bot再分3个,commodity_info商品信息(价格);commodity_tit:商品标题;comment:评论
        */
        ArrayList<String> images = new ArrayList<>();
        ArrayList<String> prices = new ArrayList<>();
        ArrayList<String> titles = new ArrayList<>();
        ArrayList<String> comments = new ArrayList<>();
        //.get(1).attr("src").substring(2))
        li.forEach(inner -> {
            images.add("https:" + inner.getElementsByClass("img_k").attr("src"));
            titles.add(inner.getElementsByClass("commodity_tit").text());
            if (inner.getElementsByClass("price").text().length()==0){
                prices.add("预约");
            }else{
                prices.add(inner.getElementsByClass("price").text().substring(1));
            }
            comments.add(inner.getElementsByClass("praise praise-l").text());
        });
​
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
​
        final SqlSession sqlSession = sqlSessionFactory.openSession();
        final ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);
​
        for (int i = 0; i < images.size(); i++) {
            mapper.add(titles.get(i),prices.get(i),images.get(i),comments.get(i));
        }
        sqlSession.commit();
        sqlSession.close();
    }
}

结束

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE初阶系列】——多线程 之 创建线程

目录 &#x1f388;认识Thread类 &#x1f388;Sleep &#x1f388;创建线程 &#x1f6a9;继承Thread&#xff0c;重写run方法 &#x1f6a9;实现Runnable接口&#xff0c;重写run方法 &#x1f6a9;使用匿名内部类创建 Thread 子类对象 &#x1f6a9;使用匿名内部类&…

C++ vector详解及模拟实现

目录 1.vector的介绍及使用 1.1 vector的介绍 1.2 vector的使用 2.vector深度剖析及模拟实现 3.迭代器失效 4.遗留的浅拷贝问题 5.完整代码 1.vector的介绍及使用 1.1 vector的介绍 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c;vector也采用的连续…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:ScrollBar)

滚动条组件ScrollBar&#xff0c;用于配合可滚动组件使用&#xff0c;如List、Grid、Scroll。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 可以包含单个子组件。 接口 ScrollBar(val…

MAC M芯片 Anaconda安装

Anaconda安装 1.M芯片下载AnaConda 1.M芯片下载AnaConda https://www.anaconda.com/download 安装完成 conda的版本是24.1.2

strcmp的模拟实现

一&#xff1a;strcmp函数的定义&#xff1a; strcmp函数功能的解释&#xff1a; 比较两个字符串的大小&#xff08;按照字符串中字符的ascll码值&#xff09;。 标准规定&#xff1a; 第一个字符串大于第二个字符串&#xff0c;则返回大于 0 的数字 第一个字符串等于第二个…

【Linux C | 多线程编程】线程的基础知识

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

Vue 3 + TypeScript 项目中全局挂载并使用工具函数

一、proxy方式 1.封装日期选择工具函数&#xff1a; 在untils文件夹下新建index.ts,并导出工具函数 /*** 获取不同类型日期* param&#xff1a;类型 dateVal: 是否指定*/ export function getSystemDate(param: any, dateVal: any) {let systemDate dateVal ? new Date(da…

Oracle Primavera P6 数据库升级

前言 为了模拟各种P6测试&#xff0c;我常常会安装各种不同版本的p6系统&#xff0c;无论是P6服务&#xff0c;亦或是P6客户端工具Professional&#xff0c;在今天操作p6使用时&#xff0c;无意识到安装在本地的P6 数据库&#xff08;21.12&#xff09;出现了与Professional软…

双指针算法_移动零_

题目&#xff1a; 给定一个数组 num &#xff0c;编写一个函数将数组内部的数字0都移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序&#xff01; 同时不能通过复制数组&#xff0c;开辟新的数组空间的情况下原地对数组进行操作 示例&#xff1a; 本题的原理&#x…

Python控制摄像头并获取数据文件

一、引言 摄像头作为计算机视觉领域的核心设备之一&#xff0c;广泛应用于视频监控、图像采集和数据处理等领域。通过Python编程语言&#xff0c;我们可以实现对摄像头的精确控制&#xff0c;包括摄像头的开启、关闭、参数设置以及数据获取等功能。 目录 一、引言 二、摄像头…

【上海大学计算机组成原理实验报告】一、数据传送实验

一、实验目的 了解实验仪器数据总线的控制方式。掌握数据传送的基本原理。掌握各寄存器的结构、工作原理及其控制方法。 二、实验原理 根据实验指导书的相关内容&#xff0c;数据输入到寄存器的过程是先通过指令选择源和目标&#xff0c;再通过数据总线来传送数据&#xff0…

探索Webpack中的常见Loader

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

yolov8 分割 模型 网络 模块图

下图是使用yolov8n-seg-p6.yaml imgsz1472 类别数2的情况下训练得到的静态导出的onnx文件使用netron工具可视化的结果 简单标注了yolov8n-seg-p6.yaml配置文件中各层和netron工具可视化的结果的对应关系(head 中的 Segment除外)

ideaSSM失物招领管理系统网页模式开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea ssm 失物招领管理系统是一套完善的完整信息管理系统&#xff0c;结合SSM框架完成本系统SpringMVC spring mybatis &#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数…

yocto系列之构建与运行第一个镜像

回顾 在前面的文章中&#xff0c;我们介绍了Yocto&#xff0c;并展示了如何在Ubuntu PC上进行Yocto构建。这里是对应的链接&#xff1a; Yocto: 第1部分 - yocto系列之yocto是个什么东东 https://mp.csdn.net/mp_blog/creation/editor/136742286 Yocto: 第2部分 - yocto系列…

Linux学习(6)——Linux环境变量

1.环境变量简介 通过设置环境变量&#xff0c;可以满足不同用户的需求。 直接定义的变量是全局变量&#xff0c;不是环境变量。shell进程的子进程无法访问这种变量。 用export命令可以将全局变量导出为环境变量。子进程就可以访问了。 &#xff08;虽然用export命令修饰后&…

闲聊电脑(7)常见故障排查

闲聊电脑&#xff08;7&#xff09;常见故障排查 夜深人静&#xff0c;万籁俱寂&#xff0c;老郭趴在电脑桌上打盹&#xff0c;桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭&#xff1a;冰箱大哥&#xff0c;平时遇到电脑故障该咋处理呢&#xff1f; 冰箱&#xf…

数据结构——动态顺序表

数据结构的动态顺序表有以下几个操作&#xff1a;创建&#xff0c;销毁&#xff0c;初始化&#xff0c;增删查改和打印以及内存空间不够时的扩容 本文的宏定义&#xff1a; #define SeqTypeData int 1.动态顺序表的创建 typedef struct SeqListInit{//动态顺序表的创建SeqT…

自学rabbitmq入门到精通

交换机的fault &#xff08;发布与订阅模式&#xff09; 因为消息是由生产者发送给excahnge&#xff0c;exchange发送给队列&#xff0c; 然后由队列发送给消费者的。 展示使用图形化界面使用fanout模式。 创建交换机 然后创建三个队列&#xff0c;绑定对应的交换机&#xff…

docker的常用指令

docker的常用指令 从docker镜像仓库&#xff0c;搜索所有和mysql有关的镜像 docker search mysql 从docker仓库拉取mysql docker pull mysql这里的mysql是指使用search搜索出来的所有容器的NAME 如果和我一样遇到以下问题&#xff1a; 我可以登录阿里云的官网&#xff0c;找…