当前位置: 首页 > news >正文

【Hadoop综合实践】手机卖场大数据综合项目分析

🚀 本文章实现了基于MapReduce的手机浏览日志分析
🚀 文章简介:主要包含了数据生成部分,数据处理部分,数据存储部分与数据可视化部分
🚀 【本文仅供参考!!非唯一答案】其中需求实现的方式有多种,提供的代码并非唯一写法,选择适合的方式即可。

目录

        • 手机日志分析需求
        • 数据生成工具类
        • 模拟数据生成类
        • MapReduce程序需求编写

手机日志分析需求

  • 本文主要实现以下需求
  1. 编写数据生成器生成1G~10G大小的数据,字段必须包括id,日期,手机号码、型号、操作系统字段。
  2. 需要将手机号码4~9为掩码处理。
  3. 分析2021年、2022年操作系统市场占比、手机型号市场占比情况
  4. 分析2022年手机运营商市场占比情况
  5. 分析数据存储到HDFS集群/ana/phone节点下面
  6. 将分析结果存储到Mysql,并进行数据可视化

数据生成工具类

  • 手机号码随机生成
  • 可以采用随机数生成的方式,结合三大运营商的号码前三位数为规则进行生成 代码如下
/*** @Description  生成三大运营商的手机号*/
/*** 中国移动手机号段:* 134、135、136、137、138、139、147、150、151、152、157、158、159、172、178、182、183、184、187、188、198、1703、1705、1706* 中国联通手机号段:* 130、131、132、145、155、156、166、171、175、176、185、186、1704、1707、1708、1709* 中国电信手机号段:* 133、153、173、177、180、181、189、191、193、199、1700、1701、1702* 腾讯云API https://market.cloud.tencent.com/products/31101*/
public class PhoneNumberGenerator {//生成一万个手机号码,只需将 generatePhoneNumbers 方法中的参数 count 修改为 10000 即可//移动private static final String[] CHINA_MOBILE_PREFIX = {"134", "139", "150", "151", "182"};//联通private static final String[] CHINA_UNICOM_PREFIX = {"130","155","186"};//电信private static final String[] CHINA_TELECOM_PREFIX = {"133","153","180","181","189"};public static void main(String[] args) {String phoneNumbers = generatePhoneNumbers(1);System.out.println(phoneNumbers);}public static String generatePhoneNumbers(int count) {String phoneNumber=null;Random random = new Random();for (int i = 0; i < count; i++) {String prefix;int operatorIndex = random.nextInt(3);switch (operatorIndex) {case 0:prefix = CHINA_MOBILE_PREFIX[random.nextInt(CHINA_MOBILE_PREFIX.length)];break;case 1:prefix = CHINA_UNICOM_PREFIX[random.nextInt(CHINA_UNICOM_PREFIX.length)];break;default:prefix = CHINA_TELECOM_PREFIX[random.nextInt(CHINA_TELECOM_PREFIX.length)];}phoneNumber = prefix + generateRandomNumber(random, 11 - prefix.length());}return replaceCharacters(phoneNumber,3,8);}private static String replaceCharacters(String input, int startIndex, int endIndex) {if (input == null || input.length() < endIndex) {return input;}StringBuilder sb = new StringBuilder(input);for (int i = startIndex; i <= endIndex; i++) {sb.setCharAt(i, '*');}return sb.toString();}private static String generateRandomNumber(Random random, int length) {StringBuilder sb = new StringBuilder();for (int i = 0; i < length; i++) {sb.append(random.nextInt(10));}return sb.toString();}
}
  • 运营商解析的其中一种方式 【采用接口分析】
  • 这里可以使用鹅厂或者其他厂商开发的接口进行运营商识别 申请获取对应的秘钥即可 例子如下

