网络爬虫:爬取假数据

网络爬虫:爬取假数据


文章目录

  • 网络爬虫:爬取假数据
  • 前言
  • 一、项目介绍:
  • 二、项目来源:
  • 三、架构图:(流程图)
  • 四、使用了什么技术:(知识点)
  • 五、结果示意图:
  • 六、具体代码与分析:
    • 1.在web网页获取数据(全部数据打包为字符串)
      • (1)记录网址
      • (2)使用crawler方法根据网址获取web网页上的数据(未处理)
      • 这是我们从web网页上爬取的“乱数据”
    • 2.初步获取姓氏,名字(根据正则表达式)获取3个集合
    • (1)通过正则表达式处理“从网页爬取的乱数据”并放到集合当中
    • (2)将姓氏、名字彻底拆开来,再放到集合当中
      • 在网页上“姓氏”,“男生名字”,“女生名字”的样式分别为:
        • 姓氏:
        • 男生名字:
          • 女生名字:
    • (1)通过正则表达式处理“从网页爬取的乱数据”并放到集合当中:
      • 效果图:
    • (2)将姓氏、名字彻底拆开来,再放到集合当中:
    • 3.生成指定数量的男生和女生(姓名-性别-年龄)
  • 七、总结:需要注意的地方 && 改进之处:
    • (1)我们可以将这个“随机生成的男生,女生”保存到本地:(IO)
    • (2)如果网址失效了 或 网页内容改变了,上面的正则表达式就失效了,须要我们自己去编写regex。
  • 八、个人思考:
  • 九、补充:使用hutool包(稀里糊涂地就写完了代码)
    • 拷贝jar包,直接使用就好了
    • 使用hutool的好处:我们不用自己写:crawler 和 getData方法
  • 十、附录:完整代码


前言

学习java过程中,值得回忆的代码。
在这里插入图片描述


提示:以下是本篇文章正文内容:


一、项目介绍:


爬取web页面上的百家姓和男生,女生的名字,然后组合成一个完整的姓名。

你可以指定须要的 boyCount 和 girlCount,然后会返回一个集合(顺序是打乱的,集合元素是一个类似于“傅彬远-男-19”的字符串)



二、项目来源:


黑马阿伟java系列课程:😊链接在这里😊


三、架构图:(流程图)

在这里插入图片描述

四、使用了什么技术:(知识点)

1.URL对象,爬取网页上的内容
2.书写正则表达式,根据正则表达式爬取内容
3.处理,拼接字符串的方法
4.Collections.shuffle();// 打乱元素的方法
5.将数据保存到本地(IO流)

五、结果示意图:


在这里插入图片描述



六、具体代码与分析:

1.在web网页获取数据(全部数据打包为字符串)

(1)记录网址

(2)使用crawler方法根据网址获取web网页上的数据(未处理)


//1.定义变量记录网址:百家姓,男生名,女生名
String familyNameNet = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee
693fdb1137ee1b0d&from=kg0";
String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";
String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";//2.从"网址"中爬取数据(webCrawler方法)
//注意:要去确保自己可以上网,连接了WiFi
String familyNameStr = webCrawler(familyNameNet);
String boyNameStr = webCrawler(boyNameNet);
String girlNameStr = webCrawler(girlNameNet);

// webCrawler方法:从网页爬取数据
private static String webCrawler(String net) throws IOException {StringBuilder sb = new StringBuilder();URL url = new URL(net);// 注意1:根据参数创建一个url对象// 返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。URLConnection conn = url.openConnection();// 返回从此打开的连接读取的输入流。// conn.getInputStream()返回一个字节流,InputStreamReader是转换流,字节流转为字符流,InputStreamReader isr = new InputStreamReader(conn.getInputStream());int ch;//注意:为什么是int ch ?而不是char ch?while ((ch = isr.read()) != -1) {// 每次读取一个字符,直到读完为止sb.append((char) ch);// 拼接}isr.close();return sb.toString();// 返回
}


这是我们从web网页上爬取的“乱数据”

