news 2026/9/4 7:28:15

基于Scrapy与Pyecharts的招聘数据采集分析系统实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Scrapy与Pyecharts的招聘数据采集分析系统实战

简介:这是一套面向计算机专业学生及Python初学者的期末大作业级实战项目,聚焦Boss直聘平台数据采集与分析全流程,适用于课程设计、毕业设计及数据分析能力训练。资源包含665个文件,涵盖25个核心Python脚本(爬虫、Django后端、API接口与数据处理逻辑)、107个HTML模板页、229个JS交互文件、61个CSS样式文件及54张PNG图表素材,完整支撑前后端分离架构与可视化展示;压缩包仅7.29MB,轻量易部署。已有93人学习下载,配套详细文档说明、README使用手册及附赠教学内容,代码全程注释清晰,覆盖环境配置、Django REST Framework接口开发、pandas数据清洗、matplotlib/seaborn可视化等关键环节,并提供back后端模块、templates模板目录与boss_drf专项爬虫子系统,助学习者从零理解工业级爬虫+分析系统的构建逻辑。

1. 项目概述:从招聘数据中挖掘商业洞察

最近在做一个挺有意思的私活,客户想了解特定行业和城市的招聘市场动态,比如薪资水平、技能需求、公司招聘偏好这些。直接去翻招聘网站,信息太零散,而且手动统计根本不现实。所以,我决定动手写一个系统,专门用来抓取和分析Boss直聘上的公开招聘数据。这不仅仅是一个简单的爬虫脚本,而是一个集数据采集、清洗、存储、分析和可视化于一体的完整系统。对于市场分析、竞品调研、个人求职策略制定,甚至是学术研究,这类系统都能提供非常直观的数据支撑。今天,我就把这个项目的核心思路、技术实现细节,以及我踩过的那些坑,完整地分享出来。无论你是想学习如何构建一个实用的数据管道,还是对招聘数据分析本身感兴趣,相信都能从中找到有价值的内容。

这个系统的目标很明确:自动化、结构化地获取Boss直聘的招聘信息,并通过数据分析揭示出一些肉眼难以察觉的趋势。比如,哪些技能在今年突然变得抢手?哪个城市的某个岗位平均薪资最高?大公司和小公司在招聘要求上有什么不同?为了回答这些问题,我们需要一个稳定可靠的数据来源,这就是爬虫部分的工作;然后,我们需要把杂乱的数据整理干净,这是数据清洗;最后,通过图表把结论清晰地呈现出来,这就是可视化。整个过程,我会使用Python作为主力语言,搭配一些非常成熟的生态库,确保项目的可复现性和可扩展性。

2. 系统核心架构与设计思路

2.1 整体技术栈选型与考量

构建这样一个系统,技术选型是第一步,也是最关键的一步。它直接决定了开发的效率、系统的稳定性以及未来的维护成本。我的核心思路是:模块化、松耦合、易扩展。基于这个原则,我选择了以下技术栈:

  • 数据采集层(爬虫)

    • 语言:Python。这是爬虫领域的绝对主流,库生态极其丰富,从简单的请求到复杂的浏览器模拟,应有尽有。
    • 请求库Requests+httpxRequests简单易用,是处理HTTP请求的瑞士军刀。但对于需要更高性能或异步处理的场景,我会备选httpx,它支持HTTP/2和异步,速度更快。
    • 解析库BeautifulSoup4ParselBeautifulSoup4的API对新手非常友好,适合解析结构相对规整的HTML。而Parsel与Scrapy深度集成,XPath和CSS选择器的性能更优,在复杂页面提取时是我的首选。
    • 框架Scrapy。对于需要大规模、结构化爬取的项目,Scrapy是不二之选。它提供了完整的爬虫框架,包括调度、去重、管道处理等,让我们能专注于核心的解析逻辑,而不是重复造轮子。本项目虽然可以用纯脚本实现,但为了展示工业级实践,我选择基于Scrapy进行构建。
    • 反爬应对:这是爬虫项目的灵魂。我计划采用多管齐下的策略:使用fake-useragent轮换请求头;部署IP代理池(可以使用一些稳定的付费代理服务或自建);在Scrapy中合理设置下载延迟(DOWNLOAD_DELAY)和自动限速(AutoThrottle)扩展,模拟人类行为。
  • 数据存储层

    • 缓存Redis。用于存储去重指纹(如请求URL的MD5值)、临时存放待抓取队列,以及作为分布式爬虫的共享状态存储。它的高速读写特性非常适合这种场景。
    • 结构化存储MySQLPostgreSQL。招聘数据是典型的结构化数据,字段明确(职位名、公司、薪资、地点、要求等),适合用关系型数据库进行持久化存储,便于后续复杂的关联查询和统计分析。
    • 备份与中间存储MongoDB(可选)。如果前期对数据格式不确定,或者想保留原始的、未清洗的JSON格式数据以备不时之需,NoSQL的MongoDB是一个很好的补充。但在本系统核心流程中,我会将清洗后的结构化数据存入MySQL。
  • 数据分析与可视化层

    • 数据处理Pandas。数据分析的“王牌”,提供了DataFrame这种高效的数据结构,进行数据清洗、转换、聚合、分组计算等操作得心应手。
    • 可视化Matplotlib+Seaborn+PyechartsMatplotlib是基础绘图库,功能强大但API稍显底层;Seaborn基于Matplotlib,提供了更美观的统计图形和更简洁的API;Pyecharts则能生成交互式的、可在网页中展示的Echarts图表,非常适合构建数据仪表盘。
    • Web框架FlaskStreamlit。如果需要构建一个交互式的可视化Web应用,轻量级的Flask足够灵活。但如果想快速搭建一个以数据展示为核心的应用,Streamlit是更好的选择,它可以用纯Python脚本快速创建出精美的Web应用,将数据分析结果实时可视化。

