【Selenium+Webmagic】基于JAVA语言实现爬取js渲染后的页面,附有代码

news2024/11/14 22:06:40

事先声明
笔者最近需要查看一些数据,自己挨个找太麻烦了,于是简单的学了一下爬虫。笔者在这里声明,爬的数据只为学术用,没有其他用途,希望来这篇文章学习的同学能抱有同样的目的。

枪本身不坏,坏的是使用枪的人

效果
在这里插入图片描述

基于JAVA语言实现爬取js渲染后的页面,详细教程

  • 下载ChromeDriver
    • 下载ChromeDrive以及相对应的Chrome
    • 禁止Chrome自动升级
      • 第一步:禁用任务计划
      • 第二步:禁用更新服务
      • 第三步:重命名更新程序
  • 使用IDEA实现爬取js渲染后的页面
    • 所需依赖
    • 修改maven的镜像地址
    • 具体实现
      • 建议
      • WebMagic
      • 一个简单的demo
      • 实现思路
      • 使用Selenium解析js渲染后的页面信息
      • 重写自定义pageProcessor的process方法
      • 项目代码

下载ChromeDriver

查看自己的Chrome版本,过高需要卸载再下载
在地址栏键入

chrome://version/

查看版本
在这里插入图片描述

下载ChromeDrive以及相对应的Chrome

ChromeDriver的版本需要仔细考究,一个ChromeDriver版本对应一个Chrome版本,由于Chrome版本更新太快,最近已经到119.xx了,ChromeDriver最高支持版本才115.xx, 因此我们要先把本地的Chrome卸载,然后下载相应的历史版本
Chrome历史版本1
Chrome历史版本2 版本更多更全面
ChromeDriver历史版本

笔者以114为例子
在这里插入图片描述
点击后会进入下载页,里面有windows版本以及note.txt,在txt文件中会写有支持哪个Chrome版本
在这里插入图片描述
在这里插入图片描述
我上面给出的Chrome历史版本1中没有114版本,在历史版本2中有,可以自行去下载

禁止Chrome自动升级

由于Chrome更新太快,ChromeDriver跟不上,并且Chrome总是自动升级,这里给出禁止Chrome自动升级的解决办法1

第一步:禁用任务计划

首先是【右键计算机->管理】,在【计算机管理(本地)->系统工具->任务计划程序->任务计划程序库】中找到两个和Google自动更新相关的任务计划【GoogleUpdateTaskMachineCore】与【GoogleUpdateTaskMachineUA】,并把它俩禁用掉。
在这里插入图片描述

第二步:禁用更新服务

然后在下方的【服务和应用程序->服务】中,找到两个和Google更新相关的服务【Google更新服务(gupdate)】、【Google更新服务(gupdatem)】,并右键,选择属性,把启动类型改为禁用。如果没有找到的可以略过。
在这里插入图片描述

第三步:重命名更新程序

完成上面两步后理论上就可以停止Chrome的自动更新了,不过有网友说这么做之后,不要在Chrome中点击【帮助->关于Google Chrome】
这里笔者尝试过,确实有这种情况,为了避免,我们可以修改他的update.exe的名字:
笔者给出自己电脑上update的地址:(没有修改Chrome默认安装地址)

C:\Program Files (x86)\Google\Update

修改这个名字,如果你在这个位置没有找到,可以参考资料1的位置
在这里插入图片描述
到这里就结束了,在地址栏键入

chrome://version/

查看当前版本

不过笔者没有再尝试在Chrome中点击【帮助->关于Google Chrome】是否会更新,大胆的小伙伴可以试试

使用IDEA实现爬取js渲染后的页面

相应的版本

SpringBoot 2.6.13
Webmagic: 0.8.0
Selenium-java 3.141.59

现在SpringInitializer已经不支持SpringBoot2.x了,你可以升级使用SpringBoot3,再使用下面代码或者参考我另一篇文章使用SpringBoot2:Spring Initializer 已经不支持Java8,也就是SpringBoot2.x项目初始化

所需依赖

下面依赖有些你可能不需要 比如thymeleaf,不过都加上也不会报错

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/us.codecraft/webmagic-extension -->
        <dependency>
            <groupId>us.codecraft</groupId>
            <artifactId>webmagic-extension</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
            <version>0.8.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.3-jre</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--模拟浏览器行为-->
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
        </dependency>

    </dependencies>

修改maven的镜像地址

下载semenium的依赖需要的时间会比较长,而且下载webmagic依赖的时候有些包在阿里云Central镜像下找不到, 需要修改为all
打开配置文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改完保存即可