public class PhoneOperator {public static String calcAuthorization(String source, String secretId, String secretKey, String datetime)throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {String signStr = "x-date: " + datetime + "\n" + "x-source: " + source;Mac mac = Mac.getInstance("HmacSHA1");Key sKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), mac.getAlgorithm());mac.init(sKey);byte[] hash = mac.doFinal(signStr.getBytes("UTF-8"));String sig = new BASE64Encoder().encode(hash);String auth = "hmac id=\"" + secretId + "\", algorithm=\"hmac-sha1\", headers=\"x-date x-source\", signature=\"" + sig + "\"";return auth;}public static String urlencode(Map<?, ?> map) throws UnsupportedEncodingException {StringBuilder sb = new StringBuilder();for (Map.Entry<?, ?> entry : map.entrySet()) {if (sb.length() > 0) {sb.append("&");}sb.append(String.format("%s=%s",URLEncoder.encode(entry.getKey().toString(), "UTF-8"),URLEncoder.encode(entry.getValue().toString(), "UTF-8")));}return sb.toString();}public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {//云市场分配的密钥IdString secretId = "xx";//云市场分配的密钥KeyString secretKey = "xx;String source = "market";Calendar cd = Calendar.getInstance();SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);sdf.setTimeZone(TimeZone.getTimeZone("GMT"));String datetime = sdf.format(cd.getTime());// 签名String auth = calcAuthorization(source, secretId, secretKey, datetime);// 请求方法String method = "POST";// 请求头Map<String, String> headers = new HashMap<String, String>();headers.put("X-Source", source);headers.put("X-Date", datetime);headers.put("Authorization", auth);// 查询参数Map<String, String> queryParams = new HashMap<String, String>();queryParams.put("mobile","XXX");// body参数Map<String, String> bodyParams = new HashMap<String, String>();// url参数拼接String url = "https://service-8c43o60c-1253285064.gz.apigw.tencentcs.com/release/sms";if (!queryParams.isEmpty()) {url += "?" + urlencode(queryParams);}BufferedReader in = null;try {URL realUrl = new URL(url);HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();conn.setConnectTimeout(5000);conn.setReadTimeout(5000);conn.setRequestMethod(method);// request headersfor (Map.Entry<String, String> entry : headers.entrySet()) {conn.setRequestProperty(entry.getKey(), entry.getValue());}// request bodyMap<String, Boolean> methods = new HashMap<>();methods.put("POST", true);methods.put("PUT", true);methods.put("PATCH", true);Boolean hasBody = methods.get(method);if (hasBody != null) {conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");conn.setDoOutput(true);DataOutputStream out = new DataOutputStream(conn.getOutputStream());out.writeBytes(urlencode(bodyParams));out.flush();out.close();}// 定义 BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(conn.getInputStream()));String line;String result = "";while ((line = in.readLine()) != null) {result += line;}System.out.println(result);} catch (Exception e) {System.out.println(e);e.printStackTrace();} finally {try {if (in != null) {in.close();}} catch (Exception e2) {e2.printStackTrace();}}}
}

结果如下 (另一种方式为:直接根据前三位手机号进行判断)
在这里插入图片描述

模拟数据生成类

  • 数据生成器 id,日期,手机号码、型号、操作系统