注意:在设计和编码时,必须严格遵守目标网站(Boss直聘)的robots.txt协议,并控制请求频率,避免对对方服务器造成压力。本系统仅用于学习和演示合规的数据采集与分析思路,所获数据不应用于任何商业用途或侵犯他人权益。

2.2 爬虫策略:精准、稳定、可持续

面对Boss直聘这样具有复杂反爬机制的网站,一个鲁棒的爬虫策略至关重要。我的策略可以概括为“由面到点,层层递进”。

  1. 入口策略:不直接硬闯搜索列表页,因为其反爬最强。我选择从公司主页入手。可以先通过搜索引擎、公开的企业名录等方式,收集一批目标公司的Boss直聘官方主页链接。以公司主页作为爬虫入口,相对更稳定。
  2. 列表页抓取:进入公司主页后,定位到“在招职位”列表。这里需要解析出每个职位详情页的链接。关键点在于模拟翻页行为,并处理好JavaScript动态加载的内容。Scrapy-Splash或Selenium可以作为渲染动态页面的备选方案,但会显著降低速度。优先尝试分析前端API接口,如果能直接找到返回JSON数据的接口,效率会成倍提升。
  3. 详情页解析:这是获取核心数据的一步。需要从详情页HTML中,精准提取出职位名称、薪资范围、工作地点、经验要求、学历要求、职位描述、公司信息等字段。这里会大量使用XPath或CSS选择器。一个技巧是:先用浏览器的开发者工具查看元素,但不要完全依赖自动生成的路径,因为网站结构可能微调。应该寻找具有稳定idclass的元素,或者利用文本内容本身进行定位。
  4. 增量爬取:为了避免重复抓取和节省资源,需要实现增量爬虫。最常用的方法是在数据库中为每一条记录存储一个基于核心字段(如职位ID、公司、职位名、发布时间)生成的唯一哈希值。在存储新数据前进行比对,只存储新的或已更新的记录。Scrapy内置的dupefilter就是基于请求URL实现去重的,我们可以扩展它,实现基于内容哈希的去重。

3. 核心模块实现细节与避坑指南

3.1 Scrapy爬虫的工程化实现

我选择使用Scrapy框架来构建爬虫主体,因为它能让代码结构非常清晰。一个标准的Scrapy项目包含以下几个核心部分:

  • Items:定义我们要抓取的数据结构。这相当于为数据建模。
# items.py import scrapy class BossJobItem(scrapy.Item): # 定义字段 job_id = scrapy.Field() # 职位ID job_title = scrapy.Field() # 职位名称 company = scrapy.Field() # 公司名称 salary = scrapy.Field() # 薪资范围,如“15-30K” location = scrapy.Field() # 工作地点 experience = scrapy.Field() # 经验要求 education = scrapy.Field() # 学历要求 job_description = scrapy.Field() # 职位描述 tags = scrapy.Field() # 职位标签(技能关键词) publish_time = scrapy.Field() # 发布时间 source_url = scrapy.Field() # 来源URL crawl_time = scrapy.Field() # 爬取时间
  • Spiders:编写爬虫逻辑,即如何跟踪链接以及如何提取数据。