具体实现

建议

再看下面代码之前,还是要有一定的webmagic基础的,推荐BiliBili上一个教程,只需要两个多小时就能理解webmagic的工作流程Java爬虫案例实战-webmagic(第二话) 2021最新

WebMagic

WebMagic中文文档

从图中可以看到Spider是爬虫启动的关键入口。

我们要做的就是自定义一个xxPageProcessor,实现PageProcessor接口,重写两个方法
Site, process
在process方法中将抓取到的url地址添加到scheduler队列中,图中一个request其实是一个url地址,并不是http的请求;
其中resultItems保存的是向pipeline中写入的数据,是一个linkedhash结构

pipeline是输出的关键,可以向控制台中输出,也可以自定义一个pipeline,向数据库中写入信息

Scheduler默认是内存队列,可以修改为redis队列(成本高)

Download我这里没有自定义,不过官网给出了自定义的方法,感兴趣的可以看看

一个简单的demo

/**
 * @Author:sichenyong
 * @Email: sichenyongwork@163.com
 * @Package:com.scy
 * @Project:crawer
 * @Date:2023/12/2 19:45
 * @description:使用css选择器解析
 */
@Slf4j
public class MyPageProcessor2 implements PageProcessor {
    public void process(Page page) {
        Html html = page.getHtml();
        String title = html.css("title", "text").get();
        log.info("title is {}", title);
        page.putField("title", title);

        String s = html.css("a", "href").get();
        // 向resultItems中写入数据
        page.putField("a", s);
        List<String> all = html.css("a", "href").all();
        page.putField("allLinks", all);

        page.putField("html",html);

    }

    public Site getSite() {
        return Site.me();
    }

    public static void main(String[] args) {
        MyPageProcessor2 myPageProcessor2 = new MyPageProcessor2();
        Spider.create(myPageProcessor2).addUrl("https://www.stats.gov.cn/sj/sjjd/202311/t20231115_1944598.html")
                .start();
    }
}

实现思路

在这里插入图片描述
相较于webmagic的架构,我们只需要在process方法中使用selenium的解析方法获取js加载后的数据就可以

