虫洞数观系列一 | 豆瓣电影TOP250数据采集与MySQL存储实战
目录
系列文章
1. 引言
2 技术栈Request
2.1请求头headers
2.2查找定位信息
2.3处理网页html结构化数据
2.4每页url规律
2.5逐条查找所需信息
2.6完整代码
3 数据存储至mysql
3.1新建数据库
3.2编写数据库写入py文件
3.2.1构建1个执行sql语句的函数
3.2.2构造一个将dataframe转成sql语句的函数
3.2.3完整代码
4 总结
系列文章
虫洞数观系列总览 | 技术全景:豆瓣电影TOP250数据采集→分析→可视化完整指南
1. 引言
豆瓣电影TOP250以其清晰的页面结构、规律的数据排列(如电影名称、评分、导演等信息的固定标签和类名),成为爬虫练习的理想目标。虽然存在请求频率限制、IP检测等反爬机制,但相比淘宝、微博等大型网站,其反爬措施较为宽松。本文将基于Requests和Selenium两种技术栈,演示如何高效爬取该榜单数据。
网址链接豆瓣电影 Top 250
2 技术栈Request
2.1请求头headers
headers
是 HTTP 请求中的一部分,用于向服务器传递客户端(如浏览器)的相关信息。服务器会根据这些信息来判断请求的来源、客户端类型以及如何处理请求。主要作用是绕过反爬虫机制,通过模拟浏览器行为,避免被服务器识别为爬虫。
在网站中如何查找自己的请求头
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
请求头解读:
-
Mozilla/5.0
:这是一个通用的标识符,表示客户端兼容 Mozilla 浏览器(现代浏览器通常都会包含这个字段)。 -
Windows NT 10.0; Win64; x64
:表示客户端的操作系统信息。-
Windows NT 10.0
:操作系统是 Windows 10。 -
Win64
和x64
:表示系统是 64 位架构。
-
-
AppleWebKit/537.36
:表示客户端使用的渲染引擎是 AppleWebKit(Chrome 和 Safari 都基于此引擎)。 -
KHTML, like Gecko
:表示客户端兼容 KHTML 和 Gecko 渲染引擎(Gecko 是 Firefox 的渲染引擎)。 -
Chrome/134.0.0.0
:表示客户端使用的是 Chrome 浏览器,版本号为 134.0.0.0。 -
Safari/537.36
:表示客户端兼容 Safari 浏览器,版本号为 537.36。
2.2查找定位信息
很多人可能一开始不理解xpath,尤其看到网页信息,如"/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]"就感觉头大,不重要!!!,重在理解大致含义,看久啦就习惯啦,慢慢就理解啦,以下是告诉你怎么查看xpath
2.3处理网页html结构化数据
在使用 requests
请求网页后,返回的数据通常是 HTML 格式的结构化文本。HTML 文档由标签、属性和内容组成,具有清晰的层次结构。以下是一个简单的 HTML 示例,展示了其典型的结构:
<div class="info"><div class="hd"><a href="https://movie.douban.com/subject/1292052/"><span class="title">肖申克的救赎</span></a></div>
</div>
在处理网页数据时,虽然可以直接对 requests.text
(即原始的 HTML 字符串)进行操作,但这种方式会面临极大的工作量。HTML 文档通常包含复杂的标签嵌套和属性结构,手动解析字符串不仅繁琐,还容易出错。为了高效、准确地提取目标数据,引入 etree
,将 HTML 字符串解析为树形结构(ElementTree)。这种结构化解析方式不仅简化了数据提取过程,还支持强大的 XPath 和 CSS 选择器,极大地提升了开发效率。
以下是一个简单的示例,展示如何使用 etree
解析 HTML 并提取数据:
from lxml import etreetree = etree.HTML(html)
# 使用 XPath 提取电影名称
titles = tree.xpath('//div[@class="info"]/div[@class="hd"]/a/span[@class="title"]/text()')
print(titles) # 输出:['肖申克的救赎']
2.4每页url规律
# 第1页
'https://movie.douban.com/top250?start=0&filter='# 第2页
'https://movie.douban.com/top250?start=25&filter='# 第3页
'https://movie.douban.com/top250?start=50&filter='# 第4页
'https://movie.douban.com/top250?start=75&filter='# 第5页
'https://movie.douban.com/top250?start=100&filter='# 尾页
'https://movie.douban.com/top250?start=225&filter='
可以发现一个规律
for page in range(1, 11):# 目标urlurl = f'https://movie.douban.com/top250?start={(page - 1) * 25}&filter='
2.5逐条查找所需信息
我们需要一层一层定位所需要的信息,如下图
2.6完整代码
# 导入模块
import pandas as pd
import requests
from lxml import etree
import csvdef crawler_douban():# 请求头信息headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'}moive_list = []for page in range(1, 11):# 目标urlurl = f'https://movie.douban.com/top250?start={(page - 1) * 25}&filter='# 发送请求, 获取响应res = requests.get(url, headers=headers)# 打印响应信息# print(res.text)# 网页源码html = res.text# 实例化etree对象tree = etree.HTML(html)divs = tree.xpath('//div[@class="info"]')# print(divs)i = 1for div in divs:dic_temp = {}dic_temp['电影中文名'] = ''dic_temp['电影英文名'] = ''dic_temp['电影详情页链接'] = ''dic_temp['导演'] = ''dic_temp['主演'] = ''dic_temp['上映年份'] = ''dic_temp['国籍'] = ''dic_temp['类型'] = ''dic_temp['评分'] = ''dic_temp['评分人数'] = ''dic_temp['评语'] = ''print('>>>>>>>>>>')print(i)print(div)div_temp = div.xpath('./div[@class="hd"]/a')urlx = div_temp[0].get('href')texts = [a.xpath('string(.)').strip() for a in div_temp]print(texts)need_list1 = []for each_text in texts:each_text_list = each_text.split('\n')for each_one in each_text_list:need_list1.append(each_one.replace(' ', ''))div_temp = div.xpath('./div[@class="bd"]')texts = [a.xpath('string(.)').strip() for a in div_temp]need_list2 = []for each_text in texts:each_text_list = each_text.split('\n')for each_one in each_text_list:need_list2.append(each_one.replace(' ', ''))print(need_list1)print(need_list2)dic_temp['电影中文名'] = need_list1[0]dic_temp['电影英文名'] = need_list1[1].replace('\xa0/\xa0', '')dic_temp['电影详情页链接'] = urlxdic_temp['导演'] = need_list2[0].split('xa0\xa0\xa0')[0]print(need_list2[0])try:dic_temp['导演'] = dic_temp['导演'].replace('导演:', '').replace('\xa0\xa0\xa0', '')dic_temp['导演'] = dic_temp['导演'].split('主演:')[0]except:passtry:dic_temp['主演'] = need_list2[0].split('主演:')[1]except:passdic_temp['上映年份'] = need_list2[1].split('\xa0/\xa0')[0]dic_temp['国籍'] = need_list2[1].split('\xa0/\xa0')[1]dic_temp['类型'] = need_list2[1].split('\xa0/\xa0')[2]dic_temp['评分'] = need_list2[7]dic_temp['评分人数'] = need_list2[9]if need_list2[-1] != need_list2[9]:dic_temp['评语'] = need_list2[-1]if dic_temp != {}:print(dic_temp)moive_list.append(dic_temp)i += 1print(f'----------------------第{page}页爬取完成--------------------------------------')print('-----------------------爬虫结束-------------------------------')df = pd.DataFrame(moive_list)df.to_excel('douban_TOP250_moive.xlsx', index=None)return df# 程序入口
if __name__ == "__main__":df = crawler_douban()print(df)
3 数据存储至mysql
3.1新建数据库
使用Navicat新建数据库时,既可通过可视化界面操作,也能直接编写SQL命令完成。
可视化界面操作
编写SQL命令
CREATE TABLE `top250movie` (`update_date` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新日期',`feature` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '特征值',`movie_ch` varchar(255) DEFAULT NULL COMMENT '电影中文名',`movie_en` varchar(255) DEFAULT NULL COMMENT '电影英文名',`movie_url` varchar(255) DEFAULT NULL COMMENT '电影详情页链接',`director` varchar(255) DEFAULT NULL COMMENT '导演',`star` varchar(255) DEFAULT NULL COMMENT '主演',`start_year` varchar(255) DEFAULT NULL COMMENT '上映年份',`country` varchar(255) DEFAULT NULL COMMENT '国籍',`type` varchar(255) DEFAULT NULL COMMENT '类型',`rating` varchar(255) DEFAULT NULL COMMENT '评分',`num_ratings` varchar(255) DEFAULT NULL COMMENT '评分人数',`comment` varchar(1000) DEFAULT NULL COMMENT '评语',PRIMARY KEY (`feature`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
3.2编写数据库写入py文件
3.2.1构建1个执行sql语句的函数
定义了一个函数 cost_execute_sql_no_return_value(sql)
,用于执行 不返回结果 的 SQL 语句(如 INSERT
、UPDATE
、DELETE
),并处理数据库连接池、事务和错误。
数据库连接池配置
__config = {"host": "localhost", # MySQL 服务器地址"port": 3306, # 端口号"user": "root", # 用户名"password": "dandan1901", # 密码"database": "douban" # 数据库名
}
-
定义了 MySQL 的连接参数,包括主机、端口、用户名、密码和数据库名。
初始化连接池
try:pool = mysql.connector.pooling.MySQLConnectionPool(**__config,pool_size=10 # 连接池大小(最多 10 个连接))
except Exception as e:print(e) # 如果连接池初始化失败,打印错误
-
MySQLConnectionPool
:创建一个 MySQL 连接池,pool_size=10
表示最多维护 10 个连接。 -
异常处理:如果连接池初始化失败(如密码错误、网络问题),捕获异常并打印。
执行 SQL 语句
try:con = pool.get_connection() # 从连接池获取一个连接cursor = con.cursor() # 创建游标cursor.execute(sql) # 执行 SQLcon.commit() # 提交事务print(('Successfully insert ' + sql).encode('gbk', 'ignore').decode('gbk', 'ignore'))
except Exception as e:print(e) # 打印错误信息if "con" in dir(): # 如果连接存在con.rollback() # 回滚事务print(('Failed insert ' + sql).encode('gbk', 'ignore').decode('gbk', 'ignore'))
finally:if "con" in dir(): # 确保连接被关闭con.close()
-
pool.get_connection()
:从连接池获取一个可用连接。 -
cursor.execute(sql)
:执行传入的 SQL 语句。 -
con.commit()
:如果执行成功,提交事务。 -
con.rollback()
:如果执行失败,回滚事务。 -
con.close()
:在finally
中确保连接被关闭(防止资源泄漏)。 -
编码处理:
('Successfully insert ' + sql).encode('gbk', 'ignore').decode('gbk', 'ignore')
这段代码是为了避免中文字符在打印时出现编码错误(gbk
是 Windows 终端常用编码)。
3.2.2构造一个将dataframe转成sql语句的函数
将 DataFrame 中的数据批量插入/更新到 MySQL 数据库的 top250movie
表中
def write_info_into_db(df):for i in range(df.shape[0]):df.loc[i, '特征值'] = 'TOP' + str(i + 1).zfill(4)df['更新日期'] = str(datetime.datetime.now())# 将数据写入数据库insert_cols = {'update_date': '更新日期','feature': '特征值','movie_ch': '电影中文名','movie_en': '电影英文名','movie_url': '电影详情页链接','director': '导演','star': '主演','start_year': '上映年份','country': '国籍','type': '类型','rating': '评分','num_ratings': '评分人数','comment': '评语',}# df_copy = pd.DataFrame(df)db_list = list(insert_cols.keys())print(db_list)for i in range(df.shape[0]):dbname = 'top250movie'sql = "REPLACE INTO " + dbname + " ("for ix in range(len(db_list)):if ix < len(db_list) - 1:sql = sql + str(db_list[ix]) + ', 'else:sql = sql + str(db_list[ix])sql = sql + ") VALUES ("for ix in range(len(db_list)):each_key = db_list[ix]print(df.loc[i, insert_cols[each_key]])if ix < len(db_list) - 1:sql += "'" + str(df.loc[i, insert_cols[each_key]]) + "'" + ","else:sql += "'" + str(df.loc[i, insert_cols[each_key]]) + "'" + ");"print('>>>>>>>>>>')print(sql)cost_execute_sql_no_return_value(sql)
数据处理
for i in range(df.shape[0]):df.loc[i, '特征值'] = 'TOP' + str(i + 1).zfill(4) # 生成形如 "TOP0001" 的特征值
-
为 DataFrame 的每一行添加
特征值
列,格式为TOP0001
、TOP0002
...(zfill(4)
保证 4 位数字)。
df['更新日期'] = str(datetime.datetime.now()) # 添加当前时间戳
-
添加
更新日期
列,值为当前时间(字符串格式)。
数据库字段映射
insert_cols = {'update_date': '更新日期', # 数据库列名: DataFrame 列名'feature': '特征值','movie_ch': '电影中文名','movie_en': '电影英文名','movie_url': '电影详情页链接','director': '导演','star': '主演','start_year': '上映年份','country': '国籍','type': '类型','rating': '评分','num_ratings': '评分人数','comment': '评语',
}
-
定义数据库列名(
key
)和 DataFrame 列名(value
)的映射关系。
db_list = list(insert_cols.keys()) # 获取数据库列名列表
print(db_list) # 打印列名(调试用)
生成并执行 SQL
for i in range(df.shape[0]): # 遍历 DataFrame 每一行dbname = 'top250movie'sql = "REPLACE INTO " + dbname + " ("# 拼接列名部分(如 REPLACE INTO top250movie (update_date, feature, ...))for ix in range(len(db_list)):if ix < len(db_list) - 1:sql += str(db_list[ix]) + ', 'else:sql += str(db_list[ix])sql += ") VALUES ("# 拼接值部分(如 VALUES ('2023-01-01', 'TOP0001', ...))for ix in range(len(db_list)):each_key = db_list[ix]print(df.loc[i, insert_cols[each_key]]) # 打印当前值(调试用)if ix < len(db_list) - 1:sql += "'" + str(df.loc[i, insert_cols[each_key]]) + "', "else:sql += "'" + str(df.loc[i, insert_cols[each_key]]) + "');"print('>>>>>>>>>>')print(sql) # 打印完整 SQL(调试用)cost_execute_sql_no_return_value(sql) # 执行 SQL
-
REPLACE INTO
:如果主键冲突,则删除旧记录并插入新记录(类似INSERT + DELETE
)。 -
动态生成 SQL:根据
db_list
和 DataFrame 的值拼接 SQL 语句。 -
执行 SQL:调用
cost_execute_sql_no_return_value(sql)
(前文定义的函数)执行。
3.2.3完整代码
# 导入模块
import datetimeimport mysql.connector.pooling
import pandas as pd
import requests
from lxml import etreedef cost_execute_sql_no_return_value(sql):__config = {"host": "localhost","port": 3306,"user": "root","password": "faw-vw.1901","database": "douban"}try:pool = mysql.connector.pooling.MySQLConnectionPool(**__config,pool_size=10)except Exception as e:print(e)try:con = pool.get_connection()cursor = con.cursor()cursor.execute(sql)con.commit()print(('Successfully insert ' + sql).encode('gbk', 'ignore').decode('gbk', 'ignore'))except Exception as e:print(e)if "con" in dir():con.rollback()print(('Failed insert ' + sql).encode('gbk', 'ignore').decode('gbk', 'ignore'))finally:if "con" in dir():con.close()def crawler_douban():# 请求头信息headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'}moive_list = []for page in range(1, 11):# 目标urlurl = f'https://movie.douban.com/top250?start={(page - 1) * 25}&filter='# 发送请求, 获取响应res = requests.get(url, headers=headers)# 打印响应信息# print(res.text)# 网页源码html = res.text# 实例化etree对象tree = etree.HTML(html)divs = tree.xpath('//div[@class="info"]')# print(divs)i = 1for div in divs:dic_temp = {}dic_temp['电影中文名'] = ''dic_temp['电影英文名'] = ''dic_temp['电影详情页链接'] = ''dic_temp['导演'] = ''dic_temp['主演'] = ''dic_temp['上映年份'] = ''dic_temp['国籍'] = ''dic_temp['类型'] = ''dic_temp['评分'] = ''dic_temp['评分人数'] = ''dic_temp['评语'] = ''print('>>>>>>>>>>')print(i)print(div)div_temp = div.xpath('./div[@class="hd"]/a')urlx = div_temp[0].get('href')texts = [a.xpath('string(.)').strip() for a in div_temp]print(texts)need_list1 = []for each_text in texts:each_text_list = each_text.split('\n')for each_one in each_text_list:need_list1.append(each_one.replace(' ', ''))div_temp = div.xpath('./div[@class="bd"]')texts = [a.xpath('string(.)').strip() for a in div_temp]need_list2 = []for each_text in texts:each_text_list = each_text.split('\n')for each_one in each_text_list:need_list2.append(each_one.replace(' ', ''))print(need_list1)print(need_list2)dic_temp['电影中文名'] = need_list1[0]dic_temp['电影英文名'] = need_list1[1].replace('\xa0/\xa0', '')dic_temp['电影详情页链接'] = urlxdic_temp['导演'] = need_list2[0].split('xa0\xa0\xa0')[0]print(need_list2[0])try:dic_temp['导演'] = dic_temp['导演'].replace('导演:', '').replace('\xa0\xa0\xa0', '')dic_temp['导演'] = dic_temp['导演'].split('主演:')[0]except:passtry:dic_temp['主演'] = need_list2[0].split('主演:')[1]except:passdic_temp['上映年份'] = need_list2[1].split('\xa0/\xa0')[0]dic_temp['国籍'] = need_list2[1].split('\xa0/\xa0')[1]dic_temp['类型'] = need_list2[1].split('\xa0/\xa0')[2]dic_temp['评分'] = need_list2[7]dic_temp['评分人数'] = need_list2[9]if need_list2[-1] != need_list2[9]:dic_temp['评语'] = need_list2[-1]if dic_temp != {}:print(dic_temp)moive_list.append(dic_temp)i += 1print(f'----------------------第{page}页爬取完成--------------------------------------')print('-----------------------爬虫结束-------------------------------')df = pd.DataFrame(moive_list)df.to_excel('douban_TOP250_moive.xlsx', index=None)return dfdef write_info_into_db(df):for i in range(df.shape[0]):df.loc[i, '特征值'] = 'TOP' + str(i + 1).zfill(4)df['更新日期'] = str(datetime.datetime.now())# 将数据写入数据库insert_cols = {'update_date': '更新日期','feature': '特征值','movie_ch': '电影中文名','movie_en': '电影英文名','movie_url': '电影详情页链接','director': '导演','star': '主演','start_year': '上映年份','country': '国籍','type': '类型','rating': '评分','num_ratings': '评分人数','comment': '评语',}# df_copy = pd.DataFrame(df)db_list = list(insert_cols.keys())print(db_list)for i in range(df.shape[0]):dbname = 'top250movie'sql = "REPLACE INTO " + dbname + " ("for ix in range(len(db_list)):if ix < len(db_list) - 1:sql = sql + str(db_list[ix]) + ', 'else:sql = sql + str(db_list[ix])sql = sql + ") VALUES ("for ix in range(len(db_list)):each_key = db_list[ix]print(df.loc[i, insert_cols[each_key]])if ix < len(db_list) - 1:sql += "'" + str(df.loc[i, insert_cols[each_key]]) + "'" + ","else:sql += "'" + str(df.loc[i, insert_cols[each_key]]) + "'" + ");"print('>>>>>>>>>>')print(sql)cost_execute_sql_no_return_value(sql)# 程序入口
if __name__ == "__main__":# 爬取数据df = crawler_douban()print(df)# 将数据写入数据库write_info_into_db(df)
展示结果如下
4 总结
此处省略1万字,感谢各位看到最后,最后附上代码信息,数据库也在文件中,百度网盘链接如下
通过网盘分享的文件:项目工坊_豆瓣爬虫
链接: https://pan.baidu.com/s/1cY8plsXfVYl8NuhBixVrTQ?pwd=y131 提取码: y131
相关文章:
虫洞数观系列一 | 豆瓣电影TOP250数据采集与MySQL存储实战
目录 系列文章 1. 引言 2 技术栈Request 2.1请求头headers 2.2查找定位信息 2.3处理网页html结构化数据 2.4每页url规律 2.5逐条查找所需信息 2.6完整代码 3 数据存储至mysql 3.1新建数据库 3.2编写数据库写入py文件 3.2.1构建1个执行sql语句的函数 3.2.2构造一个…...
模型 阿米巴模式
系列文章分享模型,了解更多👉 模型_思维模型目录。小团队独立经营,企业活力无限。 1 阿米巴模式的应用 1.1 日航重生(航空业成功案例) 应用领域 航空运输业破产重组与组织激活 案例名称 日本航空(JAL&…...
针对stm32F103C8t6芯片调节USB串口的经验
1、首先这是自己手搓的板子,对于之前一直没有了解过USB这方面,则这个针对USB部分没有设计上拉电阻,造成不管怎么调节PC端都没有反应。 图一 这个没有添加1.5K电阻 这个D+位置应该再接一个1.5KR的电阻如图2所示 图2 这样调节的话PC端就可以识别到USB串口,但是这是串口还是会…...
JVM详解(包括JVM内存模型与GC垃圾回收)
📖前言: 学会使用Java对于一个程序员是远远不够的。Java语法的掌握只是一部分,另一部分就是需要掌握Java内部的工作原理,从编译到运行,到底是谁在帮我们完成工作的? 接下来着重对Java虚拟机,也就…...
解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式
🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操…...
【Linux网络】——Socket网络编程
前言 在当今数字化的时代,网络通信已经成为计算机领域不可或缺的一部分。无论是日常的网页浏览、社交媒体交互,还是大规模的企业级数据传输,都离不开高效可靠的网络通信。而在Linux操作系统中,Socket网络编程是实现各种网络应用的…...
基于javaweb的SpringBoot雪具商城系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
Android 简化图片加载与显示——使用Coil和Kotlin封装高效工具类
为了简化使用Coil加载网络图片和GIF的过程,我们可以封装一个工具类。这个工具类将包括初始化ImageLoader的方法、加载图片到ImageView的方法,以及可能的其他便捷方法,如加载圆形图片、设置占位图等。下面是一个示例: 首先&#x…...
Flink watermark的时间字段有空值,建表的时候,如何处理
在 Flink 中处理时间字段存在空值时,需通过 表定义阶段的特殊处理 和 Watermark 生成策略调整 来避免因空值导致的窗口计算异常或任务失败。以下是具体解决方案及实现方法: 1. 空值处理核心策略 1.1 查询时,过滤空值数据(推荐&am…...
关于matlab和python谁快的问题
关于matlab和python谁快的问题,python比matlab在乘法上快10倍,指数计算快4倍,加减运算持平,略慢于matlab。或许matlab只适合求解特征值。 import torch import timen 50000 # 矩阵规模 M torch.rand(n, 31)start_time time.t…...
【DevOps】DevOps and CI/CD Pipelines
DevOps 是一种将开发与运维实践相结合的模式,旨在缩短软件开发周期并交付高质量软件。 DevOps 是什么? 开发团队与运维团队之间的协作 • 持续集成与持续交付(CI/CD) • 流程自动化 • 基础设施即代码(IaC)…...
ROS--IMU数据包
IMU惯性测量单元 一:IMU二:ROS中三:IMU数据包三:总结 提示:以下是本篇文章正文内容,下面案例可供参考 一:IMU IMU(Inertial Measurement Unit,惯性测量单元)…...
【机器学习】手撕封装PCA——将高维数据映射到低维数据的过程
PCA将高维数据映射到低维数据的过程 一、摘要二、PCA的降维思路三、PCA代码实现降维过程3.1 PCA类的实现与封装3.2 PCA类的使用示例 四、PCA的恢复过程 一、摘要 本文详细介绍了主成分分析法(PCA)在高维数据降维中的应用。首先,阐述了PCA的基…...
LangChain开发(七)自定义输出格式(JSON/XML/YAML)
文章目录 JSON结构输出未使用PydanticPydantic流式处理 XML结构输出xml输出指定字段 YAML输出源码地址参考资料 JSON结构输出 虽然一些模型提供商支持内置的方法返回结构化输出,但并非所有都支持。我们可以使用输出解析器来帮助用户通过指示指定任意的JSON模型&…...
RustDesk部署到linux(自建服务器)
简介 RustDesk是一款开源的远程桌面软件,由中国开发者开发,使用Rust编程语言构建。它支持跨平台运行,可以在Windows、macOS、Linux、iOS、Android和Web等多个平台上使用。RustDesk的主要功能包括远程桌面访问、文件传输、文本聊天等&…...
分布式锁,redisson,redis
目录 什么是分布式锁分布式锁解决什么问题分布式锁的特点使用分布式锁的场景怎么使用分布式锁1. 添加依赖2. 配置 Redisson 客户端3. 使用 Redisson 实现分布式锁 什么是分布式锁 分布式锁是一种锁机制,用于在分布式环境下,解决多个线程并发访问同一共享…...
linux常用指令(9)
加油同志们,我们离胜利不远了,再有两天我们就可以了解完linux的一些基本常用指令了,到时我们便可以进入一些shell脚本语法了,那么话不多说,来看. 1.more指令 功能描述:more指令是一个基于vi编辑器的文本过滤器,它以全屏幕的方式按页显示文本文件的内容. 基本语法…...
深入解析 JVM 内存区域及核心概念
深入解析 JVM 内存区域及核心概念 Java 虚拟机(JVM)内部划分了多个内存区域,每个区域存储不同类型的数据并承担不同的职责。本文将详细介绍以下内容: 程序计数器:记录当前线程正在执行的字节码指令及其“行号”信息&a…...
字节跳动春招研发部笔试题解
字节跳动春招研发部笔试题 1.万万没想到之聪明的编辑 我叫王大锤,是一家出版社的编辑。我负责校对投稿来的英文稿件,这份工作非常烦人,因为每天都要去修正无数的拼写错误。但是,优秀的人总能在平凡的工作中发现真理。我发现一个发…...
java对象模型
java对象自身的存储模型JVM会给这个类创建一个instanceKlass,保存在方法区,用来在JVM层表示该Java类。 a类。当我们在Java代码中,使用new创建一个对象的时候,JVM会在栈中给对象赋值,会在堆中创建一个instanceOopDesc对…...
深入理解指针(3)(C语言版)
文章目录 前言 一、字符指针变量二、数组指针变量2.1 数组指针变量是什么2.2 数组指针变量怎么初始化2.2.1 静态初始化2.2.2 动态初始化 三、二维数组传参的本质四、函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 typedef关键字4.4拓展 五、函数指针数组六、转…...
Linux内核 内存管理 物理内存初始化流程
1.ARM64页表初始化流程图 start_kernel()│▼ setup_arch() // 架构相关初始化│▼ early_fixmap_init() // 初始化Fixmap(临时映射设备树等)│▼ arm64_memblock_init() // 从设备树解析内存布局│▼ arm…...
Day23:和为s的数字
购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。 示例 1: 输入:price [3, 9, 12, 15], target 18 输出:[3,15] 或者 [15,3]示例 2&#x…...
Transformer 通关秘籍2:利用 BERT 将文本 token 化
前面两节分别通过两个代码示例展示了模型将文本转换为 token 之后是什么样的,希望你可以对此有一个感性的认识。 本节来简要介绍一下将一个连续的文本转换为 token 序列的大致过程,这个过程被称为分词,也叫 tokenization。 在你没了解这方面…...
电脑干货:万能驱动--EasyDrv8
目录 万能驱动EasyDrv8 功能介绍 主程序界面 驱动解压与安装 PE环境支持 系统部署环境 桌面环境一键解决方案 万能驱动8电脑版是由IT天空出品的一款智能识别电脑硬件并自动安装驱动的工具,一般又称为it天空万能驱动,万能驱动vip版,简称…...
18502 字符串哈希匹配字符串
18502 字符串哈希匹配字符串 ⭐️难度:中等 🌟考点:字符串hash 📖 📚 import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int…...
openmmlab介绍 一下
OpenMMLab 是由商汤科技(SenseTime)发起并维护的开源深度学习项目,专注于计算机视觉领域。它提供了一系列模块化、可扩展的工具库,旨在帮助研究者和开发者高效地实现、复现和部署前沿的视觉算法。OpenMMLab 的设计强调模块化、…...
基于javaweb的SpringBoot线上网络文件管理系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
【设计模式】工厂模式详解-----简单工厂模式、工厂方法模式、抽象工厂模式
工厂模式详解 一、概述 工厂模式(Factory Pattern) 是一种 创建型设计模式,用于 封装对象的创建逻辑,避免在代码中直接实例化对象,从而提高代码的 可维护性、扩展性和解耦性。 二、工厂模式分类 工厂模式包括 简单工…...
【雅思播客09】Turn Left here.
Hello everyone! And welcome to my channel! Im Reevs. Good morning! 大家好,欢迎来到懒人英语晨读栏目,我是Reevs,早上好呀。 I have a great lesson for you today. 今天我有一堂非常棒的课。 We have an elementary lesson, which is …...
初阶7 vector
本章重点 vector的介绍vector的使用vector的模拟实现 1.vector的介绍 vector就类似数据结构中的顺序表 vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素。 意味着可以采用下标对vector的元素 进行访问,和数…...
归并排序总结
归并排序是分治法的典型应用,把两个或k个有序的子序列合并为一个。2路归并,2合一。k路归并,k合一。内部排序通常采用2路归并排序,先将数组分成两半,分别排序,然后合并。合并的过程需要将两个有序的子数组合…...
ollama迁移已下载的单个模型到服务器
ollama迁移已下载的单个模型到服务器 场景 ollama是面向用户级的,部署和运行都很简单,是否高效就另说了。但最起码,他能充分利用用户的硬件设备,在GPU不足也能调用cpu和内存去加持。 ollama运行的模型基本是量化版本的…...
基于SSM+Vue物流信息管理系统(附源码)
预览页面 获取方式 https://gitee.com/XiaoLin_Java/communion/blob/master/README.en.md...
docker创建registry镜像仓库2.8版本
目录 shell脚本内容 运行效果 问题与解决 涉及镜像包registry:2.8(x86版本) shell脚本内容 [roottest1 docker]# cat registry.sh #!/bin/bash read -p "请输入用户:" user read -p "请输入密码:" passpathpwd passdir"$…...
Ubuntu下用QEMU模拟运行OpenBMC
1、前言 在调试过程中,安装了很多依赖库,具体没有记录。关于kvm,也没理清具体有什么作用。本文仅记录,用QEMU成功的将OpenBMC跑起来的过程,做备忘,也供大家参考。 2、环境信息 VMware Workstation 15 Pro…...
Unity Shader编程】之复杂光照
在Unity Shader的LightMode标签中,除了前向渲染和延迟渲染外,还支持多种渲染模式设置。以下是主要分类及用途: 一、核心渲染路径模式 前向渲染相关 ForwardBase 用于基础光照计算,处理环境光、主平行光、逐顶点/SH光源及光照贴图。…...
从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.1.3前馈网络(FFN)与激活函数(GELU)优化
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.1.3 前馈网络(FFN)与激活函数(GELU)优化1. 前馈网络(FFN)的架构设计与数学原理1.1 FFN在Transformer中的核心作用2. GELU激活函数的数学特性与优化2.1 GELU的数学形式与近似计算3. 逐行代码实现…...
STM32 MODBUS-RTU主从站库移植
代码地址 STM32MODBUSRTU: stm32上的modbus工程 从站 FreeModbus是一个开源的Modbus通信协议栈实现。它允许开发者在各种平台上轻松地实现Modbus通信功能,包括串口和以太网。FreeMODBUS提供了用于从设备和主站通信的功能,支持Modbus RTU和Modbus TCP协…...
计算机是如何工作的
目录 冯诺依曼体系 CPU基本工作流程: 逻辑门 门电路 算术逻辑单元 ALU(Arithmetic&LogicUnit) 算术单元(Arithmetic Unit) 逻辑单元(Logic Unit) ALU符号 寄存器(Register)和内存(RAM) 控制单元 CU(Control Unit) 指令(Instruc…...
Arduino、ESP32驱动GUVA-S12SD UV紫外线传感器(光照传感器篇)
目录 1、传感器特性 2、控制器和传感器连线图 3、驱动程序 UV紫外线传感器是一个测试紫外线总量的最佳传感器,它不需要使用波长滤波器,只对紫外线敏感。 Arduino UV紫外线传感器,直接输出对应紫外线指数(UV INDEX)的线性电压,输出电压范围大约0~1100mV(对应UV INDEX值…...
【NLP 48、大语言模型的神秘力量 —— ICL:in context learning】
目录 一、ICL的优势 1.传统做法 2.ICL做法 二、ICL的发展 三、ICL成因的两种看法 1.meta learning 2.Bayesian Inference 四、ICL要点 ① 语言模型的规模 ② 提示词prompt中提供的examples数量和顺序 ③ 提示词prompt的形式(format) 五、fine-tune VS I…...
面向对象软件工程实践软件案例
智力运动-数字化思维训练课程介绍 数字化思维训练是科技赋能素质教育创新实践项目,通过数字化信息化手段,深度融合优质原创智力运动教育课程资源,服务幼儿园与小学,提供信息时代校园素质教育教学解决方案。在《面向对象软件工程》…...
PX4飞控-接收MAVLINK消息(2)-生成MAVLINK_MSG_ID_***.h文件
我在自制的底板上跑vxworks操作系统中移植了MAVLINK的C库用来与PX4飞控进行通信,其中使用的C库和其他依赖文件,例如common文件夹均为从飞控源码中获取,文件获取位置为px4-Autopolite/bulid/mavlink中,因为PX4源码中自带MAVLINK的依…...
Spring Boot 连接 MySQL 配置参数详解
Spring Boot 连接 MySQL 配置参数详解 前言参数及含义常用参数及讲解和示例useUnicode 参数说明: 完整配置示例注意事项 前言 在 Spring Boot 中使用 Druid 连接池配置 MySQL 数据库连接时,URL 中 ? 后面的参数用于指定连接的各种属性。以下是常见参数…...
【数据结构】_单链表_相关面试题(二)
本章重点 hello友友们~ 今天我们将对单链表的后半部分的相关面试题进行详细解析,下面就跟着我一起开启吧~ really GO! 1.相交链表 题目: 输入两个链表,找出它们的第一个公共结点。 代码分析: //找到相交结点…...
深入理解指针(2)(C语言版)
文章目录 前言一、数组名的理解二、使用指针访问数组三、一维数组传参的本质四、冒泡排序五、二级指针六、指针数组七、指针数组模拟二维数组总结 前言 在上一篇文章中,我们初步了解了指针的基本概念和用法。今天,我们将继续深入探索指针在数组、函数传…...
二叉树相关算法实现:判断子树与单值二叉树
目录 一、判断一棵树是否为另一棵树的子树 (一)核心思路 (二)代码实现 (三)注意要点 二、判断一棵树是否为单值二叉树 (一)核心思路 (二)代码实现…...
redux ,react-redux,redux-toolkit 简单总结
Redux、React-Redux 和 Redux Toolkit 是协同工作的三个库,各自承担不同角色,相互协同。 Redux:基础底座 底层状态管理库,负责状态存储、Action 派发和 Reducer 执行 React-Redux:连接 React 组件与 Redux Store 通…...
5. 实现一个中间件
原文地址: 实现一个中间件 更多内容请关注:php代码框架 理解中间件 中间件(Middleware) 是一种在请求被路由到控制器方法之前或响应返回客户端之前执行的代码。它通常用于处理通用任务,如身份验证、日志记录、CORS 处理等。 在…...