Scrapy爬虫实战:以百度搜索页为例的入门项目解析

发布时间:2026/10/14 23:00:49

Scrapy爬虫实战:以百度搜索页为例的入门项目解析 1. 为什么拿百度搜索页当Scrapy入门练手需求边界与预期管理1.1 这个项目到底在爬什么Scrapy 爬虫框架新手接触它时最大的问题不是不知道它有多强而是不知道用它做的第一个项目该长什么样。我见过不少人捧着一本爬虫书把目录背完了第二天依然只会对着官方示例发呆。我的建议是别想太多直接找一个每天都会用到的页面去拆解。百度搜索页恰好就是这样的对象——它结构清晰、目标明确、反馈快拿来做“初探 Scrapy 爬虫框架”的第一个练手项目非常合适。先把这个标题拆开看。“百度网页爬取”这句话很容易被理解成“把百度整个网站爬下来”这既不可能也完全没有必要。真实的练手目标是构造一句搜索词获取百度搜索结果页的 HTML再从结果页中提取出每一条结果的标题、链接和摘要信息。就这么简单。搜索词不同、结果数量不同但页面结构高度一致所以后面写的解析代码可以反复复用。这也是为什么搜索引擎结果页特别适合当 Scrapy 入门的教学样本。说句实在话Scrapy 本身不复杂复杂的是你对“数据从哪里来、爬到之后放哪里去”没有概念。百度搜索页的数据流很直观请求一个 URL页面返回解析入库。你只需要关注三个环节请求是怎么构造的、页面结构是怎么样的、解析结果存到哪。这三个环节正好覆盖了 Scrapy 中请求Request、响应Response、条目Item和管道Pipeline这四个最核心的概念。等这个项目跑完你会发现框架的大半个骨架你已经摸过了。1.2 初学阶段容易踩的预期误区我见过不少人在开始这个项目之前先把事情想得特别复杂。比如花一整天研究如何隐藏 IP、如何对抗验证码、如何模拟真人浏览器。这些东西当然真实存在但绝对不是“初探”阶段的最优玩法。你把全部精力放在对抗策略上最后很可能连基础的页面解析都没学会。第一个误区是以为爬虫的难点全在反爬。真实情况是反爬只是整个链路中的一环。项目能不能跑通更重要的是解析逻辑、数据结构和流程控制。百度搜索页本身有明确的反爬机制但按本文的方式控制好频率就可以在一个很小的规模上完成学习目标。不要指望初学阶段就做出那种每秒几十个请求、能跑一整年的东西那不叫练手那叫攻城。第二个误区是忽略 URL 编码。很多人直接往 URL 里拼中文关键词结果请求发出去了页面返回的却是错误或空白。百度搜索页采用wd参数传递关键词中文必须经过 URL 编码否则请求发出去不一定报错但服务端收到的关键词是乱的这会给排查增加很多不必要的成本。第三个误区是一上来就追求完整工程化。要自动翻页、要并发调优、要分布式采集这些在入门阶段都先放一放。本文项目只需要抓取第一页的部分结果跑通后你再自己扩展。先把一条流水线跑通比你同时开十个线程在那里试错强十倍。预期管理做好了后面遇到的每个问题都会变得可控。2. 环境搭建与第一个爬虫骨架从安装到跑通一次请求2.1 安装与项目初始化里容易被忽略的细节Scrapy 的安装通常一句话就能搞定我建议先建虚拟环境再执行pip install scrapy。不要图省事直接装在系统 Python 里因为 Scrapy 依赖的Twisted、lxml、pyOpenSSL等库版本敏感虚拟环境能避免很多莫名其妙的问题。Python 版本选 3.8 以上即可新版 Scrapy 对旧版本的支持并不好动手之前先看一眼自己python --version的输出。装好之后初始化项目我习惯在干净的目录下执行scrapy startproject baidu_scraper执行完你会得到一个以baidu_scraper命名的项目目录。值得注意的一点是这里的小写项目名会在很多地方作为 import 根路径出现不要起成中文也不要用-。项目结构大致如下baidu_scraper/ scrapy.cfg baidu_scraper/ __init__.py items.py middlewares.py pipelines.py settings.py spiders/ __init__.py初学者最容易忽略的是scrapy.cfg这个文件。它记录的是项目配置和部署信息默认情况下不需要改但如果你后面想用 Scrapyd 部署就会回来找它。spiders目录是存放爬虫代码的地方items.py定义数据结构pipelines.py做数据清洗和存储settings.py控制全局行为。这几个文件的基础作用在这个项目中你都会实际用到。创建完项目后进到spiders目录里新建一个 Python 文件。也可以用 Scrapy 自带的模板快速生成cd baidu_scraper/baidu_scraper/spiders scrapy genspider baidu_search baidu.com这条命令会生成一个包含基础框架的爬虫代码但初学阶段我的建议是别直接用模板而是自己手写一个最简单的请求先把流程跑通再慢慢扩展。2.2 定义 Item 与构建第一个 Spider先定义我们要从搜索结果页里拿什么数据。打开items.py写入下面这段代码import scrapy class BaiduItem(scrapy.Item): title scrapy.Field() # 搜索结果标题 link scrapy.Field() # 跳转链接 abstract scrapy.Field() # 摘要文本 query scrapy.Field() # 本次搜索的关键词定义 Item 的好处是让爬虫的每个条目标识清楚字段怎么处理、往哪里存都有了统一约定。就算你现在只是打印出来也建议先建这个结构。别嫌麻烦等后面你把abstract拿去做编码清洗、把link做去重时就会明白提前定义字段有多省心。现在写爬虫主体。在spiders/baidu_search.py中import scrapy from urllib.parse import quote class BaiduSearchSpider(scrapy.Spider): name baidu_search def start_requests(self): keyword Scrapy 爬虫教程 url https://www.baidu.com/s?wd quote(keyword) yield scrapy.Request(url, callbackself.parse)这里有几个地方值得展开讲一下。start_requests是 Scrapy 的入口方法它要求返回可迭代对象最常见的就是yield一个或多个Request。quote(keyword)会对中文关键字进行 URL 编码百度页面才能正确识别。我见过不少人用urlencode但在这里其实quote更简单直接。正文解析暂时先不写先写一个最简单的解析方法把响应内容保存成文件验证请求是否能通def parse(self, response): page_text response.text with open(baidu_page.html, w, encodingutf-8) as f: f.write(page_text)2.3 让爬虫真正跑起来命令行调试技巧在项目根目录执行cd baidu_scraper scrapy crawl baidu_search如果一切正常你会看到大量日志滚出来。起初完全可以忽略这些日志只看最后是否生成了baidu_page.html。我第一回跑通的时候看到这个文件里确实有关键词相关的搜索结果才真正松了一口气。这就是这个项目的里程碑你已经能通过 Scrapy 拿到百度搜索页的完整 HTML 了后面的解析工作不过是把这堆 HTML 里面的有用内容抠出来。有必要提一下日志级别。默认日志全是 DEBUG非常嘈杂。你可以在启动命令里加-s LOG_LEVELINFO也可以直接在settings.py里设置LOG_LEVEL INFO。我建议项目一开始就在settings.py里配好省得每次敲命令都要多打一串参数。scrapy crawl baidu_search -s LOG_LEVELINFO另一个强烈推荐的做法是写解析代码之前先用 Scrapy Shell 对目标页面进行反复试探。在项目根目录执行scrapy shell https://www.baidu.com/s?wdScrapy它会打开一个交互式终端把你请求到的 response 对象直接放进环境里。这个工具是整个开发链路中最重要的调试利器尤其是面对百度这种结构经常微调的页面每次写完选择器都要先在这里验证而不是直接改爬虫代码盲跑。3. 百度搜索结果页的结构解析与数据提取XPath 与 CSS 选择器实战3.1 搜索结果页的 HTML 骨架拆解打开上一步保存的baidu_page.html你会看到一堆充满 class 和 id 的 div 标签。不同时期百度搜索结果页的 HTML 结构可能不同但大体上保留了这些线索整个搜索结果列表位于div#content_left容器内每条普通结果通常是div.result较小类型的结果有可能是div.result-op或div.c-container标题一般出现在h3标签下的a标签中里面是标题文本链接就在这个a标签的href属性中摘要文本通常在标题下方的div里class 名称可能是c-abstract或者其他形态。我建议不要在代码里把任何 class 名称写成“死老硬”。百度的前端改版速度很快你今天写好的选择器也许三个月后就不再匹配了。最终还是要以实际抓下来的 HTML 为准。这也是整个项目里最需要动手的部分去看、去试、去调整而不是背选择器。3.2 用 Scrapy Shell 验证选择器有了 HTML 文件后可以继续在 Scrapy Shell 里做验证。登录交互环境后你直接输入response.css(div#content_left h3 a::text).getall()如果返回一个列表里面是每条搜索结果的标题那么第一个选择器就验证通过了。再试试提取链接response.css(div#content_left h3 a::attr(href)).getall()这里就是初学者最常见的分岔口。很多人发现取出来的链接是类似/link?url...的跳转地址而不是真实的落地页 URL。这是百度为了统计点击行为设置的中间跳转直接存下来也不是不能用但如果你想拿到真实的目标网址需要对该跳转链接发起请求跟随重定向后再读取最终 URL。为了保持入门项目的简单性我建议先把跳转链接原样存到 Item 里含义注释清楚。等后续你有能力处理重定向时再去做还原也不迟。摘要不是每条结果都有所以要先试试response.css(div#content_left div.c-abstract::text).getall()如果拿不到结果换成另一个常见结构比如空格分开的多个文本片段response.xpath(//div[idcontent_left]//div[contains(class,c-abstract)]//text()).getall()实际操作过程中摘要的 class 经常变化。我的做法是不追求选得完美只要能把大部分结果里的摘要文本取出来就够用。入门项目本来就不该在边缘个案上死磕。3.3 提取标题、链接与摘要的正式 parse 代码下面是我调整过后的完整解析逻辑你可以直接作为参考def parse(self, response): results response.css(div#content_left h3 a) for a in results: item BaiduItem() item[title] a.css(::text).get() href a.css(::attr(href)).get() if not href: continue item[link] response.urljoin(href) item[query] self.keyword item[abstract] yield item里面有几个细节值得注意。第一response.urljoin(href)能把页面 URL 与相对路径或跳转路径拼接成完整 URL比直接拼字符串稳妥。第二有些结果没有标题或者标题只有一个链接文字::text拿不到值时用.get()返回None需要判断后跳过。否则后面管道处理会一直报错。第三摘要我暂时没有填因为在主列表页里结构不稳定更推荐后续再解析详情页但那已经超出“初探”的范畴了。写到这里你的爬虫已经从发起请求进入到解析数据的阶段。跑一遍scrapy crawl baidu_search -o results.json在项目目录下会生成一个results.json里面保存了从百度搜索结果页提取出来的标题和链接。到这一步Scrapy 的核心链路已经被你完整走通请求、下载、解析、导出。项目进度大约完成了 60%。4. 初探路上绕不开的反爬机制UA、Cookie 与请求频率4.1 服务器是怎么认出爬虫的当你的爬虫开始正常工作后大概率会遇到一类现象第一次请求挺顺利接着做第二次、第三次时返回的页面变成验证码或者直接返回一个空壳页面。这背后是目标服务器的反爬机制在起作用。网站识别爬虫最常用的是三招。第一招定身份检查 User-AgentUA。如果你的请求头里没有浏览器 UA或者 UA 是类似python-requests/x.x这种字符串服务器一眼就能看出来不是真人浏览器。第二招查行为真人搜索通常几秒一次爬虫却可能在几毫秒内连续发起几十个请求。第三招留凭证很多搜索页会在浏览器设置 Cookie带着 Cookie 访问翻页和二次请求成功率更高。针对这三招Scrapy 都有对应的控制手段。不要一上来就想着搞代理池、搞浏览器指纹、搞自动化验证码识别那些都属于后续进阶内容。作为初探项目把 UA 设置成常见浏览器把请求频率降到人类操作水平就已经足够完成实验了。4.2 settings.py 中需要调整的关键参数打开项目里的settings.py我建议重点关注这几个参数参数建议值作用ROBOTSTXT_OBEYFalse关闭内置 robots 协议检查但要在心里给自己画红线USER_AGENT浏览器完整 UA 字符串避免疑似脚本特征DOWNLOAD_DELAY3每次下载之间的最小间隔单位秒CONCURRENT_REQUESTS4全局最大并发请求数CONCURRENT_REQUESTS_PER_IP1同一 IP 的并发数限制它比限制总量有效LOG_LEVELINFO减少日志噪音其中DOWNLOAD_DELAY和CONCURRENT_REQUESTS_PER_IP是保护自己最管用的两个旋钮。真实用户的请求间隔不可能低于 0.1 秒你把下载延迟调到 3 秒等于给自己踩刹车。很多人觉得调低并发会影响速度但入门项目需要的本来就不是速度而是稳定。一次只发一两个请求跑完歇一会儿比触发风控后长时间停机要划算得多。User-Agent 不要用那种全网通用的“空格”值。我习惯从自己浏览器的开发者工具里复制一个真实 UA然后填到settings.py里。注意大小写和空格不要错UA 字符串里任何错误都可能造成页面渲染结果变化。4.3 验证码与封 IP 的现实初学阶段的处理策略如果有人告诉你没有遇到过验证码要么他爬得少要么他运气好。百度搜索页在检测到高频请求后最常见的返回内容就是安全验证页面。这个页面长得一点也不像正常搜索结果里面是一个大大的验证码滑块或点击验证。初学阶段我的建议非常明确看到验证码就停下来。不要试图写代码去识别验证码那是另一个深坑。你只需要暂停爬虫等几分钟甚至半小时再重跑。如果仍然弹验证码可以考虑更换当前网络的出口 IP比如用手机热点。这些都属于常规操作绝不是为了提高什么“隐蔽性”而是尊重对方服务器的负载同时保证自己的教学项目能顺利演示。在代码层面可以打开 Scrapy 的重试机制保证遇到非 200 状态码时自动重试几次。默认配置下Scrapy 会对超时请求重试 2 次如果你希望更稳妥可以在settings.py里这样配置RETRY_TIMES 2 RETRY_HTTP_CODES [500, 502, 503, 504, 522, 524]如果返回的是验证码页面它的 HTTP 状态码通常是 200所以重试机制并不能识别出“这不是目标内容”。你可以在解析函数里加一个简单判断如果响应中没有content_left节点就认为被风控了直接返回不再解析。4.4 robots.txt 不是万能的但别无视每个正规网站几乎都有robots.txt它声明了哪些路径允许自动采集。百度搜索页的 robots 协议对普通爬虫并不友好所以很多人直接把ROBOTSTXT_OBEY设为False。我的态度是这个开关只是一个工具关键是你心里要有一把尺。初学项目里我会把ROBOTSTXT_OBEY设为False但同时在代码里做明确限速并且只抓取公开搜索结果里很少的一部分数据不涉及个人信息也不做商业化使用。这样做的目的是让流程跑通不是为了教唆任何人去恶意抓取。以后你有了工作项目一切采集行为都要以对方的服务条款和适用法律法规为准。其实真正应该关注的是“频率红线”。你自己定一个阈值比如每分钟不超过 20 次请求跑完 50 条结果就立刻停止。这样即使不解析 robots 文件也远比开着高并发、无视任何协议要安全得多。5. 数据落盘与去重打破“只会在控制台打印”的入门瓶颈5.1 用 Pipeline 保存到 CSV 和 JSON很多人都停在scrapy crawl baidu_search然后看终端输出的阶段。打印输出只能用于调试不能作为数据交付。实现数据导出最简单的方式是 Scrapy 自带的 Feed Export比如刚才说的-o results.json它可以把 Item 序列化输出。但这个方式有两个问题一是它无法做字段过滤和清洗二是当 Item 体积变大、类型变多时它的控制力显得很弱。正确的方式是使用 Pipeline。Pipeline 是 Scrapy 中负责处理 Item 的组件你可以把它理解成流水线上的质检工位。先写一个最简单的 Pipeline把 Item 写入 JSON Lines 文件。打开pipelines.py写入import json class JsonPipeline: def open_spider(self, spider): self.file open(results.jsonl, w, encodingutf-8) def close_spider(self, spider): self.file.close() def process_item(self, item, spider): line json.dumps(dict(item), ensure_asciiFalse) \n self.file.write(line) return item然后在settings.py中激活这个 PipelineITEM_PIPELINES { baidu_scraper.pipelines.JsonPipeline: 300, }后面的数字300是执行优先级数字越小越先执行。多个 Pipeline 会按优先级依次处理每一个 Item上一个的返回值会传给下一个。这套机制很灵活一个 Pipeline 清洗字段另一个去重第三个存储各管一段。得到 JSON 文件之后把它转成 CSV 非常容易。你也可以直接写另一个导出 CSV 的 Pipeline。但为了简单我建议先输出 JSON之后用任意数据分析工具或者写个小脚本转格式。JSON 比 CSV 更能适配嵌套信息也让字段关系更清楚入门阶段拿它练手最合适。需要注意的是写入文件的编码。Windows 下如果不指定encodingutf-8默认可能会写出 GBK 乱码。这里强制指定 UTF-8并且ensure_asciiFalse这样中文摘要和标题保存下来才可读。5.2 去重逻辑与业务级去重Scrapy 自带的去重机制是基于请求 URL 的。同一个 URL 不会重复下载这对防止页面被重复请求非常有效。但你抓的是搜索结果页同一篇文章可能通过不同跳转地址进入同一个目标页面也可能在不同关键词的搜索结果里反复出现。这种“业务级去重”光靠请求去重不够必须在 Item 层面做。最简单的办法是把链接或者标题经过哈希后存到一个集合里。如果哈希值已经存在就丢弃这个 Item。例如import hashlib seen_links set() def process_item(self, item, spider): link item.get(link, ) digest hashlib.md5(link.encode(utf-8)).hexdigest() if digest in seen_links: raise DropItem(Duplicate link: %s % link) seen_links.add(digest) return item这里DropItem是 Scrapy 内置的异常在process_item里抛出它这个 Item 就不会再进入后面的 Pipeline。如果你需要跨多次运行去重那就得引入数据库或外部缓存初学阶段用内存里的set足够说明问题。我特别想强调的是去重不能只做一个点而是要看你的业务需要。如果只是想避免同一个目标链接被重复保存链接哈希就够。如果怕标题一样但链接不同那就用标题哈希。如果怕组合重复可以把标题、链接、摘要拼接后再哈希。关键是你要想明白“重复”到底指什么否则做出来的去重只是自欺欺人。6. 跑完这个项目的总结哪些环节最耗时怎么继续进阶6.1 实测中拖慢进度的三个坑把整个项目跑下来后回头看看最耗时的往往不是写代码而是排查下面这三类问题。第一个坑是页面结构漂移。你照着博客里的 CSS 类名写选择器跑起来却一条数据都没有。根本原因是百度的页面结构一直在调整或者搜索结果里混入了不同类型的卡片。这个问题没有捷径只能在 Scrapy Shell 里反复看实际返回的 HTML然后针对当前结构写选择器。不要怕麻烦这个步骤本身就是爬虫工作的日常。第二个坑是 URL 编码不彻底。关键词里有空格、引号、百分号时只做quote可能还不够。比如搜索Scrapy 爬虫建议先打印构造出来的完整 URL在浏览器里打开看一眼是否正常。如果浏览器里能搜出结果再回到 Scrapy 中发起请求这样可以快速隔离问题是在编码、还是 UA、还是别的位置。第三个坑是请求频率失控。最开始测试时可用-s DOWNLOAD_DELAY0这类参数临时提速这会让你很爽但也很快让你触发风控。等到被验证码拦住再冷静下来调慢往往已经损失了不少时间。我的经验是前期就按慢速来每跑完一组数据看一眼日志里返回的响应是否正常确认稳定后再一点点提速。6.2 从“爬下来”到“稳定爬”还需要补什么这个初探项目完成以后你对 Scrapy 的组成部分已经有了实际感知Spider 负责解析逻辑、Item 定义数据结构、Pipeline 负责后续处理、Settings 控制全局行为。想要往更深入的方向走建议按照下面的路径补齐第一是学习分页。搜索页有翻页机制百度使用pn10这样的参数表示第二页。对pn进行循环就能抓取多页结果。但每次翻页都要保持同样的限速否则很容易触发风控。第二是学习中间件。Scrapy 的 Downloader Middleware 可以在请求发出前统一修改 Headers在请求返回后统一检查状态码。把 UA 轮换、Cookie 管理、重试逻辑放到中间件里爬虫代码会变得非常干净。第三是学习异步与并发控制。Scrapy 默认基于 Twisted 异步引擎CONCURRENT_REQUESTS等参数就是用来控制异步并发窗口的。等你理解了异步事件循环才能真正明白为什么 Scrapy 快也才能知道它什么时候会失控。第四是学习数据清洗与入库。文本摘要里经常混着换行、空格和乱码标题可能带有权重标签。可以用 Python 的re模块做清洗也可以借助正则提取结构化字段。之后把数据存进 MySQL 或 MongoDB又是一个全新的项目。最后再分享一个我个人的操作习惯任何爬虫项目都不要急着写 Spider。先手动打开页面看清数据结构再用scrapy shell试选择器最后才写正式的解析代码。这一套流程在带新手的实践里验证过很多次比对着文档死磕要高效得多。Scrapy 入门不难难的是把“能跑”的东西变成“稳定、可控、有产出”的东西。希望这个百度网页爬取的初探项目能帮你把第一脚踩实后面再遇到什么复杂的采集需求你至少知道自己该怎么拆、该从哪里入手。
延伸阅读