/*** @Description*  数据生成器  id,日期,手机号码、型号、操作系统*  id:UUID 随机生成  日期:2021 2022 手机号码:三大运营商  型号:Apple HuaWei Oppo Vivo Meizu Nokia  操作系统:Apple ios Harmony Samsung*  1.分析2021年、2022年操作系统市场占比、手机型号市场占比情况*  2.分析2022年手机运营商市场占比情况*  3.分析数据存储到HDFS集群/ana/phone节点下面*  4.将分析结果存储到Mysql,并进行数据可视化*/
public class DataGenerator {public static void main(String[] args) {try {BufferedWriter writer = new BufferedWriter(new FileWriter("data/phone.log"));for (int i = 0; i < 1000; i++) {//UUID随机生成   id,日期,手机号码、型号、操作系统String id = UUID.randomUUID().toString();String date = getRandomDate();String phoneNumber = PhoneNumberGenerator.generatePhoneNumbers(1);String model = getRandomModel();String operatingSystem = getRandomOperatingSystem();String line = id + "," + date + "," + phoneNumber + "," + model + "," + operatingSystem;writer.write(line);writer.newLine();}writer.close();} catch (IOException e) {e.printStackTrace();}}private static String getRandomDate() {Random random = new Random();int year = random.nextInt(2) == 0 ? 2021 : 2022;int month = random.nextInt(12) + 1;int dayOfMonth;if (month == 2) {dayOfMonth = random.nextInt(28) + 1;} else if (month == 4 || month == 6 || month == 9 || month == 11) {dayOfMonth= random.nextInt(30) + 1;} else {dayOfMonth= random.nextInt(31) + 1;}return year + "-" +(month < 10 ? "0" : "") +month+ "-" +(dayOfMonth<10? "0":"")+dayOfMonth ;}private static String getRandomPhoneNumber() {Random random = new Random();StringBuilder phoneNumber = new StringBuilder("1");for (int i = 0; i < 10; i++) {phoneNumber.append(random.nextInt(10));}return phoneNumber.toString();}private static String getRandomModel() {String[] models = {"Apple", "HuaWei", "Oppo", "Vivo", "Meizu", "Nokia"};return models[new Random().nextInt(models.length)];}private static String getRandomOperatingSystem() {String[] operatingSystems = {"Apple", "HarmonyOS", "Samsung","iOS"};return operatingSystems[new Random().nextInt(operatingSystems.length)];}
}

结果如下
在这里插入图片描述

MapReduce程序需求编写