使用Selenium解析js渲染后的页面信息

  1. 首先定义初始化chromedriver的函数

    private String devicePath = "D:\\SoftWare\\environemnt\\chromeDriver\\chromedriver.exe";
    private ChromeDriver webDriver;
    
    
    void setUp(){
       System.getProperties().setProperty("webdriver.chrome.driver",devicePath);
       ChromeOptions options = new ChromeOptions();
       options.addArguments("--headless");
       webDriver = new ChromeDriver(options);
       webDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
    }
    
  2. 实现解析函数

    /**
        * @description:解析js加载后的页面,获取相关信息
        * @author: sichenyong
        * @email: sichenyongwork@163.com
        * @date: 2023/12/4 16:43
        * @param: [page]
        * @return: com.example.entity.UsefulMessage
        **/
       UsefulMessage parseJS(Page page) {
    
           UsefulMessage usefulMessage = new UsefulMessage();
           String url = page.getUrl().get();
           webDriver.get(url);
           // 获取所有的a标签地址
           List<WebElement> aElements = webDriver.findElements(By.cssSelector("div.list-content > ul > li > a.fl.mhide.pc1200"));
           if (aElements.size() > 0) {
               List<String> hrefValue = new ArrayList<>();
    
               for (WebElement aElement : aElements) {
                   hrefValue.add(aElement.getAttribute("href"));
               }
               // 设置列表地址
               usefulMessage.setHrefs(hrefValue);
               // 设置是否是列表页
               usefulMessage.setListPage(true);
               // 获取下一页的地址
               WebElement element = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.wrapper-list-right > div.list-pager.mhide > a.next"));
               String nextUrl = element.getAttribute("href");
               //设置下一页的url地址
               usefulMessage.setNextPageUrl(nextUrl);
               log.info("===下一页地址===" + nextUrl);
    
               String column = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.wrapper-list-left.mhide > div > ul > li.active")).getText();
               // 设置栏目
               usefulMessage.setColumn(column);
           }
           webDriver.quit();
           return usefulMessage;
       }
    
  3. 完整代码

    /**
    * @Author:sichenyong
    * @Email: sichenyongwork@163.com
    * @Package:com.example.component
    * @Project:selenium
    * @Date:2023/12/3 22:02
    * @description:使用selenium解析js加载之后的页面信息
    * @Version:1.0 由于笔者没有学过设计模式,因此写的代码有些冗余,见谅。
    */
    @Slf4j
    public class SeleniumProcessor {
    	//下载的ChromeDriver地址
       private String devicePath = "D:\\SoftWare\\environemnt\\chromeDriver\\chromedriver.exe";
       private ChromeDriver webDriver;
    
    
       void setUp(){
           System.getProperties().setProperty("webdriver.chrome.driver",devicePath);
           ChromeOptions options = new ChromeOptions();
           options.addArguments("--headless");
           webDriver = new ChromeDriver(options);
           webDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
       }
    
       /**
        * @description:解析js加载后的页面,获取相关信息
        * @author: sichenyong
        * @email: sichenyongwork@163.com
        * @date: 2023/12/4 16:43
        * @param: [page]
        * @return: com.example.entity.UsefulMessage
        **/
       UsefulMessage parseJS(Page page) {
    		// 自定义的实体类,保存自己向要的js生成的信息
           UsefulMessage usefulMessage = new UsefulMessage();
           String url = page.getUrl().get();
           webDriver.get(url);
           // 获取所有的a标签地址
           List<WebElement> aElements = webDriver.findElements(By.cssSelector("div.list-content > ul > li > a.fl.mhide.pc1200"));
           if (aElements.size() > 0) {
               List<String> hrefValue = new ArrayList<>();
    
               for (WebElement aElement : aElements) {
                   hrefValue.add(aElement.getAttribute("href"));
               }
               // 设置列表地址
               usefulMessage.setHrefs(hrefValue);
               // 设置是否是列表页
               usefulMessage.setListPage(true);
               // 获取下一页的地址
               WebElement element = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.wrapper-list-right > div.list-pager.mhide > a.next"));
               String nextUrl = element.getAttribute("href");
               //设置下一页的url地址
               usefulMessage.setNextPageUrl(nextUrl);
               log.info("===下一页地址===" + nextUrl);
    
               String column = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.wrapper-list-left.mhide > div > ul > li.active")).getText();
               // 设置栏目
               usefulMessage.setColumn(column);
           }
           webDriver.quit();
           return usefulMessage;
       }
    
       /**
        * @description: 解析网页的数据
        *              parse可以根据需要进行修改,爬取你想要的
        * @author: sichenyong
        * @email: sichenyongwork@163.com
        * @date: 2023/12/4 14:20
        * @param: [page, filterTitle]
        * @return: void
        **/
       void parse(Page page, String filterTitle, String column) {
           try {
               // 获取url
               String url = page.getUrl().get();
               webDriver.get(url);
               // 获取标题
               String title = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.detail-title > h1")).getText();
               if (title.contains(filterTitle)) {
                   // 创建数据库实体
                   Stats stats = new Stats();
                   // 读入当前页的url
                   stats.setPubUrl(url);
                   // 读入title
                   stats.setWebTitle(title);
                   // 读入栏目
                   stats.setPubColumn(column);
                   // 获取数据来源
                   WebElement source = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.detail-title > div > h2:nth-child(1) > span"));
                   String pubSources = source.getText();
                   String regex = ":";
                   if (pubSources.contains(":")) {
                       regex = ":";
                   }
                   String[] strings = pubSources.split(regex);
                   String pubSource = strings[strings.length-1];
                   stats.setPubSource(pubSource);
                   // 获取发布时间
                   String pubTime = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.detail-title > div > h2:nth-child(1) > p")).getText();
                   pubTime = pubTime.replaceAll("/","-");
                   stats.setPubTime(pubTime);
    
                   // 存入数据库
                   page.putField("stats",stats);
               }
               else {
                   log.error("文章\"" + title + "\"中不包含关键字:{}", filterTitle);
                   page.getResultItems().setSkip(true);
               }
           } catch (Exception e) {
               e.printStackTrace();
           }
           finally {
               webDriver.quit();
           }
       }
    
       /**
        * @description: 需要过滤的数据有多个
        * @author: sichenyong
        * @email: sichenyongwork@163.com
        * @date: 2023/12/4 14:21
        * @param: [page, filterTitles]
        * @return: void
        **/
       void parse(Page page, List<String> filterTitles,String column) {
           try {
               // 获取url
               String url = page.getUrl().get();
               webDriver.get(url);
               // 获取标题
               String title = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.detail-title > h1")).getText();
               if (support(title, filterTitles)) {
                   // 创建数据库实体
                   Stats stats = new Stats();
                   // 读入当前页的url
                   stats.setPubUrl(url);
                   // 读入title
                   stats.setWebTitle(title);
                   // 读入栏目
                   stats.setPubColumn(column);
                   // 获取数据来源
                   WebElement source = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.detail-title > div > h2:nth-child(1) > span"));
                   String pubSources = source.getText();
                   String regex = ":";
                   if (pubSources.contains(":")) {
                       regex = ":";
                   }
                   String[] strings = pubSources.split(regex);
                   String pubSource = strings[strings.length-1];
                   stats.setPubSource(pubSource);
                   // 获取发布时间
                   String pubTime = webDriver.findElement(By.cssSelector("body > div > div.wrapper-content > div > div.detail-title > div > h2:nth-child(1) > p")).getText();
                   pubTime = pubTime.replaceAll("/","-");
                   stats.setPubTime(pubTime);
    
                   // 存入数据库
                   page.putField("stats",stats);
               }
               else {
                   log.error("文章\"" + title + "\"中不包含关键字:{}", filterTitles);
                   page.getResultItems().setSkip(true);
               }
           } catch (Exception e) {
               e.printStackTrace();
           }
           finally {
               webDriver.quit();
           }
       }
    
       /**
        * @description:判断title是否在想要的列表中
        * @author: sichenyong
        * @email: sichenyongwork@163.com
        * @date: 2023/12/4 14:28
        * @param: [title, filterTitles]
        * @return: boolean
        **/
       boolean support(String title, @NotNull List<String> filterTitles) {
           for (String filterTitle : filterTitles) {
               if (title.contains(filterTitle)) {
                   return true;
               }
           }
           return false;
       }
    }
    
    