# spiders/boss_spider.py import scrapy from ..items import BossJobItem from urllib.parse import urljoin class BossSpider(scrapy.Spider): name = 'boss' allowed_domains = ['zhipin.com'] # 假设我们有一个公司主页列表作为起始点 start_urls = ['https://www.zhipin.com/c101010100-p100101/'] # 示例:北京-Java def parse(self, response): # 1. 解析列表页,提取职位详情页链接 job_links = response.xpath('//div[@class="job-primary"]/div[@class="info-primary"]/h3/a/@href').getall() for link in job_links: full_url = urljoin(response.url, link) # 将详情页的请求交给 parse_job_detail 方法处理 yield scrapy.Request(full_url, callback=self.parse_job_detail) # 2. 翻页逻辑 next_page = response.xpath('//a[@class="next"]/@href').get() if next_page: yield scrapy.Request(urljoin(response.url, next_page), callback=self.parse) def parse_job_detail(self, response): # 解析详情页,填充Item item = BossJobItem() item['job_title'] = response.xpath('//div[@class="job-primary detail-box"]/div[@class="info-primary"]/div[@class="name"]/h1/text()').get() item['company'] = response.xpath('//div[@class="company-info"]/a[@class="name"]/text()').get() # 薪资、地点等字段的提取,需要仔细分析页面结构 salary_text = response.xpath('//span[@class="salary"]/text()').get() item['salary'] = self._clean_salary(salary_text) if salary_text else None # ... 提取其他字段 item['source_url'] = response.url item['crawl_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') yield item def _clean_salary(self, salary_text): # 清洗薪资字符串,例如“15-30K·13薪” -> “15-30” import re match = re.search(r'(\d+)-(\d+)K?', salary_text) if match: return f"{match.group(1)}-{match.group(2)}" return salary_text
  • Item Pipelines:处理爬取到的Item,比如数据清洗、验证和存储。
# pipelines.py import pymysql from itemadapter import ItemAdapter from .items import BossJobItem class MySQLPipeline: def __init__(self, mysql_uri, mysql_db): self.mysql_uri = mysql_uri self.mysql_db = mysql_db @classmethod def from_crawler(cls, crawler): return cls( mysql_uri=crawler.settings.get('MYSQL_URI'), mysql_db=crawler.settings.get('MYSQL_DATABASE', 'boss_data') ) def open_spider(self, spider): self.conn = pymysql.connect( host=self.mysql_uri['host'], user=self.mysql_uri['user'], password=self.mysql_uri['password'], database=self.mysql_db, charset='utf8mb4' ) self.cursor = self.conn.cursor() # 创建表(如果不存在) self._create_table() def close_spider(self, spider): self.conn.close() def process_item(self, item, spider): if isinstance(item, BossJobItem): # 实现增量逻辑:检查 job_id 或根据其他字段生成唯一键是否已存在 # 这里假设 job_id 是唯一的 check_sql = "SELECT id FROM job_listings WHERE job_id = %s" self.cursor.execute(check_sql, (item['job_id'],)) if self.cursor.fetchone(): # 已存在,可以选择更新(例如更新发布时间) spider.logger.info(f"Job {item['job_id']} already exists, skipping.") else: # 不存在,插入新记录 insert_sql = """ INSERT INTO job_listings (job_id, job_title, company, salary_min, salary_max, location, ...) VALUES (%s, %s, %s, %s, %s, %s, ...) """ # 需要将item中的薪资字符串拆分成最小值和最大值 salary_min, salary_max = self._parse_salary(item['salary']) values = (item['job_id'], item['job_title'], item['company'], salary_min, salary_max, item['location'], ...) self.cursor.execute(insert_sql, values) self.conn.commit() return item def _parse_salary(self, salary_str): # 将“15-30”解析为 (15, 30) if salary_str and '-' in salary_str: try: low, high = salary_str.split('-') return int(low), int(high) except ValueError: return None, None return None, None
  • Middlewares:用于处理请求和响应,是植入反爬策略的关键位置,比如设置代理、更换User-Agent。