更多相关文章

2026/10/14 23:00:49

参数越多越容易过拟合?Double Descent如何颠覆你的模型容量直觉

1. 经典机器学习里那个“常识”是怎么来的——从Bias-Variance到过拟合直觉不知道你有没有一种感觉:深度学习领域里流传着太多“反直觉”的结论,而其中最反直觉、也最常被拿出来讨论的,就是大模型明明参数多到能把训练集倒背如流,…

2026/10/14 23:00:49

2026论文降重工具实测盘点:从查重原理到AI改写正确用法

“2026权威盘点”这标题起得有点大,我其实不是权威,就是个被论文折磨过、也帮不少人改过论文的过来人。但我可以保证,下面写的每一句,都来自这几年跟查重系统、降重工具实打实搏斗出来的经验。2026年了,查重系统的算法…

2026/10/14 23:00:49

seaborn热力图实战:从入门到参数调优与案例详解

第一次真正意识到热力图的价值,是在处理一份几十列的业务报表的时候。表格里密密麻麻全是数字,我盯着相关性系数来回看,眼睛都快失焦了,还是说不清哪些变量之间有关联。后来用 seaborn.heatmap 把相关性矩阵画成一张图&#xff0c…

2026/10/14 23:41:09

从工具调用到Code Mode:AI Agent范式转移与工程实践