重写自定义pageProcessor的process方法

/**
 * @Author:sichenyong
 * @Email: sichenyongwork@163.com
 * @Package:com.scy.component
 * @Project:stats
 * @Date:2023/12/3 13:25
 * @description:
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@Slf4j
public class StatsPageProcessor implements PageProcessor {
    /**
     * @description: 过滤标题文章,保存含有filterTitle的文章
     * demo: filterTitle = "Java"
     *          函数会自动保存所有含有Java的文章,将不含有java的文章过滤掉
     * @author: sichenyong
     * @email: sichenyongwork@163.com
     * @date: 2023/12/3 14:03
     **/
    protected String filterTitle="";
    protected List<String> filterTitles;
    private String column;

    @Override
    public void process(Page page) {

        SeleniumProcessor seleniumProcessor1 = new SeleniumProcessor();
        seleniumProcessor1.setUp();
        // 获取解析js后的网页信息
        UsefulMessage usefulMessage = seleniumProcessor1.parseJS(page);

        // 是列表页
        if (usefulMessage.isListPage()) {
            // 获取所有的链接
            List<String> links = usefulMessage.getHrefs();
            // 传给Scheduler
            page.addTargetRequests(links);
            // 解析下一页
            String nextPage = usefulMessage.getNextPageUrl();
            page.addTargetRequest(nextPage);

            column = usefulMessage.getColumn();
            // 列表页面的数据不写入数据库
            page.getResultItems().setSkip(true);
        }
        else {
            // 详情页面写入数据库
//            parseStats(page);
            SeleniumProcessor seleniumProcessor = new SeleniumProcessor();
            seleniumProcessor.setUp();
            if (filterTitles == null) {
                seleniumProcessor.parse(page, filterTitle, column);
            }
            else {
                seleniumProcessor.parse(page, filterTitles, column);
            }
        }
    }


    /**
     * @description: 解析详情页面 - 无法解析js加载的页面
     * @Deprecated
     * @param: page
     * @return: void
     * @author: sichenyong
     * @email: sichenyongwork@163.com
     * @date: 2023/12/3 14:04
     **/
    @Deprecated
    private void parseStats(Page page) {
        Html html = page.getHtml();
        // 获取页面的标题
        String title = html.css("body > div > div.wrapper-content > div > div.detail-title > h1","text").get();
        // 如果文章中包含filterTitle,则保存文章
        if (title.contains(filterTitle)) {
            Stats stats = new Stats();
            //获取当前页面的url
            String currentUrl = page.getUrl().get();
            // 获取当前页面的pubtime
            String pubTime = html.css("body > div > div.wrapper-content > div > div.detail-title > div > h2:nth-child(1) > p", "text").get();
            // 获取页面的来源
            String pubSources = html.xpath("/html/body/div/div[3]/div/div[1]/div/h2[1]/span/text()").get();
            String regex = ":";
            if (pubSources.contains(":")) {
                regex = ":";
            }
            String[] strings = pubSources.split(regex);
            String pubSource = strings[strings.length-1];

            stats.setWebTitle(title);
            stats.setPubUrl(currentUrl);
            stats.setPubSource(pubSource);
            stats.setPubTime(pubTime);

            // 写入数据库
            page.putField("stats",stats);
        }
    }

    @Override
    public Site getSite() {
        Site site = new Site();
        // 设置重试间隔时间
        site.setRetryTimes(3);
        site.setRetrySleepTime(3000);
        site.setSleepTime(3000);
        return site;
    }
}