# middlewares.py import random from scrapy import signals class RandomUserAgentMiddleware: def __init__(self, user_agents): self.user_agents = user_agents @classmethod def from_crawler(cls, crawler): s = crawler.settings ua_list = s.get('USER_AGENT_LIST', []) if not ua_list: ua_list = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...', # ... 更多UA ] return cls(ua_list) def process_request(self, request, spider): request.headers['User-Agent'] = random.choice(self.user_agents) class ProxyMiddleware: def process_request(self, request, spider): # 从代理池获取一个代理IP proxy = get_proxy_from_pool() # 假设的函数 if proxy: request.meta['proxy'] = proxy

避坑心得

  1. 选择器稳定性:网站前端微小的改动就可能导致你的XPath或CSS选择器失效。不要使用过于复杂或依赖绝对位置的路径。多使用具有明确语义的class>CREATE TABLE `job_listings` ( `id` int(11) NOT NULL AUTO_INCREMENT, `job_id` varchar(100) NOT NULL COMMENT '职位原始ID', `job_title` varchar(200) NOT NULL, `company` varchar(200) NOT NULL, `salary_min` int(11) DEFAULT NULL COMMENT '最低薪资(K)', `salary_max` int(11) DEFAULT NULL COMMENT '最高薪资(K)', `salary_unit` varchar(10) DEFAULT 'K', `is_negotiable` tinyint(1) DEFAULT '0', `city` varchar(50) DEFAULT NULL, `district` varchar(50) DEFAULT NULL, `is_remote` tinyint(1) DEFAULT '0', `experience` varchar(50) DEFAULT NULL COMMENT '经验要求分类', `education` varchar(50) DEFAULT NULL COMMENT '学历要求分类', `job_description` text, `publish_time` datetime DEFAULT NULL, `source_url` varchar(500) DEFAULT NULL, `crawl_time` datetime NOT NULL, `tags` json DEFAULT NULL COMMENT '技能标签,JSON数组格式,如 [\"Python\", \"数据分析\", \"SQL\"]', PRIMARY KEY (`id`), UNIQUE KEY `uniq_job` (`job_id`), KEY `idx_city` (`city`), KEY `idx_publish_time` (`publish_time`), KEY `idx_title` (`job_title`(20)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='招聘职位主表';

    使用utf8mb4字符集可以支持存储Emoji等特殊字符。tags字段使用JSON类型,方便存储和查询数组数据。建立了必要的索引以加速后续的查询分析。

    4. 数据分析与可视化:从数据到洞察

    当数据被干净地存储到数据库后,我们就可以开始最有意思的部分——挖掘洞察。我会使用Pandas从MySQL中读取数据,并进行一系列分析。

    4.1 使用Pandas进行多维数据分析

    首先,连接数据库并加载数据:

    import pandas as pd import pymysql import matplotlib.pyplot as plt import seaborn as sns from pyecharts.charts import Bar, Pie, Map, WordCloud from pyecharts import options as opts # 连接数据库 conn = pymysql.connect(host='localhost', user='root', password='your_password', database='boss_data') query = "SELECT * FROM job_listings WHERE publish_time > '2023-01-01'" # 按需筛选 df = pd.read_sql(query, conn) conn.close() # 数据预览和基本清洗(确保在数据库层面已做,这里做二次检查) print(df.head()) print(df.info())

    接下来,我们可以进行多种分析:

    1. 薪资水平分析:

    # 计算平均薪资(取薪资范围中位数) df['salary_mid'] = (df['salary_min'] + df['salary_max']) / 2 # 按城市分组查看平均薪资 avg_salary_by_city = df.groupby('city')['salary_mid'].mean().sort_values(ascending=False).head(10) print(avg_salary_by_city)

    2. 技能需求热度分析:

    # 假设tags字段是JSON字符串列表,如 '["Python", "SQL"]' # 需要先将其从字符串转换为Python列表 import ast df['tags_list'] = df['tags'].apply(lambda x: ast.literal_eval(x) if pd.notnull(x) else []) # 将所有标签展开(explode),并统计频率 all_tags = df.explode('tags_list') tag_counts = all_tags['tags_list'].value_counts().head(20) print(tag_counts)

    3. 公司招聘规模分析:

    # 统计发布职位最多的公司 top_companies = df['company'].value_counts().head(10) print(top_companies)

    4.2 利用Pyecharts构建交互式可视化大屏

    静态图表适合报告,交互式图表更适合探索。Pyecharts能生成非常漂亮的网页图表。

    示例1:热门技能词云

    from pyecharts.charts import WordCloud from pyecharts.globals import SymbolType # 使用上面统计的tag_counts data = [(tag, int(count)) for tag, count in tag_counts.items()] wordcloud = ( WordCloud() .add(series_name="技能热度", data_pair=data, word_size_range=[20, 100]) .set_global_opts( title_opts=opts.TitleOpts(title="热门技能需求词云", title_textstyle_opts=opts.TextStyleOpts(font_size=23)), tooltip_opts=opts.TooltipOpts(is_show=True), ) ) wordcloud.render("skill_wordcloud.html") # 生成HTML文件

    示例2:各城市平均薪资水平地图

    from pyecharts.charts import Map # 准备数据:格式为 [(城市名, 数值), ...] city_salary_data = [(city, round(value, 2)) for city, value in avg_salary_by_city.to_dict().items()] salary_map = ( Map() .add("平均薪资(K)", city_salary_data, "china") .set_global_opts( title_opts=opts.TitleOpts(title="各城市招聘平均薪资分布"), visualmap_opts=opts.VisualMapOpts(max_=50), # 假设最高50K ) ) salary_map.render("salary_map.html")

    示例3:职位数量与薪资关系的散点图(气泡图)可以分析某个岗位(如“数据分析师”)在不同经验要求下的薪资分布。

    为了构建一个完整的可视化仪表盘,我们可以使用FlaskStreamlit将这些独立的图表整合到一个Web页面中。Streamlit尤其简单:

    # app.py (Streamlit) import streamlit as st import pandas as pd import plotly.express as px # Streamlit 也支持 Plotly st.set_page_config(layout="wide") st.title("Boss直聘招聘市场分析仪表盘") # 加载数据 df = load_data_from_db() # 创建多列布局 col1, col2 = st.columns(2) with col1: st.subheader("热门技能Top 10") # 这里可以嵌入一个Pyecharts的HTML,或者用Streamlit原生图表 fig1 = px.bar(tag_counts.head(10), x=tag_counts.head(10).index, y=tag_counts.head(10).values) st.plotly_chart(fig1, use_container_width=True) with col2: st.subheader("各城市平均薪资") # 同样,可以嵌入地图HTML或使用其他库 # st.components.v1.html(open("salary_map.html").read(), height=500) fig2 = px.bar(avg_salary_by_city.head(15)) st.plotly_chart(fig2, use_container_width=True) # 添加过滤器 selected_city = st.sidebar.selectbox("选择城市", df['city'].unique()) filtered_df = df[df['city'] == selected_city] # ... 根据筛选条件更新图表

    运行streamlit run app.py,一个交互式的数据分析应用就启动了。

    5. 系统部署与运维要点

    一个完整的系统不能只跑在本地。为了让其持续运行,需要考虑部署和运维。

    1. 环境隔离:使用virtualenvconda创建独立的Python环境,确保项目依赖不会冲突。使用requirements.txt文件记录所有依赖包及其版本。

      pip freeze > requirements.txt
    2. 定时任务:爬虫需要定期执行以获取最新数据。在Linux服务器上,最经典的方式是使用Cron定时任务。

      # 每天凌晨2点执行爬虫 0 2 * * * cd /path/to/your/project && /path/to/your/venv/bin/scrapy crawl boss >> /var/log/boss_crawl.log 2>&1

      更复杂的调度可以使用Apache AirflowCelery Beat

    3. 日志管理:完善的日志是排查问题的生命线。在Scrapy的settings.py中配置日志级别和输出文件。

      LOG_LEVEL = 'INFO' LOG_FILE = '/var/log/scrapy_boss.log'
    4. 监控告警:监控爬虫是否正常运行、数据量是否异常、错误率是否升高。可以编写简单的脚本检查日志文件中的错误关键词,或者使用更专业的监控系统如Prometheus+Grafana。当爬虫因网站改版而大面积解析失败时,能第一时间收到告警。

    5. 数据备份:定期备份MySQL数据库。可以使用mysqldump命令,并结合云存储服务。

    6. 常见问题与排查技巧实录

    在实际开发和运行中,我遇到了不少问题,这里总结几个典型的:

    问题1:爬虫很快被屏蔽,返回403或验证码页面。

    • 排查:首先检查请求头,特别是User-Agent是否模拟了真实浏览器。然后检查请求频率是否过高。
    • 解决
      • 完善中间件,使用更真实的User-Agent列表并随机切换。
      • 显著降低DOWNLOAD_DELAY,并启用AUTOTHROTTLE
      • 引入IP代理池。这是应对IP封锁最有效的手段。可以购买可靠的付费代理服务,并实现一个中间件来随机选用代理。
      • 如果网站使用了复杂的JavaScript反爬(如数据通过AJAX加载且参数加密),可能需要动用SeleniumPlaywright来模拟浏览器行为,但这会极大增加资源消耗和降低效率。优先尝试寻找并破解其数据接口。

    问题2:数据解析失败,很多字段为None。

    • 排查:打开一个目标网页,用浏览器开发者工具查看元素,对比你代码中的XPath/CSS选择器是否还能定位到目标元素。很可能网站前端已经更新了。
    • 解决
      • 更新你的选择器。尽量使用更具鲁棒性的选择方式,比如通过包含特定文本的相邻元素来定位。
      • 编写选择器的“降级”逻辑:如果首选选择器找不到,尝试备用选择器。
      • 将解析失败的页面URL和HTML片段保存下来,用于后续调试和更新解析规则。

    问题3:数据库写入速度慢,成为瓶颈。

    • 排查:检查是否每条数据都立即提交(commit),或者是否使用了低效的插入方式。
    • 解决
      • 在Pipeline中使用批量插入(executemany)来代替逐条插入。
      • 调整MySQL配置,如增大innodb_buffer_pool_size
      • 考虑先将数据暂存到本地文件(如JSON Lines格式),爬虫结束后再用单独的脚本批量导入数据库,实现读写分离。

    问题4:提取的技能标签噪音很大。

    • 排查:查看提取出的标签列表,是否混入了“福利”、“团队”等非技能词汇。
    • 解决
      • 优化技能词典,只保留纯粹的技术栈关键词。
      • 在提取后加入过滤步骤,比如只保留出现在公认技术词库中的词。
      • 尝试使用jieba.analyse的TF-IDF或TextRank功能进行关键词提取,并设置停用词列表来过滤常见非技术词汇。

    构建这样一个系统,最大的收获不是最终那一张张漂亮的图表,而是在这个过程中对数据流水线的每一个环节——从采集、反爬对抗、清洗、存储到分析——都有了更深刻、更实战化的理解。每一个环节的坑踩过去,都是宝贵的经验。最后,务必记住,技术是用来解决问题的,但必须在法律和道德的框架内使用。尊重网站规则,控制访问频率,只获取公开且允许获取的数据,用于正当的学习和研究目的,这才是长久之道。

    本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 7:28:06

### Python Turtle 库正方形绘制代码及深度解析报告

一、 核心绘制代码实现 以下是使用 Python 内置 Turtle 库绘制标准正方形的完整代码。该代码通过循环结构实现了图形的高效绘制,逻辑清晰且易于扩展。 import turtle# 初始化海龟画笔,设置基础属性 pen turtle.Turtle() pen.pencolor("blue")…

作者头像 李华
网站建设 2026/9/4 7:27:40

高难度谱面设计逻辑:从交互语言到心流体验的深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 7:27:21

单片机PID温控电烙铁设计:从传感器选型到PID算法实战

简介:本资源是一个基于STC89C52单片机的智能电烙铁温度控制系统完整开发包,面向电子工程初学者、嵌入式爱好者及高职/本科实践教学场景,解决手工焊接中温度失控导致虚焊、元器件损伤等核心问题。压缩包含32个文件,涵盖4个C源码&am…

作者头像 李华
网站建设 2026/9/4 7:26:20

大模型微调学习(二)

二、Lora微调这页主要说明:对 GPT-3 这种超大模型进行全参数 Fine-tune,成本非常高。“噩梦”主要体现在三个方面: 显存压力大:175B 参数模型全参训练大约需要 96 张 V100 32GB 才能基本放得下。存储成本高:每训练一个…

作者头像 李华
网站建设 2026/9/4 7:26:01

开发急躁症:从情绪失控到系统化问题排查的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华