1. 从「工具调用」到「Code Mode」:一场正在发生的 Agent 范式转移过去一年多,我一直在做 AI Agent 相关的落地项目,从最早的 Function Calling 到后来的多工具编排,踩过的坑可以说能写满一个笔记本。但最近半年,一个明…

2026/10/14 23:41:09

PS5串流全攻略:从局域网配置到延迟调优,让主机走出客厅

1. 项目设想:一台 PS5,凭什么只能待在客厅1.1 当游戏机被电视“独占”时的痛点很多有 PS5 的家庭都会遇到类似的尴尬:主机明明摆在客厅,电视却不一定永远属于你。家里人要看综艺、小孩要上网课、长辈要投屏刷剧,这时候…

2026/10/14 23:41:09

零基础80天PMP备考复盘:逆向思维与笨方法如何拿下3A

拿到成绩那天,屏幕上跳出三个 Above Target,我心里其实没有太多意外。并不是我多有把握,而是这80天里每一天做了什么、做得对不对,我自己清楚得很。这篇不是来炫耀分数的,是想把一套“零基础 80天 笨方法”的组合拳完…

2026/10/14 23:41:09

Libtorch部署实战:从模型导出到C++高性能推理的完整指南

在深度学习落地这条路上,我折腾过不少推理框架,但最后上生产环境时,Libtorch是我最常用的选择之一。很多人觉得Libtorch部署是个“高大上”的事,其实说白了就是把PyTorch训练好的模型,从Python环境搬到C环境里跑起来。…

2026/10/14 23:41:09

个人AI Agent架构实战:记忆层、权限机制与跨应用编排设计

你可能见过不少号称“AI 助理”的产品,打开一看就是个问答盒子,能陪你聊天、能写点文案,但真要让它“替我办成一件事”,它既记不住你上周交代过的偏好,也不敢碰你的日历、邮件和通讯录。这种产品本质上还是聊天界面&am…

2026/10/14 23:36:07

Redis从安装到实战:配置、数据结构与缓存问题排查全攻略

先问自己一个问题:有没有遇到过这样的场景——线上接口突然变慢,数据库CPU飙高,用户反馈页面打不开,重启服务后过几分钟又被打爆;或者明明是同一个数据,每次请求都要去数据库查一遍,白白浪费了连…

2026/10/14 11:31:03

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/14 17:41:07

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/14 2:32:55

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