项目代码

有时间再上传


  1. 三步彻底关闭chrome谷歌浏览
    器自动更新; ↩︎ ↩︎

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

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

相关文章

20:kotlin 类和对象 --泛型(Generics)

类可以有类型参数 class Box<T>(t: T) {var value t }要创建类实例&#xff0c;需提供类型参数 val box: Box<Int> Box<Int>(1)如果类型可以被推断出来&#xff0c;可以省略 val box Box(1)通配符 在JAVA泛型中有通配符?、? extends E、? super E&…

peft / bitsandbytes包windows安装问题

peft / bitsandbytes包windows安装问题 环境版本安装peftCUDA Setup failed despite GPU being available报错信息解决方法 ImportError: cannot import name is_npu_available from accelerate.utils报错信息解决方法 AttributeError: NoneType object has no attribute cuDev…

linux部署前端静态页面(实战)

Linux基本命令&#xff08;学习笔记&#xff09;零基础入门linux系统运维_linux find exec rm_Z_Xshan的博客-CSDN博客 如果linux不熟可以看我之前写的入门教程 感谢支持&#xff01;&#xff01; 一、服务器 这里去购买云服务器&#xff0c;如果是练习可以用虚拟机&#xff…

内网穿透的应用-公网环境下移动端通过群晖管家+cpolar远程管理家中本地局域网内黑群晖设备

白嫖怪狂喜&#xff01;黑群晖也能使用群晖管家啦&#xff01; 文章目录 白嫖怪狂喜&#xff01;黑群晖也能使用群晖管家啦&#xff01;1.使用环境要求&#xff1a;2.下载安装群晖管家app3.随机地址登陆群晖管家app4.固定地址登陆群晖管家app 自己组装nas的白嫖怪们虽然也可以通…

软件设计中如何画各类图之五用例图(Use Case Diagram):系统功能需求与用户交互的图形化描述

目录 1 前言2 用例图基本介绍3 用例图的符号及说明3.1 用例&#xff08;Use Case&#xff09;3.2 参与者&#xff08;Actor&#xff09;3.2 关系&#xff08;Relationships&#xff09; 4 画用例图的步骤4.1 确定系统边界4.2 识别参与者4.3 定义用例4.4 绘制关系4.5 完善细节 5…

CopyOnWriteArrayList怎么用

什么是CopyOnWriteArrayListCopyOnWriteArrayList常用方法CopyOnWriteArrayList源码详解CopyOnWriteArrayList使用注意点CopyOnWriteArrayList存在的性能问题CopyOnWriteArrayList 使用实例基本应用实例并发应用实例 拓展写时复制 什么是CopyOnWriteArrayList CopyOnWriteArra…

2023经典软件测试面试题

1、问&#xff1a;你在测试中发现了一个bug&#xff0c;但是开发经理认为这不是一个bug&#xff0c;你应该怎样解决&#xff1f; 首先&#xff0c;将问题提交到缺陷管理库里面进行备案。 然后&#xff0c;要获取判断的依据和标准&#xff1a; 根据需求说明书、产品说明、设计…

2024清理软件排名第一的是CCleaner

CCleaner2024版是一款专业好用的系统优化和隐私保护工具。CCleaner官方版主要用来清除Windows系统不再使用的垃圾文件和使用者的上网记录以空出硬盘容量&#xff0c;按工具同时注重保护用户隐私&#xff0c;被誉为“世界上最受欢迎的PC清洁剂”。 CCleaner下载如下&#xff1a…

【23真题】押题卷的漏网之鱼!

今天分享的是23年中国计量大学805的信号与系统试题及解析。第二大题的第1小题这类题&#xff01;太经典了&#xff0c;他那个相位图像&#xff0c;怎么看都是24真题的样子图片。但是我出的话&#xff0c;会把幅频特性从三角变为矩形&#xff0c;再加上个信号是否无失真的判断。…