  • 分析2021年、2022年操作系统市场占比、手机型号市场占比情况

/*** @Description*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Partitioner;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class PhoneOSAnalysis {private static int totalCount;private static int lineCount2021 = 0;private static int lineCount2022 = 0;public static class TokenizerMapper extends Mapper<Object, Text, Text, DoubleWritable> {private final static DoubleWritable one = new DoubleWritable(1);private Text word = new Text();public void map(Object key, Text value, Context context) throws IOException, InterruptedException {String[] fields = value.toString().split(",");if (fields.length >= 5) {// 操作系统市场占比word.set(fields[1].substring(0, 4) + "-OS-" + fields[4]);context.write(word, one);// 手机型号市场占比word.set(fields[1].substring(0, 4) + "-Model-" + fields[3]);context.write(word, one);}}}public static class MarketShareReducer extends Reducer<Text, DoubleWritable, Text, DoubleWritable> {private DoubleWritable result = new DoubleWritable();public void reduce(Text key, Iterable<DoubleWritable> values, Context context)throws IOException, InterruptedException {double sum = 0;for (DoubleWritable val : values) {//这里会根据分组的key来计算sumsum += val.get();}int yearTotalCount = key.toString().contains("2021") ? lineCount2021 : lineCount2022;double percentage = sum / yearTotalCount;result.set(percentage);context.write(key, result);}}public static void main(String[] args) throws Exception {Configuration conf = new Configuration();FileSystem fs = FileSystem.get(conf);Path inputPath = new Path("data/phone.log");FSDataInputStream inputStream = fs.open(inputPath);try (BufferedReader reader = new BufferedReader(new InputStreamReader(fs.open(inputPath)))) {String line;while ((line = reader.readLine()) != null) {if (line.contains("2021")) {lineCount2021++;} else if (line.contains("2022")) {lineCount2022++;}}}//        totalCount = Math.max(lineCount2021, lineCount2022);Job job = Job.getInstance(conf, "market share analysis");job.setJarByClass(PhoneOSAnalysis.class);job.setMapperClass(TokenizerMapper.class);// 设置自定义分区器job.setPartitionerClass(CustomPartitioner.class);job.setNumReduceTasks(2);job.setReducerClass(MarketShareReducer.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(DoubleWritable.class);Path outputPath = new Path("data/result");if (fs.exists(outputPath)) {fs.delete(outputPath, true);}FileInputFormat.addInputPath(job, new Path("data/phone.log"));FileOutputFormat.setOutputPath(job, new Path(String.valueOf(outputPath)));//        TextInputFormat.addInputPath(job, new Path("hdfs://192.168.192.100:8020/"));
//        TextInputFormat.outInputPath(job, new Path("hdfs://192.168.192.100:8020/"));System.exit(job.waitForCompletion(true) ? 0 : 1);}public static class CustomPartitioner extends Partitioner<Text, DoubleWritable> {@Overridepublic int getPartition(Text key, DoubleWritable value, int numPartitions) {// 根据年份进行分区if (key.toString().contains("2021")) {return 0;} else {return 1;}}}
}
  • 分析2022年手机运营商市场占比情况

/*** @Description*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;public class OperatorMR {private static int lineCount2022 = 0;public static class TokenizerMapper extends Mapper<Object, Text, Text, DoubleWritable> {private final static DoubleWritable one = new DoubleWritable(1);private Text word = new Text();public void map(Object key, Text value, Context context) throws IOException, InterruptedException {String[] fields = value.toString().split(",");if (fields.length >= 3 && fields[1].contains("2022")) {// 手机运营商市场占比word.set(fields[1].substring(0, 4) + "-Operator-" + getCarrier(fields[2]));context.write(word, one);}}private String getCarrier(String phoneNumber) {String prefix = phoneNumber.substring(0, 3);switch (prefix) {//"133","153","180","181","189"case "133":case "153":case "180":case "181":case "189":return "电信";//"130","155","186"case "130":case "155":case "186":return "联通";default:return "移动";}}}public static class MarketShareReducer extends Reducer<Text, DoubleWritable, Text, DoubleWritable> {private DoubleWritable result = new DoubleWritable();public void reduce(Text key, Iterable<DoubleWritable> values, Context context)throws IOException, InterruptedException {double sum = 0;for (DoubleWritable val : values) {sum += val.get();}double percentage = sum / lineCount2022;result.set(percentage);context.write(key, result);}}public static void main(String[] args) throws Exception {Configuration conf = new Configuration();FileSystem fs = FileSystem.get(conf);Path inputPath = new Path("data/phone.log");try (BufferedReader reader = new BufferedReader(new InputStreamReader(fs.open(inputPath)))) {String line;while ((line = reader.readLine()) != null) {if (line.contains("2022")) {lineCount2022++;}}}Job job = Job.getInstance(conf, "PhoneOperator");job.setJarByClass(OperatorMR.class);job.setMapperClass(TokenizerMapper.class);job.setReducerClass(MarketShareReducer.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(DoubleWritable.class);Path outputPath = new Path("data/result-phone");if (fs.exists(outputPath)) {fs.delete(outputPath, true);}
//        TextInputFormat.addInputPath(job, new Path("hdfs://192.168.192.100:8020/"));
//        TextInputFormat.outInputPath(job, new Path("hdfs://192.168.192.100:8020/"));FileInputFormat.addInputPath(job, new Path("data/phone.log"));FileOutputFormat.setOutputPath(job, outputPath);System.exit(job.waitForCompletion(true) ? 0 : 1);}
}

结果如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

-将分析结果存储到Mysql,并进行数据可视化

package com.yopai.mrmysql;/*** @Description*/import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.db.DBConfiguration;
import org.apache.hadoop.mapreduce.lib.db.DBOutputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;public class OPMysqlMR {private static int lineCount2022 = 0;public static class TokenizerMapper extends Mapper<Object, Text, Text, DoubleWritable> {private final static DoubleWritable one = new DoubleWritable(1);private Text word = new Text();public void map(Object key, Text value, Context context) throws IOException, InterruptedException {String[] fields = value.toString().split(",");if (fields.length >= 3 && fields[1].contains("2022")) {// 手机运营商市场占比word.set(fields[1].substring(0, 4) + "-Operator-" + getCarrier(fields[2]));context.write(word, one);}}private String getCarrier(String phoneNumber) {String prefix = phoneNumber.substring(0, 3);switch (prefix) {case "133":case "153":case "180":case "181":case "189":return "电信";case "130":case "155":case "186":return "联通";default:return "移动";}}}public static class MarketShareReducer extends Reducer<Text, DoubleWritable, DBOutputWritable, NullWritable> {private DoubleWritable result = new DoubleWritable();public void reduce(Text key, Iterable<DoubleWritable> values, Context context)throws IOException, InterruptedException {double sum = 0;for (DoubleWritable val : values) {sum += val.get();}double percentage = sum / lineCount2022;result.set(percentage);context.write(new DBOutputWritable(key.toString(), result.get()), NullWritable.get());}}public static void main(String[] args) throws Exception {Configuration conf = new Configuration();// 设置数据库连接信息String dbUrl = "jdbc:mysql://localhost:3306/blog";String dbUsername = "root";String dbPassword = "Admin2022!";DBConfiguration.configureDB(conf, "com.mysql.jdbc.Driver", dbUrl, dbUsername, dbPassword);try (Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword)) {String createTableSql = "CREATE TABLE IF NOT EXISTS operator_market_share(operator VARCHAR(255), market_share DOUBLE)";PreparedStatement preparedStatement = connection.prepareStatement(createTableSql);preparedStatement.executeUpdate();}FileSystem fs = FileSystem.get(conf);Path inputPath = new Path("data/phone.log");try (BufferedReader reader = new BufferedReader(new InputStreamReader(fs.open(inputPath)))) {String line;while ((line = reader.readLine()) != null) {if (line.contains("2022")) {lineCount2022++;}}}Job job = Job.getInstance(conf, "PhoneOperator");job.setJarByClass(OPMysqlMR.class);job.setMapperClass(TokenizerMapper.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(DoubleWritable.class);job.setReducerClass(MarketShareReducer.class);job.setOutputKeyClass(DBOutputWritable.class);job.setOutputValueClass(NullWritable.class);// 设置数据库输出DBOutputFormat.setOutput(job, "operator_market_share", "operator", "market_share");FileInputFormat.addInputPath(job, new Path("data/phone.log"));System.exit(job.waitForCompletion(true) ? 0 : 1);}
}
package com.yopai.mrmysql;import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.mapred.lib.db.DBWritable;import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** @Description*/
public class DBOutputWritable implements Writable, DBWritable {private String operator;private double market_share;public DBOutputWritable() {}public DBOutputWritable(String operator, double market_share) {this.operator = operator;this.market_share = market_share;}@Overridepublic void readFields(DataInput in) throws IOException {operator = in.readUTF();market_share = in.readDouble();}@Overridepublic void write(DataOutput out) throws IOException, IOException {out.writeUTF(operator);out.writeDouble(market_share);}@Overridepublic void readFields(ResultSet resultSet) throws SQLException {// 不需要实现此方法,因为我们只会写入数据到数据库}@Overridepublic void write(PreparedStatement preparedStatement) throws SQLException {preparedStatement.setString(1, operator);preparedStatement.setDouble(2, market_share);}
}

运行结果如下
在这里插入图片描述

  • 可视化操作
package com.yopai.draw;/*** @Description*/
import java.awt.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot;
import org.jfree.data.general.DefaultPieDataset;public class PieChartExample extends JFrame {public PieChartExample() {// 从数据库获取数据DefaultPieDataset dataset = new DefaultPieDataset();try {String dbUrl = "jdbc:mysql://localhost:3306/blog";String dbUsername = "root";String dbPassword = "Admin2022!";Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery("SELECT operator, market_share FROM operator_market_share");while (resultSet.next()) {String operator = resultSet.getString("operator");double marketShare = resultSet.getDouble("market_share");dataset.setValue(operator, marketShare);}} catch (Exception e) {e.printStackTrace();}// 创建饼图JFreeChart pieChart = ChartFactory.createPieChart("运营商市场占比",   // 图表标题dataset,          // 数据集true,             // 是否显示图例true,             // 是否生成工具提示false             // 是否生成URL链接);// 设置字体以显示中文Font font = new Font("宋体", Font.PLAIN, 12);pieChart.getTitle().setFont(font);pieChart.getLegend().setItemFont(font);PiePlot plot = (PiePlot) pieChart.getPlot();plot.setLabelFont(font);// 添加饼图到面板并显示ChartPanel chartPanel = new ChartPanel(pieChart);setContentPane(chartPanel);}public static void main(String[] args) {PieChartExample pieChartExample = new PieChartExample();pieChartExample.setSize(600, 600);pieChartExample.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);pieChartExample.setVisible(true);}
}

结果如下
在这里插入图片描述
本篇文章到这里结束 需要注意的是每个人的环境不用调用的API会有所差异。

相关文章:

【Hadoop综合实践】手机卖场大数据综合项目分析

&#x1f680; 本文章实现了基于MapReduce的手机浏览日志分析 &#x1f680; 文章简介&#xff1a;主要包含了数据生成部分&#xff0c;数据处理部分&#xff0c;数据存储部分与数据可视化部分 &#x1f680; 【本文仅供参考&#xff01;&#xff01;非唯一答案】其中需求实现的…...

服务器技术(三)--Nginx

Nginx介绍 Nginx是什么、适用场景 Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力确实在同类型的网页服务器中表现较好。 Nginx专为性能优化而开发&#xff0c;性能是其最重要的考量&#xf…...

OpenCV——总结《车牌识别》之《常用的函数介绍》

1. cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))element cv2.getStructuringElement(shape, ksize[, anchor])用于创建形态学操作的结构元素&#xff08;structuring element&#xff09;。 参数解释&#xff1a; shape&#xff1a;结构元素的形状&#xff0c;可以…...

chatgpt赋能python:如何利用Python进行自动化办公

如何利用Python进行自动化办公 在现代办公环境中&#xff0c;自动化成为了一种趋势。利用计算机程序自动处理重复性劳动&#xff0c;可以提高生产效率和工作质量&#xff0c;同时也能够让工作更加轻松。Python作为一种常用的编程语言&#xff0c;在自动化办公中发挥了重要作用…...

linux-2.6.22.6内核网卡驱动框架分析

网络协议分为很多层&#xff0c;而驱动这层对应于实际的物理网卡部分&#xff0c;这也是最底层的部分&#xff0c;以cs89x0.c这个驱动程序为例来分析下网卡驱动程序框架。 正常开发一个驱动程序时&#xff0c;一般都遵循以下几个步骤&#xff1a; 1.分配某个结构体 2.设置该结…...

机器学习7:特征工程

在传统的软件工程中&#xff0c;核心是代码&#xff0c;然而&#xff0c;在机器学习项目中&#xff0c;重点则是特征——也就是说&#xff0c;开发人员优化模型的方法之一是增加和改进其输入特征。很多时候&#xff0c;优化特征比优化模型带来的增益要大得多。 笔者曾经参与过一…...

coverage代码覆盖率测试介绍

coverage代码覆盖率测试介绍 背景知识补充 1、什么是覆盖率 测试过程中提到的覆盖率&#xff0c;指的是已测试的内容&#xff0c;占待测内容的百分比&#xff0c;在一定程度上反应测试的完整程度。 覆盖率有可以根据要衡量的对象细分很多种&#xff0c;比如接口覆盖率、分支…...

使用 Debian、Docker 和 Nginx 部署 Web 应用

前言 本文将介绍基于 Debian 的系统上使用 Docker 和 Nginx 进行 Web 应用部署的过程。着重介绍了 Debian、Docker 和 Nginx 的安装和配置。 第 1 步&#xff1a;更新和升级 Debian 系统 通过 SSH 连接到服务器。更新软件包列表&#xff1a;sudo apt update升级已安装的软件…...

Redis原理 - 内存策略

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis原理 - 内存策略 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-memery-strategy.html Redis 本身是一个典型的 key-value 内存存储数据库&#xff0c;因此所有的 key、value 都保存在之前学习…...

【计算机网络】IP 地址处理函数

目录 1.struct sockaddr_in的结构 2.一般我们写的结构 3.常见的“点分十进制” 到 ” uint32_t 的转化接口 3.1. inet_aton 和 inet_ntoa &#xff08;ipv4&#xff09; 3.2. inet_pton 和 inet_ntop (ipv4 和 ipv6&#xff09; 3.3. inet_addr 和 inet_network 3…...

9i物联网浏览器(cef_114.2.110114.2.100支持H264视频)WinForm-CefSharp114(5735)视频版本体验

更新:2023.6.25 版本:Cef_114.2.110和114.2.100+chromium-114.0.5735.134的32位和64位 说明:支持图片,mp3,mp4(H264)多媒体 测试环境:windows server 2019 测试网址:www.html5test.com 1.包下载地址 1.1 https://www.nuget.org/packages/CefSharp.Common/ 1.2 https…...

如何在本地运行一个已关服但具有客户端的游戏

虽然游戏服务器关闭后&#xff0c;我们通常无法再进行在线游戏&#xff0c;但对于一些已经关服但仍保留客户端的游戏来说&#xff0c;我们仍然可以尝试在本地进行游玩。本文将介绍如何在本地运行一个已关服但具有客户端的游戏的方法。 一、获取游戏客户端 要在本地运行一个已关…...

C语言编程—预处理器

预处理器不是编译器的组成部分&#xff0c;但是它是编译过程中一个单独的步骤。简言之&#xff0c;C 预处理器只不过是一个文本替换工具而已&#xff0c;它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器&#xff08;C Preprocessor&#xff09;简写为 CP…...

使用 Maya Mari 设计 3D 波斯风格道具(p1)

今天瑞云渲染小编给大家带来了Simin Farrokh Ahmadi 分享的Persian Afternoon 项目过程&#xff0c;解释了 Maya 和 Mari 中的建模、纹理和照明过程。 介绍 我的名字是西敏-法罗赫-艾哈迈迪&#xff0c;人们都叫我辛巴 在我十几岁的时候&#xff0c;我就意识到我喜欢艺术和创造…...

Redis分布式问题

Redis实现分布式锁 Redis为单进程单线程模式&#xff0c;采用队列模式将并发访问变成串行访问&#xff0c;且多客户端对Redis的连接并不存在竞争关系Redis中可以使用SETNX命令实现分布式锁。当且仅当 key 不存在&#xff0c;将 key 的值设为 value。 若给定的 key 已经存在&…...

synchronized原理

目录 一、基本特点 二、加锁过程 2.1、偏向锁 2.2、轻量级锁 2.3、重量级锁 三、其它的优化操作 3.1、锁消除 3.2、锁粗化 一、基本特点 synchronized有以下特性: 开始是乐观锁&#xff0c;如果锁冲突频繁&#xff0c;就转换为悲观锁。开始是轻量级锁&#xff0c…...

10G光模块能兼容千兆光口吗

当涉及到光网络设备和光模块的兼容性时&#xff0c;确保正确的匹配是至关重要的。本期文章内容&#xff0c;我们将探讨10G光模块与千兆光口之间的兼容性。 一、10G光模块和千兆光口的基本概念 首先&#xff0c;我们需要了解10G光模块和千兆光口的基本概念。10G光模块是一种用…...

css 显示省略号 和 动态显示省略号

省略是非常常见的功能。 简单的实现省略号 下面的代码就可以实现省略号&#xff0c;超过宽度的时候就会出现省略号 .text-name{//宽高是一定要设置的不然是会无效延伸的width: 200rpx;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}稍微复杂点的情况&#…...

LeetCode 1253. 重构 2 行二进制矩阵

【LetMeFly】1253.重构 2 行二进制矩阵 力扣题目链接&#xff1a;https://leetcode.cn/problems/reconstruct-a-2-row-binary-matrix/ 给你一个 2 行 n 列的二进制数组&#xff1a; 矩阵是一个二进制矩阵&#xff0c;这意味着矩阵中的每个元素不是 0 就是 1。第 0 行的元素之…...

【八股】【C++】内存

这里写目录标题 内存空间分配new和delete原理C有几种newmalloc / free 与 new / delete区别malloc和free原理&#xff1f;delete和delete[]区别&#xff1f;C内存泄漏malloc申请的存储空间能用delete释放吗?malloc、calloc函数、realloc函数C中浅拷贝与深拷贝栈和队列的区别C里…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...