在这里插入图片描述



2.初步获取姓氏,名字(根据正则表达式)获取3个集合

(1)通过正则表达式处理“从网页爬取的乱数据”并放到集合当中

(2)将姓氏、名字彻底拆开来,再放到集合当中


在网页上“姓氏”,“男生名字”,“女生名字”的样式分别为:

姓氏:

在这里插入图片描述


男生名字:

在这里插入图片描述


女生名字:

在这里插入图片描述



(1)通过正则表达式处理“从网页爬取的乱数据”并放到集合当中:



在这里插入图片描述



//3.通过正则表达式,筛选数据1(getData方法)
ArrayList<String> familyNameTempList = getData(familyNameStr, "(.{4})(,|。)", 1);
ArrayList<String> boyNameTempList = getData(boyNameStr, "([\\u4E00-\\u9FA5]{2})(、|。)", 1);
ArrayList<String> girlNameTempList = getData(girlNameStr, "(.. ){4}..", 0);

//方法2:getData:去除前端代码,返回初次筛选数据的集合:
//参数:完整字符串,正则表达,分组号
private static ArrayList<String> getData(String str, String regex, int index) {ArrayList<String> list = new ArrayList<>();// 注意1:按照正则表达式规则,从字符串中,取获取数据// 1.编译规则---2.创建匹配器,绑定文本---3.寻找符合要求的数据---4.返回数据// 将给定的正则表达式编译到模式中。Pattern pattern = Pattern.compile(regex);// 创建匹配给定输入与此模式的匹配器。Matcher matcher = pattern.matcher(str);// 尝试查找与该模式匹配的输入序列的下一个子序列。while (matcher.find()) {// 返回由以前匹配操作所匹配的输入子序列。------注意2:有分组list.add(matcher.group(index));}return list;}

效果图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述



(2)将姓氏、名字彻底拆开来,再放到集合当中:

在这里插入图片描述



// 4.进一步处理数据:
// familyNameList (姓氏)
// 处理方案:将每一个姓氏拆开,并添加到一个新的集合当中
ArrayList<String> familyNameList = new ArrayList<>();
for (String familyNames : familyNameTempList) {for (int i = 0; i < familyNames.length(); i++) {//注意:为了统一,我们最好都用字符串表示姓氏(虽然这里的形式都是单个字符)familyNameList.add(familyNames.charAt(i) + "");}
}// boyNameList(男名)
// 处理方案:去除其中的重复元素
// 法1:用hashset去重-------法2:list集合,元素不重复,才添加到集合当中。
// 这里使用第2种
ArrayList<String> boyNameList = new ArrayList<>();
for (String boyName : boyNameTempList) {if (!boyNameList.contains(boyName)) {boyNameList.add(boyName);}
}// girlNameList(女名)
// 处理方案:用split将空格切割,得到每一个女生的名字,添加的集合当中
ArrayList<String> girlNameList = new ArrayList<>();
for (String girlNames : girlNameTempList) {// 注意:split方法:根据给定正则表达式的匹配拆分此字符串。返回值是“数组”String[] girlNames2 = girlNames.split(" ");for (int i = 0; i < girlNames2.length; i++) {girlNameList.add(girlNames2[i]);}
}

3.生成指定数量的男生和女生(姓名-性别-年龄)


// 生成想要数据集合(getInfos方法)--注意:要指定集合中男生,女生的个数
ArrayList<String> list = getInfos(familyNameList, boyNameList, girlNameList
, 70, 50);
// 打乱
Collections.shuffle(list);

// 方法3:getInfos:根据“姓氏”,“男名”,“女名”集合,返回一个集合
// 参数:3个集合,boyCount,girlCount
private static ArrayList<String> getInfos(ArrayList<String> familyNameList,ArrayList<String> boyNameList, ArrayList<String> girlNameList, int boyCount, int girlCount) {ArrayList<String> list = new ArrayList<>();Random r = new Random();// 随机生成年龄// 获取男生名字集合:(hashset:防止出现重复的名字)HashSet<String> boys = new HashSet<>();while (true) {if (boys.size() == boyCount) break;Collections.shuffle(familyNameList);Collections.shuffle(boyNameList);boys.add(familyNameList.get(0) + boyNameList.get(0));}// 获取女生名字集合:HashSet<String> girls = new HashSet<>();while (true) {if (girls.size() == girlCount) break;Collections.shuffle(familyNameList);Collections.shuffle(girlNameList);girls.add(familyNameList.get(0) + girlNameList.get(0));}// 拼接男生信息:for (String boy : boys) {int age = r.nextInt(10) + 18;//18~27list.add(boy + "-男-" + age);}// 拼接女生信息:for (String girl : girls) {int age = r.nextInt(8) + 18;//18~25list.add(girl + "-女-" + age);}// 返回最后的集合:return list;
}


七、总结:需要注意的地方 && 改进之处:

(1)我们可以将这个“随机生成的男生,女生”保存到本地:(IO)


BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest1\\names.txt"));for(String str : list) {bw.write(str);bw.newLine();}bw.close();

(2)如果网址失效了 或 网页内容改变了,上面的正则表达式就失效了,须要我们自己去编写regex。


八、个人思考:

1.通过一整个流程下来,我须要熟悉如何分析一个项目,有哪些步骤
2.这只是一个很简单的“爬虫引用”,是用java实现的,那么向python实现的爬虫又是什么样的呢?
可以通过之后的学习,进一步了解到“爬虫”有关的进阶知识。



九、补充:使用hutool包(稀里糊涂地就写完了代码)

拷贝jar包,直接使用就好了

😊hutool网址😊

使用hutool的好处:我们不用自己写:crawler 和 getData方法


在这里插入图片描述



// 原本的代码:
//2.爬取数据,把网址上所有的数据拼接成一个字符串
String familyNameStr = webCrawler(familyNameNet);
String boyNameStr = webCrawler(boyNameNet);
String girlNameStr = webCrawler(girlNameNet);//3.通过正则表达式,把其中符合要求的数据获取出来
ArrayList<String> familyNameTempList = getData(familyNameStr, "(.{4})(,|。)", 1);
ArrayList<String> boyNameTempList = getData(boyNameStr, "([\\u4E00-\\u9FA5]{2})(、|。)", 1);
ArrayList<String> girlNameTempList = getData(girlNameStr, "(.. ){4}..", 0);

// 使用hutool后的代码:
String familyNameStr = HttpUtil.get(familyNameNet);
String boyNameStr = HttpUtil.get(boyNameNet);
String girlNameStr = HttpUtil.get(girlNameNet);List<String> familyNameTempList = ReUtil.findAll("(.{4})(,|。)", familyNameStr, 1);
List<String> boyNameTempList = ReUtil.findAll("([\\u4E00-\\u9FA5]{notes})(、|。)", boyNameStr, 1);
List<String> girlNameTempList = ReUtil.findAll("(.. ){4}..", girlNameStr, 0);

十、附录:完整代码

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Test1 {public static void main(String[] args) throws IOException {/*制造假数据:获取姓氏:https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0获取男生名字:http://www.haoming8.cn/baobao/10881.html获取女生名字:http://www.haoming8.cn/baobao/7641.html*///1.定义变量记录网址String familyNameNet = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";//2.爬取数据,把网址上所有的数据拼接成一个字符串// 这个时候的数据是“杂乱”的String familyNameStr = webCrawler(familyNameNet);String boyNameStr = webCrawler(boyNameNet);String girlNameStr = webCrawler(girlNameNet);//3.通过正则表达式,把其中符合要求的数据获取出来// 这个时候数据经过了处理ArrayList<String> familyNameTempList = getData(familyNameStr, "(.{4})(,|。)", 1);ArrayList<String> boyNameTempList = getData(boyNameStr, "([\\u4E00-\\u9FA5]{2})(、|。)", 1);ArrayList<String> girlNameTempList = getData(girlNameStr, "(.. ){4}..", 0);//4.处理数据//familyNameTempList(姓氏)//处理方案:把每一个姓氏拆开并添加到一个新的集合当中ArrayList<String> familyNameList = new ArrayList<>();for (String str : familyNameTempList) {//str 赵钱孙李  周吴郑王   冯陈褚卫   蒋沈韩杨for (int i = 0; i < str.length(); i++) {char c = str.charAt(i);familyNameList.add(c + "");}}//boyNameTempList(男生的名字)//处理方案:去除其中的重复元素ArrayList<String> boyNameList = new ArrayList<>();for (String str : boyNameTempList) {if (!boyNameList.contains(str)) {boyNameList.add(str);}}//girlNameTempList(女生的名字)//处理方案:把里面的每一个元素用空格进行切割,得到每一个女生的名字ArrayList<String> girlNameList = new ArrayList<>();for (String str : girlNameTempList) {String[] arr = str.split(" ");for (int i = 0; i < arr.length; i++) {girlNameList.add(arr[i]);}}//5.生成数据//姓名(唯一)-性别-年龄ArrayList<String> list = getInfos(familyNameList, boyNameList, girlNameList, 70, 50);Collections.shuffle(list);//System.out.println(list);//
//        //6.写出数据
//        BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\names.txt"));
//        for (String str : list) {
//            bw.write(str);
//            bw.newLine();
//        }
//        bw.close();}/** 作用:*      获取男生和女生的信息:张三-男-23** 形参:*      参数一:装着姓氏的集合*      参数二:装着男生名字的集合*      参数三:装着女生名字的集合*      参数四:男生的个数*      参数五:女生的个数* */public static ArrayList<String> getInfos(ArrayList<String> familyNameList, ArrayList<String> boyNameList, ArrayList<String> girlNameList, int boyCount, int girlCount) {//1.生成男生不重复的名字HashSet<String> boyhs = new HashSet<>();while (true) {if (boyhs.size() == boyCount) {break;}//随机Collections.shuffle(familyNameList);Collections.shuffle(boyNameList);boyhs.add(familyNameList.get(0) + boyNameList.get(0));}//2.生成女生不重复的名字HashSet<String> girlhs = new HashSet<>();while (true) {if (girlhs.size() == girlCount) {break;}//随机Collections.shuffle(familyNameList);Collections.shuffle(girlNameList);girlhs.add(familyNameList.get(0) + girlNameList.get(0));}//3.生成男生的信息并添加到集合当中ArrayList<String> list = new ArrayList<>();Random r = new Random();//【18 ~ 27】for (String boyName : boyhs) {//boyName依次表示每一个男生的名字int age = r.nextInt(10) + 18;list.add(boyName + "-男-" + age);}//4.生成女生的信息并添加到集合当中//【18 ~ 25】for (String girlName : girlhs) {//girlName依次表示每一个女生的名字int age = r.nextInt(8) + 18;list.add(girlName + "-女-" + age);}return list;}/** 作用:根据正则表达式获取字符串中的数据* 参数一:*       完整的字符串* 参数二:*       正则表达式* 参数三:*      获取数据*       0:获取符合正则表达式所有的内容*       1:获取正则表达式中第一组数据*       2:获取正则表达式中第二组数据*       ...以此类推** 返回值:*       真正想要的数据** */private static ArrayList<String> getData(String str, String regex, int index) {//1.创建集合存放数据ArrayList<String> list = new ArrayList<>();//2.按照正则表达式的规则,去获取数据Pattern pattern = Pattern.compile(regex);//按照pattern的规则,到str当中获取数据Matcher matcher = pattern.matcher(str);while (matcher.find()) {list.add(matcher.group(index));}return list;}/*(从web上爬取数据)(粗糙)(未处理)作用:从web页面上爬取数据,把数据拼接成字符串返回形参:网址net(string类型)返回:所有数据组成的字符串*/public static String webCrawler(String net) throws IOException {//1.定义StringBuilder拼接爬取到的数据StringBuilder sb = new StringBuilder();//2.创建一个URL对象URL url = new URL(net);//3.链接上这个网址//细节:保证网络是畅通的,而且这个网址是可以链接上的。URLConnection conn = url.openConnection();//4.读取数据InputStreamReader isr = new InputStreamReader(conn.getInputStream());int ch;while ((ch = isr.read()) != -1) {sb.append((char) ch);}//5.释放资源isr.close();//6.把读取到的数据返回return sb.toString();}
}

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

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

相关文章

Qt使用opencv,进行视频录制,功能打开、关闭摄像头,开始、结束录制视频,暂停、继续录制,并保存视频文件

1.效果图 2 代码实现 2.1 .h文件 #ifndef VIDEORECORDWIDGET_H #define VIDEORECORDWIDGET_H#include <QWidget>#include<QFileDialog>#include <QImage> #include <QLabel> #include <QTimer> #include <opencv2/opencv.hpp>using name…

Linux实验过程

答案截图获取&#xff0c;代写&#xff1a; https://laowangall.oss-cn-beijing.aliyuncs.com/studentall.pdf 基本任务&#xff1a; 1.Linux操作系统安装 2.vi文本编辑 3. Linux用户及文件管理命令 4. Linux权限管理命令 5. Linux网络服务 提高任务&#xff1a; 1、Li…

DIY蓝牙键盘(1) - 理解 键盘报文(免费)

DIY蓝牙键盘(1) - 理解键盘报文 1. 键盘报文体验 一个键盘对于用户的体验是&#xff0c;用户按按键A他能看到字母A会在主机上显示出来。那这是如何实现的&#xff1f; 其实很简单&#xff0c;只要键盘发送下面的两个报文给主机&#xff0c;字母A就能在主机上显示出来。 (1)…

数据结构——图的应用(最小生成树,最短路径,拓扑排序,关键路径)

目录 1.最小生成树 1.概念回顾——生成树 2.最小生成树概念 2.构造最小生成树 1.MST性质 2.Prim算法 3.Kruskal 算法 4.两种算法比较 3.最短路径 1.两点间最短路径 2.某源点到其它各点最短路径 3.单源最短路径——用Dijkstra算法 4.所有顶点间的最短路径…

Flask Python:模糊查询filter和filter_by,数据库多条件查询

数据库&#xff08;sqlalchemy&#xff09;多条件查询 前言一、filter、filter_by实现过滤查询1、filter_by()基础查询并且查询&#xff08;多条件查询&#xff09; 2、filter()like&#xff1a;模糊查询and&#xff1a;并且查询or&#xff1a;或者查询 二、all(),first(),get(…

【一站式学会Kotlin】第一节 kotlin 介绍

作者介绍&#xff1a; 百度资深Android工程师T6&#xff0c;在百度任职7年半。 目前&#xff1a;成立赵小灰代码工作室&#xff0c;欢迎大家找我开发Android、微信小程序、鸿蒙项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默。给大家…

中文Mistral模型介绍(Chinese-Mistral)——中文大语言模型

中文Mistral简介 Chinese-Mistral由清华大学地学系地球空间信息科学实验室开发。 该模型基于Mistral发布的Mistral-7B-v0.1训练得到。首先进行中文词表扩充&#xff0c;然后采用实验室提出的PREPARED训练框架&#xff08;under review&#xff09;在中英双语语料上进行增量预训…

RUST语言基本数据类型认识

1.RUST的基本数据类型参考: 2.使用RUST数据类型声明变量并赋值: let a:i81;//8位有符号整数let a1:u82;//8位无符号整数let b:i161;//16位有符号整数let b1:u162;//16位无符号整数let c:i321;//32位有符号整数let c1:u322;//32位无符号整数let d:i641;//64位有符号整数let d1:u…

C#编写MQTT客户端软件

主要参考C#MQTT编程06--MQTT服务器和客户端(winform版)_c#mqttserver-CSDN博客 但由于使用的.NET版本和MQTT库版本存在差异&#xff0c;因此有些不同。 MQTT协议内容在此不做描述&#xff0c;仅介绍VS使用C#的实现过程。本次使用VS2015&#xff0c;.netframwork4.6。 C#语言本身…

SQL server 查询数据库中所有的表名及行数

SQL server 查询数据库中所有的表名及行数 select a.name,b.rows from sysobjects as ainner join sysindexes as bon a.id b.id where (a.type u)and (b.indid in (0, 1)) and b.rows<50 and b.rows>20 order by a.name, b.rows desc;

Express框架搭建项目 node.js

文章目录 引言Express框架介绍express安装环境准备写一个简单的项目展示 文章总结 引言 Express是一个基于Node.js平台的轻量级Web应用框架&#xff0c;它提供了简洁的API和丰富的功能&#xff0c;使得开发者能够快速地构建Web服务器和API。本文将带领大家从零开始&#xff0c…

GDAL源码剖析(六)之GDAL开发及其调试

GDAL源码剖析&#xff08;六&#xff09;之GDAL开发及其调试-CSDN博客 一、简单的调用 关于GDAL的使用&#xff0c;网上的资料都很多&#xff0c;主要还是要熟悉GDAL的组织结构&#xff0c;类以及类的函数等&#xff0c;熟悉了&#xff0c;使用GDAL就不在话下了。最常用的就是…

苹果手表Apple Watch录了两个半小时的录音,却只能播放4秒,同步到手机也一样,还能修复好吗?

好多人遇到这个情况&#xff0c;用苹果手表Apple Watch录音&#xff0c;有的录1个多小时&#xff0c;有的录了3、4小时&#xff0c;甚至更长时间&#xff0c;因为手表没电&#xff0c;忘记保存等原因造成录音损坏&#xff0c;都是只能播放4秒&#xff0c;同步到手机也一样&…

JavaScript基础代码练习之冒泡排序

一、要求对一个数组进行冒泡排序&#xff0c;并将排序后的结果输出到控制台。在代码中&#xff0c;数组 arr 包含了一组数字&#xff0c;然后使用嵌套的循环来进行冒泡排序。 二、编写代码 <!DOCTYPE html> <html lang"en"><head><meta chars…

软件测试用例(2)

具体的设计方法 -- 黑盒测试 因果图 因果图是一种简化的逻辑图, 能直观地表明程序的输入条件(原因)和输出动作(结果)之间的相互关系. 因果图法是借助图形来设计测试用例的一种系统方法, 特别适用于被测试程序具有多种输入条件, 程序的输出又依赖于输入条件的各种情况. 因果图…

深挖苹果Find My技术,伦茨科技ST17H6x芯片赋予产品功能

苹果发布AirTag发布以来&#xff0c;大家都更加注重物品的防丢&#xff0c;苹果的 Find My 就可以查找 iPhone、Mac、AirPods、Apple Watch&#xff0c;如今的Find My已经不单单可以查找苹果的设备&#xff0c;随着第三方设备的加入&#xff0c;将丰富Find My Network的版图。产…

fastadmin学习08-查询数据渲染到前端

index.php查询&#xff0c;这个是前台的index.php public function index() {$slideImgs Db::name("slideimg")->where("status",,normal)->limit(5)->order(sort,desc)->select();$productList Db::name("product")->where(…

python的垃圾回收

引用计数器为主&#xff0c;标记清除和分代回收为辅 1 引用计数器 在python程序运行时&#xff0c;会根据数据类型的不同找到其对应的结构体&#xff0c;根据结构体中的字段来进行创建相关的数据&#xff0c;然后将对象添加到refchain双像链表中&#xff0c;每个对象中的ob_re…

Java中生成JWT令牌

1. 在pom.xml中引入依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version> </dependency> 2. 使用Jwts的相关方法生成令牌 import io.jsonwebtoken.Jwts; import io.…

【单片机家电产品学习记录--蜂鸣器】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 单片机家电产品–蜂鸣器 前言 记录学习单片机家电产品内容 已转载记录为主 一、知识点 1电子电路学习笔记&#xff08;17&#xff09;——蜂鸣器 蜂鸣器种类和原理 2疑…