JavaEE进阶学习:Spring Boot 配置文件

1.配置文件的作用 整个项目中所有重要的数据都是在配置文件中配置的&#xff0c;比如&#xff1a; 数据库的连接信息&#xff08;包含用户名和密码的设置&#xff09;&#xff1b;项目的启动端口&#xff1b;第三方系统的调用秘钥等信息&#xff1b;用于发现和定位问题的普通…

【Unity动画】Unity 动画播放的流程

本文以2D为案例&#xff0c;讲解Unity 播放动画的流程 准备和导入2D动画资源 外部导入序列帧生成的 Unity内部制作的 外部导入的3D动画 2.创建动画过程 打开时间轴Ctrl6 选中场景中的一个未来需要播放动画的物体 回到时间轴点击Create一个新动画片段 拖动2D动画资源放入…

Spark---Spark on Hive

1、Spark On Hive的配置 1&#xff09;、在Spark客户端配置Hive On Spark 在Spark客户端安装包下spark-2.3.1/conf中创建文件hive-site.xml&#xff1a; 配置hive的metastore路径 <configuration><property><name>hive.metastore.uris</name><v…

景联文科技解读《2023人工智能基础数据服务产业发展白皮书》,助力解决数据标注挑战

前段时间&#xff0c;国家工业信息安全发展研究中心发布《2023人工智能基础数据服务产业发展白皮书》&#xff08;以下简称“白皮书”&#xff09;。 《白皮书》指出&#xff0c;2022年&#xff0c;中国人工智能基础数据服务产业的市场规模为45亿元&#xff0c;预计今年将达到5…

Mybatis异常org.apache.ibatis.binding.BindingException: Parameter “xxx“ not found

问题1: 可能是 mybatis 的xml&#xff0c;对应的mapper接口缺少Param注解&#xff0c;或者Param注解的value与xml的不一致 切记只要参数不是一个集合类型向下图或者多个参数值就要加Param注解 问题2: mybatis的xml&#xff0c;存在多余的注释。注释中包含#{}、${}。注释掉的代…

游戏开发增笑-扣扣死-Editor的脚本属性自定义定制-还写的挺详细的,旧版本反而更好

2012年在官方论坛注册的一个号&#xff0c;居然被禁言了&#xff0c;不知道官方现在是什么辣鸡&#xff0c;算了&#xff0c;大人不记狗子过 ”后来提交问题给CEO了&#xff0c;结果CEO百忙之中居然回复了&#xff0c;也是很低调的一个人&#xff0c;毕竟做技术的有什么坏心思呢…

Leetcode周赛374补题(3 / 3) - EA专场

不愧是EA的题&#xff0c;我最爱的模拟人生……好难&#xff0c;呜呜 目录 1、找出峰值 - 暴力枚举 2、需要添加的硬币的最小数量 - 思维 贪心 3、统计完全子字符串 - 滑窗 分组循环 1、找出峰值 - 暴力枚举 2951. 找出峰值 class Solution {public List<Integer> …

Video Studio会声会影2024中文直装旗舰版

Corel Video Studio会声会影2024中文直装旗舰版是一款很流行的视频编辑处理软件&#xff0c;由于其简单易用&#xff0c;且功能不错&#xff0c;在国内拥有众多使用者&#xff0c;小编之前给大家分享过Corel Video Studio Ultimate会声会影2024旗舰版中文版&#xff0c;今天再为…

知识蒸馏的蒸馏损失方法代码总结(包括:基于logits的方法:KLDiv,dist,dkd等,基于中间层提示的方法:)

有两种知识蒸馏方法&#xff1a;一种利用教师模型的输出概率&#xff08;基于logits的方法&#xff09;[15,14,11]&#xff0c;另一种利用教师模型的中间表示&#xff08;基于提示的方法&#xff09;[12,13,18,17]。基于logits的方法利用教师的输出作为辅助信号来训练一个较小的…

免费的SEO外链发布工具,提升排名的利器

互联网已经成为信息传播和商业发展的重要平台。而对于拥有网站的个人、企业来说&#xff0c;如何让自己的网站在搜索引擎中脱颖而出&#xff1f;SEO&#xff08;Search Engine Optimization&#xff09;作为提高网站在搜索引擎中排名的关键手段. 什么是SEO外链&#xff1f; S…

C#,数值计算——计算实对称矩阵所有特征值和特征向量的雅可比(Jacobi)方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Computes all eigenvalues and eigenvectors of /// a real symmetric matrix by Jacobis method. /// </summary> public class Jacobi { private …