《花100块做个摸鱼小网站! 》第五篇—通过xxl-job定时获取热搜数据

⭐️基础链接导航⭐️

服务器 → ☁️ 阿里云活动地址

看样例 → 🐟 摸鱼小网站地址

学代码 → 💻 源码库地址

一、前言

我们已经成功实现了一个完整的热搜组件,从后端到前端,构建了这个小网站的核心功能。接下来,我们将不断完善其功能,使其更加美观和实用。今天的主题是如何定时获取热搜数据。如果热搜数据无法定时更新,小网站将失去其核心价值。之前,我采用了@Scheduled注解来实现定时任务,但这种方式灵活性不足,因此我决定用更灵活的XXL-Job组件来替代它。

二、xxl-job部署

xxl-job是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。目前github代码库star 27.3k,开源免费的,值得学习使用一下。

1. 代码库下载

github代码库地址

下载下来后,代码库结构如下:

源码结构如下:

xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器):xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;:xxl-job-executor-sample-frameless:无框架版本;

调度中心配置内容说明:

### 调度中心JDBC链接:链接地址请保持和 2.1章节 所创建的调度数据库的地址一致
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=xxx
spring.datasource.password=xxx
spring.datasource.driver-class-name=com.mysql.jdbc.Driver### 报警邮箱
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory### 调度中心通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=### 调度中心国际化配置 [必填]: 默认为 "zh_CN"/中文简体, 可选范围为 "zh_CN"/中文简体, "zh_TC"/中文繁体 and "en"/英文;
xxl.job.i18n=zh_CN## 调度线程池最大线程配置【必填】
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100### 调度中心日志表数据保存天数 [必填]:过期日志自动清理;限制大于等于7时生效,否则, 如-1,关闭自动清理功能;
xxl.job.logretentiondays=30

2. 表结构初始化

在doc目录的 db目录下,有一个sql文件,里面有一些表和数据的初始化sql,我们要在执行XXL-Job之前要把表和数据准备好。

执行结束后,表如下:

3. 启动XXL-Job

找到XxlJobAdminApplication,启动该应用,在浏览器输入:http://localhost:12000/xxl-job-admin/toLogin,会进入XXL-Job登录界面,如下:

输入用户名:admin;密码:123456点击登录进入主界面,如下:

三、自定义爬虫任务

XXL-Job的使用也很简单,一个注解就好了,这里我说一下如何使用它。

1. 引入XXL-Job依赖

summo-sbmy-job的pom.xml下添加:

<!-- xxl-job -->
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.4.1</version>
</dependency>

2. XXL-Job配置

在application.preoperties文件中加入XXL-Job的配置,配置如下:

# xxl-job
xxl.job.open=true
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:12000/xxl-job-admin
### xxl-job, access token
xxl.job.accessToken=default_token
### xxl-job executor appname
xxl.job.executor.appname=summo-sbmy
### xxl-job executor log-path
xxl.job.executor.logpath=/root/logs/xxl-job/jobhandler
### xxl-job executor log-retention-days
xxl.job.executor.logretentiondays=30
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
xxl.job.executor.address=
### xxl-job executor server-info
xxl.job.executor.ip=
xxl.job.executor.port=9999

配置弄好之后,在com.summo.sbmy.job.config目录下创建一个config文件,创建XxlJobConfig.java,代码如下:

package com.summo.sbmy.job.config;import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** xxl-job config** @author xuxueli 2017-04-28*/
@Configuration
public class XxlJobConfig {private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);@Value("${xxl.job.admin.addresses}")private String adminAddresses;@Value("${xxl.job.accessToken}")private String accessToken;@Value("${xxl.job.executor.appname}")private String appname;@Value("${xxl.job.executor.address}")private String address;@Value("${xxl.job.executor.ip}")private String ip;@Value("${xxl.job.executor.port}")private int port;@Value("${xxl.job.executor.logpath}")private String logPath;@Value("${xxl.job.executor.logretentiondays}")private int logRetentionDays;@Bean@ConditionalOnProperty(name = "xxl.job.open", havingValue = "true")public XxlJobSpringExecutor xxlJobExecutor() {logger.info(">>>>>>>>>>> xxl-job config init.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setAddress(address);xxlJobSpringExecutor.setIp(ip);xxlJobSpringExecutor.setPort(port);xxlJobSpringExecutor.setAccessToken(accessToken);xxlJobSpringExecutor.setLogPath(logPath);xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);return xxlJobSpringExecutor;}
}

配置和类都弄好之后,重新启动应用,如果顺利的话,在XXL-Job管理的执行器界面上就可以看到一个执行器已经注册了,如下:

4. 注册XXL-Job任务

以抖音热搜为例,我们最开始使用的是 @Scheduled注解,代码如下:

/*** 定时触发爬虫方法,1个小时执行一次*/
@Scheduled(fixedRate = 1000 * 60 * 60)
public void hotSearch() throws IOException{... ...
}

@Scheduled注解替换为@XxlJob("douyinHotSearchJob"),具体的代码如下:

package com.summo.sbmy.job.douyin;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.summo.sbmy.dao.entity.SbmyHotSearchDO;
import com.summo.sbmy.service.SbmyHotSearchService;
import com.summo.sbmy.service.convert.HotSearchConvert;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;import static com.summo.sbmy.common.cache.SbmyHotSearchCache.CACHE_MAP;
import static com.summo.sbmy.common.enums.HotSearchEnum.DOUYIN;/*** @author summo* @version DouyinHotSearchJob.java, 1.0.0* @description 抖音热搜Java爬虫代码* @date 2024年08月09*/
@Component
@Slf4j
public class DouyinHotSearchJob {@Autowiredprivate SbmyHotSearchService sbmyHotSearchService;@XxlJob("douyinHotSearchJob")public ReturnT<String> hotSearch(String param) throws IOException {log.info("抖音热搜爬虫任务开始");try {//查询抖音热搜数据OkHttpClient client = new OkHttpClient().newBuilder().build();Request request = new Request.Builder().url("https://www.iesdouyin.com/web/api/v2/hotsearch/billboard/word/").method("GET", null).build();Response response = client.newCall(request).execute();JSONObject jsonObject = JSONObject.parseObject(response.body().string());JSONArray array = jsonObject.getJSONArray("word_list");List<SbmyHotSearchDO> sbmyHotSearchDOList = Lists.newArrayList();for (int i = 0, len = array.size(); i < len; i++) {//获取知乎热搜信息JSONObject object = (JSONObject) array.get(i);//构建热搜信息榜SbmyHotSearchDO sbmyHotSearchDO = SbmyHotSearchDO.builder().hotSearchResource(DOUYIN.getCode()).build();//设置文章标题sbmyHotSearchDO.setHotSearchTitle(object.getString("word"));//设置知乎三方IDsbmyHotSearchDO.setHotSearchId(getHashId(DOUYIN.getCode() + sbmyHotSearchDO.getHotSearchTitle()));//设置文章连接sbmyHotSearchDO.setHotSearchUrl("https://www.douyin.com/search/" + sbmyHotSearchDO.getHotSearchTitle() + "?type=general");//设置热搜热度sbmyHotSearchDO.setHotSearchHeat(object.getString("hot_value"));//按顺序排名sbmyHotSearchDO.setHotSearchOrder(i + 1);sbmyHotSearchDOList.add(sbmyHotSearchDO);}if (CollectionUtils.isEmpty(sbmyHotSearchDOList)) {return ReturnT.SUCCESS;}//数据加到缓存中CACHE_MAP.put(DOUYIN.getCode(), sbmyHotSearchDOList.stream().map(HotSearchConvert::toDTOWhenQuery).collect(Collectors.toList()));//数据持久化sbmyHotSearchService.saveCache2DB(sbmyHotSearchDOList);log.info("抖音热搜爬虫任务结束");} catch (IOException e) {log.error("获取抖音数据异常", e);}return ReturnT.SUCCESS;}/*** 根据文章标题获取一个唯一ID** @param title 文章标题* @return 唯一ID*/private String getHashId(String title) {long seed = title.hashCode();Random rnd = new Random(seed);return new UUID(rnd.nextLong(), rnd.nextLong()).toString();}}

在XXL-Job管理台的任务管理界面中点击新增任务,如下:

创建好任务后,我们可以手动运行一次,如下:

这样抖音的热搜任务我们就配置好了,其他的爬虫任务也是这样的配置。

四、热搜更新时间

目前我们已经实现了三个热搜组件,百度、抖音、知乎,但是我们并不知道这些热搜是什么时候更新的,也不知道是不是实时的,所以我们需要把热搜更新时间放出来,大概下面这样子:


优化后组件代码如下:

<template><el-card class="custom-card" v-loading="loading"><template #header><div class="card-title"><img :src="icon" class="card-title-icon" />{{ title }}热榜<span class="update-time">{{ formattedUpdateTime }}</span></div></template><div class="cell-group-scrollable"><divv-for="item in hotSearchData":key="item.hotSearchOrder":class="getRankingClass(item.hotSearchOrder)"class="cell-wrapper"><span class="cell-order">{{ item.hotSearchOrder }}</span><spanclass="cell-title hover-effect"@click="openLink(item.hotSearchUrl)">{{ item.hotSearchTitle }}</span><span class="cell-heat">{{ formatHeat(item.hotSearchHeat) }}</span></div></div></el-card>
</template><script>
import apiService from "@/config/apiService.js";export default {props: {title: String,icon: String,type: String,},data() {return {hotSearchData: [],updateTime: null,loading: false,};},created() {this.fetchData(this.type);},computed: {formattedUpdateTime() {if (!this.updateTime) return '';const updateDate = new Date(this.updateTime);const now = new Date();const timeDiff = now - updateDate;const minutesDiff = Math.floor(timeDiff / 1000 / 60);if (minutesDiff < 1) {return '刚刚更新';} else if (minutesDiff < 60) {return `${minutesDiff}分钟前更新`;} else if (minutesDiff < 1440) {return `${Math.floor(minutesDiff / 60)}小时前更新`;} else {return updateDate.toLocaleString();}},},methods: {fetchData(type) {this.loading = true;apiService.get("/hotSearch/queryByType?type=" + type).then((res) => {this.hotSearchData = res.data.data.hotSearchDTOList;this.updateTime = res.data.data.updateTime;}).catch((error) => {console.error(error);}).finally(() => {this.loading = false; });},getRankingClass(order) {if (order === 1) return "top-ranking-1";if (order === 2) return "top-ranking-2";if (order === 3) return "top-ranking-3";return "";},formatHeat(heat) {if (typeof heat === "string" && heat.endsWith("万")) {return heat;}let number = parseFloat(heat);if (isNaN(number)) {return heat;}if (number < 1000) {return number.toString();}if (number >= 1000 && number < 10000) {return (number / 1000).toFixed(1) + "k";}if (number >= 10000) {return (number / 10000).toFixed(1) + "万";}},openLink(url) {if (url) {window.open(url, "_blank");}},},
};
</script><style scoped>
.custom-card {background-color: #ffffff;border-radius: 10px;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);margin-bottom: 20px;
}
.custom-card:hover {box-shadow: 0 6px 8px rgba(0, 0, 0, 0.25);
}
.el-card__header {padding: 10px 18px;display: flex;justify-content: space-between; /* Added to space out title and update time */align-items: center;
}
.card-title {display: flex;align-items: center;font-weight: bold;font-size: 16px;flex-grow: 1;
}
.card-title-icon {fill: currentColor;width: 24px;height: 24px;margin-right: 8px;
}
.update-time {font-size: 12px;color: #b7b3b3;margin-left: auto; /* Ensures it is pushed to the far right */
}
.cell-group-scrollable {max-height: 350px;overflow-y: auto;padding-right: 16px; flex: 1;
}
.cell-wrapper {display: flex;align-items: center;padding: 8px 8px; border-bottom: 1px solid #e8e8e8; 
}
.cell-order {width: 20px;text-align: left;font-size: 16px;font-weight: 700;margin-right: 8px;color: #7a7a7a; 
}
.cell-heat {min-width: 50px;text-align: right;font-size: 12px;color: #7a7a7a;
}
.cell-title {font-size: 13px;color: #495060;line-height: 22px;flex-grow: 1;overflow: hidden;text-align: left; text-overflow: ellipsis; 
}
.top-ranking-1 .cell-order {color: #fadb14; /* 金色 */
}
.top-ranking-2 .cell-order {color: #a9a9a9; /* 银色 */
}
.top-ranking-3 .cell-order {color: #d48806; /* 铜色 */
}
.cell-title.hover-effect {cursor: pointer; transition: color 0.3s ease; 
}
.cell-title.hover-effect:hover {color: #409eff; 
}
</style>

优化后,我们看一下最终的样式,如下:

这样,我们使用XXL-Job改造热搜组件就完成了,详细代码可以去看我的代码仓库。

番外:B站热搜爬虫

1. 爬虫方案评估

B站不是热搜,是热门视频, 但逻辑是一样的,它的接口是:https://api.bilibili.com/x/web-interface/ranking/v2

这个接口返回的是JSON格式数据,这就很简单了,看下结构就行。

2. 网页解析代码

这个就可以使用Postman生成调用代码,流程我就不赘述了,直接上代码,BilibiliHotSearchJob:

package com.summo.sbmy.job.bilibili;import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;import com.google.common.collect.Lists;
import com.summo.sbmy.common.model.dto.HotSearchDetailDTO;
import com.summo.sbmy.dao.entity.SbmyHotSearchDO;
import com.summo.sbmy.service.SbmyHotSearchService;
import com.summo.sbmy.service.convert.HotSearchConvert;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import static com.summo.sbmy.common.cache.SbmyHotSearchCache.CACHE_MAP;
import static com.summo.sbmy.common.enums.HotSearchEnum.BILIBILI;/*** @author summo* @version BilibiliHotSearchJob.java, 1.0.0* @description B站热榜Java爬虫代码* @date 2024年08月19*/
@Component
@Slf4j
public class BilibiliHotSearchJob {@Autowiredprivate SbmyHotSearchService sbmyHotSearchService;@XxlJob("bilibiliHotSearchJob")public ReturnT<String> hotSearch(String param) throws IOException {log.info("B站热搜爬虫任务开始");try {//查询B站热搜数据OkHttpClient client = new OkHttpClient().newBuilder().build();Request request = new Request.Builder().url("https://api.bilibili.com/x/web-interface/ranking/v2").addHeader("User-Agent", "Mozilla/5.0 (compatible)").addHeader("Cookie", "b_nut=1712137652; "+ "buvid3=DBA9C433-8738-DD67-DCF5" + "-DDC780CA892052512infoc").method("GET", null).build();Response response = client.newCall(request).execute();JSONObject jsonObject = JSONObject.parseObject(response.body().string());JSONArray array = jsonObject.getJSONObject("data").getJSONArray("list");List<SbmyHotSearchDO> sbmyHotSearchDOList = Lists.newArrayList();for (int i = 0, len = array.size(); i < len; i++) {//获取B站热搜信息JSONObject object = (JSONObject)array.get(i);//构建热搜信息榜SbmyHotSearchDO sbmyHotSearchDO = SbmyHotSearchDO.builder().hotSearchResource(BILIBILI.getCode()).build();//设置B站三方IDsbmyHotSearchDO.setHotSearchId(object.getString("aid"));//设置文章连接sbmyHotSearchDO.setHotSearchUrl(object.getString("short_link_v2"));//设置文章标题sbmyHotSearchDO.setHotSearchTitle(object.getString("title"));//设置作者名称sbmyHotSearchDO.setHotSearchAuthor(object.getJSONObject("owner").getString("name"));//设置作者头像sbmyHotSearchDO.setHotSearchAuthorAvatar(object.getJSONObject("owner").getString("face"));//设置文章封面sbmyHotSearchDO.setHotSearchCover(object.getString("pic"));//设置热搜热度sbmyHotSearchDO.setHotSearchHeat(object.getJSONObject("stat").getString("view"));//按顺序排名sbmyHotSearchDO.setHotSearchOrder(i + 1);sbmyHotSearchDOList.add(sbmyHotSearchDO);}if (CollectionUtils.isEmpty(sbmyHotSearchDOList)) {return ReturnT.SUCCESS;}//数据加到缓存中CACHE_MAP.put(BILIBILI.getCode(), HotSearchDetailDTO.builder()//热搜数据.hotSearchDTOList(sbmyHotSearchDOList.stream().map(HotSearchConvert::toDTOWhenQuery).collect(Collectors.toList()))//更新时间.updateTime(Calendar.getInstance().getTime()).build());//数据持久化sbmyHotSearchService.saveCache2DB(sbmyHotSearchDOList);log.info("B站热搜爬虫任务结束");} catch (IOException e) {log.error("获取B站数据异常", e);}return ReturnT.SUCCESS;}}

看下效果,第一行的4个热搜已经出来了,如下:

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

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

相关文章

chrome插件模拟isTrusted的事件

文章目录 方法原理 使用js模拟的事件isTrusted的值时false。有的时候我们想要模拟sTrusted未true的事件就比较麻烦了。 我们可以利用chrome插件的 chrome.debugger解决改问题。 方法 大体思路是&#xff1a;模拟事件的请求从content_script.js发出&#xff0c;到达background…

【类模板】类模板的特化

一、类模板的泛化 与函数模板一样&#xff0c;类模板的泛化就是普通的模板&#xff0c;不具有特殊性的模板。 以下的类模板为泛化的版本 //类模板的泛化 template<typename T,typename U> struct TC {//静态成员变量static int static_varible; //声明TC() {std::cout…

常见图像图片属性的介绍与说明

图像属性是指图像的一些基本特征和参数&#xff0c;它们定义了图像的外观和存储方式。以下是一些常见的图像属性&#xff1a; 1. 分辨率&#xff1a; 分辨率通常以像素数&#xff08;如800x600&#xff09;来表示&#xff0c;指的是图像的宽度和高度上的像素点数。分辨率越高&…

【Spring Boot-IDEA创建spring boot项目方法】

1. 使用Spring Initializr 的 Web页面创建项目 2. 使用 IDEA 直接创建项目&#xff0c;其中有两种不同的搭建路径 3. 使用 IDEA 创建Maven项目并改造为springBoot 最常使用的两种方法其实就是一种&#xff0c;这里介绍在ieda中如何搭建 SpringBoot项目。 1.new Project--> 2…

剑侠情缘c#版(游戏源码+资源+工具+程序),百度云盘下载,大小1.68G

剑侠情缘c#版&#xff08;游戏源码资源工具程序&#xff09;&#xff0c;c#开发的&#xff0c;喜欢研究游戏的可以下载看看。亲测可进游戏。 剑侠情缘c#版&#xff08;游戏源码资源工具程序&#xff09;下载地址&#xff1a; 通过网盘分享的文件&#xff1a;【游戏】剑侠情缘c#…

误删文件回收站也清空了怎么找回?误删文件的救援方案

在数字化时代&#xff0c;电脑中的文件安全至关重要。然而&#xff0c;有时我们可能因为一时疏忽&#xff0c;误删了重要文件&#xff0c;甚至在慌乱中清空了回收站。面对这种情况&#xff0c;很多人会感到惊慌失措&#xff0c;担心重要数据就此丢失。但请不要绝望&#xff0c;…

系统架构设计师——系统性能

性能指标 计算机性能指标 操作系统性能指标 网络的性能指标 数据库的性能指标 数据库管理系统的性能指标 应用系统的性能指标 Web服务器的性能指标 性能计算 定义法 计算方法主要包括定义法、公式法、程序检测法和仪器检测法。这些方法分别通过直接获取理想数据、应用衍生出的…

shell脚本—————局域网IP扫描

#!/bin/bash #该脚本用于采集某个C类网络存活主机的MAC地址 #使用方法&#xff1a;bash 脚本名字网卡名字网段前三位.10.144.100. #ETH$(ifconfig | grep eth | awk {print $1})for ip in {1..254} do { arping -c 2 -w 1 -I $1 $2$ip| grep "reply from" > /dev/…

SAP 查询中间表

可以看到如下代码中&#xff0c;查询了底表zdbconn&#xff0c;又查了中间表ZTFI0072 DATA: gv_dbs(20) ,go_exc_ref TYPE REF TO cx_sy_native_sql_error,gv_error_text TYPE string,lv_count TYPE syst_index.SELECT SINGLE conntxtFROM zdbconn INTO gv_dbsWHERE sy…

YOLOV5入门教程day3

一. 导入包和基本配置 import argparse import math import os import random import subprocess import sys import time from copy import deepcopy from datetime import datetime, timedelta from pathlib import Pathtry:import comet_ml # must be imported before torc…

[论文笔记] LLM模型剪枝

Attention Is All You Need But You Don’t Need All Of It For Inference of Large Language Models LLaMA2在剪枝时,跳过ffn和跳过full layer的效果差不多。相比跳过ffn/full layer,跳过attention layer的影响会更小。 跳过attention layer:7B/13B从100%参…

前端常考面试题

一、HTML 二、CSS 1. vw vh em rem 2. 盒模型 是什么&#xff0c;啥区别 3. 2栏布局、三栏布局 4. 水平垂直剧中效果 5. BFC 6. 移动端 三、Js 1. 列举JS常用算法 2. Promise的方法和状态 3. 排序算法有哪些 4. 深浅拷贝 5. 防抖和节流 6. 数组扁平化 自己递归…

Eureka简介与开发

Eureka 是由 Netflix 开源的服务发现和注册中心&#xff0c;它提供了服务的注册与发现功能&#xff0c;是 Spring Cloud 体系中的核心组件之一。Eureka 采用 C/S 架构&#xff0c;包含 Eureka Server 和 Eureka Client 两个主要的组件。 **Eureka Server** 充当服务注册中心&a…

数字芯片中I/O单元及电源domain布局中SIPI的考虑

芯片设计的物理实施过程通常也简称为布局布线&#xff08;P&R&#xff0c;Place-and-Route&#xff09;&#xff0c;布局一般被分为布局规划&#xff08;Floorplan&#xff09;和标准单元摆放&#xff08;Place&#xff09;两个过程。而其中的布局规划是芯片后端物理实现过…

Cubase操作:就地渲染 配和弦技巧 合并多段音频 隐藏标记轨序号 删除素材池多余音频

“授人以鱼&#xff0c;不如授之以渔&#xff0c;授人以鱼只救一时之急&#xff0c;授人以渔则可解一生之需。” ​有时侯做音乐最重要的就是不要太死板和要多思考&#xff01;如果被教的只有一部分&#xff0c;只学一部分&#xff0c;有时是很难理解的&#xff0c;一些人可能只…

2 Python开发工具:PyCharm的安装和使用

本文是 Python 系列教程第 2 篇&#xff0c;完整系列请查看 Python 专栏。 1 安装 官网下载地址https://www.jetbrains.com.cn/pycharm/&#xff0c;文件比较大&#xff08;约861MB&#xff09;请耐心等待 双击exe安装 安装成功后会有一个30天的试用期。。。本来想放鸡火教程&…

【python笔记】deque()、list()、heapq主要区别

内部实现 1、deque() deque是Python中的一个双端队列&#xff0c;位于collections模块中。 数据结构&#xff1a; deque 是一个双端队列&#xff0c;其内部实现基于一个双向链表。 这意味着元素不是连续存储在内存中的&#xff0c;而是分布在多个节点中&#xff0c;每个节点包含…

05_react应用(基于react脚手架)

react应用&#xff08;基于react脚手架&#xff09; 一、使用 create-react-app 创建 react 应用1、react 脚手架2、创建项目并启动3、react 脚手架项目结构 二、样式冲突解决方案、 react 插件安装、编码流程1、样式冲突2、vscode 的 react 插件安装3、功能界面的组件化编码流…

单挑ChatGPT模型,AI最强竞争对手来了!

在2024年3月&#xff0c;Anthropic公司发布了最新的Claude 3系列模型&#xff0c;包括Claude 3 Haiku、Claude 3 Sonnet和Claude 3 Opus三款模型。这些模型在性能上全面超越了之前的版本&#xff0c;并且在多个基准测试上表现出色&#xff0c;被认为是AI技术的一大突破。Claude…

C练手题--Exclusive “or“ (xor) Logical Operator 【8 kyu】

一、原题 链接&#xff1a;Training on Exclusive "or" (xor) Logical Operator | Codewars Exclusive "or" (xor) Logical Operator Overview In some scripting languages like PHP, there exists a logical operator (e.g. &&, ||, and, or, e…