尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python爬虫实战:抓取豆瓣Top250并完成数据清洗与可视化分析
搞爬虫和数据这块Top250榜单是个绕不开的经典练手素材。它数据量不大不小正好够你完整走一遍“请求页面 → 解析内容 → 清洗存储 → 分析可视化”的流程而且结果天然带有话题性谁看了都想知道这些高分电影到底分布在哪几年、哪个国家最能产神作。这篇文章我会把手写的爬虫逻辑、反爬细节、数据清洗和统计分析全部掰开揉碎讲清楚完整代码可以直接抄走复现适合刚学完Python基础、想用真实数据做第一个完整项目的朋友。1. 项目拆解为什么选Top250当练手数据1.1 这个数据集到底长什么样Top250榜单本身结构非常规整每页固定展示25部电影总共10页。每部电影的信息卡片里有排名、电影名中文名和原名分开显示、导演阵容、主演阵容、上映年份、制片国家/地区、类型、评分、评价人数有些条目还附带一段短评。这些字段对爬虫来说非常友好因为它们全部嵌在静态HTML里不需要响应式渲染也不涉及动态加载直接拿HTTP请求就能拿全。我当时为什么挑这个数据集而不是去爬其他网站核心原因是它的字段足够丰富又不至于复杂到失控。导演、年份、国家、类型、评分、评价人数这些字段拉下来之后可以做时间维度的分布分析可以做国家维度的产量对比可以做类型和评分的相关性论证。一个数据集能支撑四五种不同角度的分析这对练手项目来说价值很高。另一个原因是榜单的排名本身带有明确的语义——“Top250”意味着你可以围绕“什么样的电影能进这个榜单”做一些统计洞察而不只是单纯展示数据。1.2 技术选型requests BeautifulSoup 还是 Scrapy爬虫框架选择上很多人一上来就上Scrapy其实这个项目用不着。Top250只有10个页面总数250条数据单线程串行请求也就是几秒钟到十几秒钟的事引入Scrapy的下载中间件、Item Pipeline那些机制反而把简单问题复杂化了。我最终用的是 requests 请求 BeautifulSoup 解析加上 pandas 做清洗和统计这个组合足够应付这个规模的项目而且每一步都能看得见摸得着适合理解爬虫的完整链路。表格对比一下三种方案的取舍方案优点缺点适合场景requests BeautifulSoup轻量、直观、调试方便手动处理翻页和反爬单站点、百级数据量、入门学习Scrapy并发效率高、工程化结构上手曲线陡、重框架配置多站点、千万级数据、分布式需求Selenium / Playwright可处理JS渲染占资源、速度慢、略显笨重需要模拟登录或动态页面的场景我只能说选型这件事不要为了用框架而用框架。数据规模决定技术方案250条数据用requests是最合理的选择代码量小出问题也容易排查。1.3 字段设计决定分析上限爬虫阶段设计好数据字段后面分析时能省掉一半力气。我设计的字段如下字段名示例值说明rank1榜单排名title肖申克的救赎中文电影名original_titleThe Shawshank Redemption电影原名director弗兰克·德拉邦特导演actors蒂姆·罗宾斯/摩根·弗里曼主演year1994上映年份country美国制片国家genre犯罪/剧情类型rating9.7评分votes2898313评价人数quote希望让人自由经典台词这里有一个细节页面上的导演、演员、年份、国家、类型是混在一行文字里的比如“导演弗兰克·德拉邦特 主演蒂姆·罗宾斯 / 摩根·弗里曼 / ... 1994 / 美国 / 犯罪 剧情”解析时要做一次规整的字符串切分。如果只图省事把这一整行存成一个字段后面分析年份分布和国家分布时就会很痛苦还得回炉重造。所以爬虫阶段就顺手把每个信息拆到独立字段这是最值得花时间的部分。2. 反爬与解析动手前必须搞懂的4个细节2.1 User-Agent你的爬虫身份证第一次写爬虫时我直接用裸requests请求结果返回的页面里只有一片空内容状态码倒是200细看才发现被服务器识别成非浏览器访问返回了一个安全校验页面。问题就出在默认的User-Agent上Python发出去的请求头写着python-requests/2.x.x服务器一眼就看穿了。解决办法是把请求头伪装成普通浏览器。直接在请求里加上headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Accept-Language: zh-CN,zh;q0.9, Referer: https://movie.douban.com/top250 }说一下为什么还要带Accept-Language和Referer。Accept-Language告知服务器你期望中文内容避免返回乱码或者英文版Referer则是表明你是从榜单页面跳转过来的更贴近真实用户的行为链。实际测试下来带上这三个头之后请求成功率显著提升基本不会触发拦截页面。2.2 翻页参数认清start和filterTop250的翻页规则是?start0filterstart每页递增25也就是0、25、50、75一直到225。filter这个参数保持为空就行。这个翻页方式比那种带pageNum的翻页要少一层计算直接循环生成URL列表即可。urls [fhttps://movie.douban.com/top250?start{page * 25}filter for page in range(10)]这里有个排错经验不要想当然地把start当成页码传1、2、3那样抓回来的全是第一页。我第一次踩这个坑的时候就在想为什么循环10遍数据都一样后来打印了URL才反应过来start才是偏移量它代表的是从第几条记录开始展示。这个细节对做爬虫的人很基础但初学者特别容易忽略。2.3 请求节奏睡眠时间不是越小越好爬取策略上最关键的一条就是控制请求频率。Top250只有10页就算每页间隔1秒总共也就10秒完全不值得为了赶那几秒去激怒对方的防爬策略。我当时用的间隔是1到2秒的随机值import time import random time.sleep(random.uniform(1, 2))为什么要设置随机间隔而不是固定时间如果每隔固定1秒发送请求这个频率模式其实很容易被识别出来因为真人浏览不会像机器那么整齐。随机化能让请求时间序列更接近真实操作。另一个容易被忽略的点是尽量不要并发请求这个项目数据量小并发只会提高被封风险没有任何收益。2.4 解析核心CSS选择器怎么定位页面结构里每部电影的完整信息都在ol.grid_view里面的li标签下。用BeautifulSoup解析时我习惯用CSS选择器比逐层find更加易读。from bs4 import BeautifulSoup soup BeautifulSoup(html, html.parser) movie_items soup.select(ol.grid_view li)每一条li里需要提取的内容大致是item movie_item.select_one(.item) rank item.select_one(.pic em).get_text() title_node item.select_one(.title) rating item.select_one(.rating_num).get_text() quote_node item.select_one(.quote .inq)这中间有两个容易踩坑的细节。第一个是片名的处理。一个li里可能有两个.title第一个是中文名第二个是原名。用select_one(.title)只能拿中文名要拿原片名得用select(.title)取第二个而且有的电影没有原名这种情况要加个判断能取到就取取不到就填空字符串。第二个是评价人数的提取。页面上显示的是“2898313人评价”数字在span里且带propertyv:votes属性但这个数字是纯数字的解析出来要自己加上单位存纯数字后面分析时直接转int就行。3. 手把手实操从请求到可视化的完整代码3.1 环境准备与依赖安装这个项目用到的第三方库其实不多核心就四个requests负责请求、beautifulsoup4负责解析、pandas负责数据清洗和统计、matplotlib负责出图。安装命令pip install requests beautifulsoup4 pandas matplotlib版本建议不用锁太死2024年以后的新版本基本都能兼容。Python本身建议3.9以上现在的pandas和matplotlib新版本对旧版Python已经不太友好了。有虚拟环境习惯的话用venv或conda隔离一下最好。3.2 爬虫核心代码10页数据轻松入库写完整请求和解析逻辑前先定义一个解析单页电影列表的函数。为了后面异常排查方便我把解析逻辑拆成独立的函数让每个函数只干一件事这也方便你在自己机器上调试和单测。import requests import time import random import csv from bs4 import BeautifulSoup HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Accept-Language: zh-CN,zh;q0.9, Referer: https://movie.douban.com/top250 } def fetch_page(url): response requests.get(url, headersHEADERS, timeout10) response.raise_for_status() response.encoding utf-8 return response.text设置response.encoding utf-8这一步很关键。虽然服务器返回的Content-Type里事实上有charsetutf-8但requests有时候会认为编码是ISO-8859-1导致中文乱码。强行指定编码省掉这个隐患。再来是解析函数def parse_page(html): soup BeautifulSoup(html, html.parser) movies [] for item in soup.select(ol.grid_view li): try: rank item.select_one(.pic em).get_text().strip() title item.select_one(.title).get_text().strip() title_nodes item.select(.title) original_title title_nodes[1].get_text().strip() if len(title_nodes) 1 else info_line item.select_one(.bd p).get_text().strip() # 比如: 导演: 弗兰克·德拉邦特 主演: 蒂姆·罗宾斯 / 摩根·弗里曼 / ... 1994 / 美国 / 犯罪 剧情 director info_line.split(导演: )[1].split( 主演: )[0].strip() actors_part info_line.split( 主演: )[1].split( / )[0].strip() meta_part info_line.split( 1994)[-1].strip() # 这里需要小心 year info_line.split( / )[0][-4:] if / in info_line else country 未知 genre 未知 rating item.select_one(.rating_num).get_text().strip() votes item.select_one(span[propertyv:votes]).get_text().strip() quote_node item.select_one(.quote .inq) quote quote_node.get_text().strip() if quote_node else movies.append({ rank: rank, title: title, original_title: original_title, director: director, actors: actors_part, year: year, country: country, genre: genre, rating: rating, votes: votes, quote: quote }) except Exception as e: print(f解析出错: {e}, 跳过该条) continue return movies这里我对年份、国家、类型的解析写得很粗糙是因为真实页面里的info_line结构是固定的但字符串格式肉眼看起来比较乱。在实际项目中我会把年份、国家、类型用正则一次性提取而不是靠空格索引硬切。推荐的做法是用正则import re year_match re.search(r(\d{4})(? / ), info_line) year year_match.group(1) if year_match else country_and_genre re.search(r\d{4} / (.), info_line) if country_and_genre: parts country_and_genre.group(1).split( / ) country parts[0].strip() genre / .join(parts[1:]).strip().replace( , /)正则的匹配规则要配合实际页面来调试不同时期网站结构会微调这个到第4章问题里还会细讲。然后主流程的抓取与存储def main(): all_movies [] for page in range(10): url fhttps://movie.douban.com/top250?start{page * 25}filter print(f正在抓取第 {page 1} 页) html fetch_page(url) movies parse_page(html) all_movies.extend(movies) time.sleep(random.uniform(1, 2)) with open(douban_top250.csv, w, encodingutf-8-sig, newline) as f: writer csv.DictWriter(f, fieldnames[rank, title, original_title, director, actors, year, country, genre, rating, votes, quote]) writer.writeheader() writer.writerows(all_movies) print(f抓取完成共 {len(all_movies)} 条)注意encodingutf-8-sig加一个BOM头这样用Excel打开CSV时中文不会乱码。如果只给自己用pandas读用utf-8也行但考虑到可能要发给别人看带上sig是我个人的习惯。3.3 数据加载与清洗脏数据在这步终结CSV保存好之后就得交给pandas做二次处理了。读进来之后先看看数据类型和缺失情况import pandas as pd df pd.read_csv(douban_top250.csv) print(df.info()) print(df.head())base_data这步通常会发现两个典型问题year字段是字符串类型后面画图时需要转成数值votes是纯数字的字符串同样需要转int。转换前先看看有没有脏数据混在里面df[year] pd.to_numeric(df[year], errorscoerce) df[votes] pd.to_numeric(df[votes], errorscoerce) df[rating] pd.to_numeric(df[rating], errorscoerce) df df.dropna(subset[year, rating, votes])errorscoerce会让无法转换的值变成NaN之后再丢到缺失行这样比直接强转会安全很多。转换完之后再验证一下数据量print(df.shape) # 正常情况是 (250, 11)如果行数低于250对应着爬取阶段有解析失败或者重名的脏数据需要回头检查。为了后续分析更顺手我通常还会额外生成两个辅助字段一个是decade表示年代区间比如1994年属于“90年代”另一个是把actors字段按斜杠拆开分析演员出现频次。这些衍生字段在画图时会很方便。df[decade] (df[year] // 10 * 10).astype(str) 年代 df[country_main] df[country].str.split( / ).str[0]这里把多个制片国家的电影只取第一个国家作为主国家是为了统计方便。如果你关心合拍片的具体国家分布也可以把country字段展开成多行但那样会打乱排名记录的唯一性我建议还是用主国家来做聚合。3.4 分布分析评分、年代与国家数据清洗完直接上pandas的groupby做统计。先说评分分布看250部电影的分值集中在什么区间bins [0, 8.0, 8.5, 9.0, 9.5, 10.0] labels [8-8.5, 8.5-9, 9-9.5, 9.5-10] df[rating_group] pd.cut(df[rating], binsbins, labelslabels) rating_dist df[rating_group].value_counts().sort_index() print(rating_dist)再分析年代分布看哪十年贡献的经典最多decade_count df[decade].value_counts().sort_index() print(decade_count)一般来说这个分布会让你看到两个明显高峰一个是90年代一个是2010年代初期。国产片观众应该能明显感觉到90年代到2000年代初期是整个榜单里的黄金时期近几年的电影进入Top250的门槛明显变高了很多经典老片的位置很难被挤掉。国家分布可以直接计频次country_count df[country_main].value_counts().head(10) print(country_count)如果数据抓得干净美国片的数量一定是断层式领先的然后是日本、英国、法国等地。这个结果本身很直观但我们要的不只是这个数而是要通过数据看出“不同国家上榜电影的平均评分有没有差异”这就要用到groupby聚合country_rating df.groupby(country_main)[rating].mean().sort_values(ascendingFalse).head(10) print(country_rating)评分的国家对比有时能看出一些有趣的现象比如某些国家虽然上榜数量不多但一旦上榜评分中位数特别高说明这个国家的电影整体质量门槛控制得很好。3.5 可视化让数据自己讲故事统计结果终究是数字给人看肯定要出图。我用matplotlib画了三张图评分分布直方图、年代产量柱状图、国家Top10横向条形图。给一套可以直接改的参数import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, PingFang SC] plt.rcParams[axes.unicode_minus] False第一行设置中文字体Windows用户写SimHeimacOS用户写PingFang SC。第二行解决负号显示成方块的问题。评分分布直方图plt.figure(figsize(10, 6)) plt.hist(df[rating], bins20, color#5c9bd1, edgecolorwhite) plt.title(Top250电影评分分布) plt.xlabel(评分) plt.ylabel(电影数量) plt.grid(axisy, alpha0.3) plt.show()年代产量柱状图decade_count.plot(kindbar, figsize(10, 6), color#8fb8de) plt.title(各年代入榜电影数量) plt.xlabel(年代) plt.ylabel(数量) plt.xticks(rotation45) plt.show()国家Top10横向条形图country_count.head(10).sort_values().plot(kindbarh, figsize(10, 6), color#a5c8a0) plt.title(入榜电影数量Top10国家) plt.xlabel(数量) plt.ylabel(国家) plt.tight_layout() plt.show()这三张图做完整个项目的基本交付物就齐了一份CSV数据、一个分析结论页面、三张可视化配图。如果你想更进一步还可以用seaborn做评分和评价人数的散点图看两者是否存在正相关关系。但从练手项目的角度看三张核心图已经足够说明问题了。4. 爬虫实战避坑高频报错排查与解决实录4.1 403状态码被服务器识别后的求生指南我早期跑这个爬虫最常碰到的就是403。状态码403表示服务器理解请求但拒绝执行一般是请求头伪装不到位。排查顺序是这样的先确认User-Agent是否完整且贴近真实浏览器。确认是否用了默认的Python UA。确认请求频率是不是太快比如一次性连发10个请求没停。确认是否缺少Referer头。按这个顺序排下来大概率能解决九成的问题。如果还是403那就加一层cookie先在浏览器里打开一个榜单页把请求头里的Cookie复制出来放进headers里。不过这个操作属于临时偷懒方案cookie一般有有效期过段时间就得换不建议长期依赖。4.2 解析结果为空先打印再定位BeautifulSoup选择器写错时最典型的表现是解析出来的列表长度为零。有的新手这时候会反复检查选择器语法但实际上最有效的方法是先打印一段HTML肉眼确认结构。html fetch_page(https://movie.douban.com/top250?start0filter) print(html[:5000])打印出来看看li标签到底长什么样子再对照着写选择器比盲目试错高效得多。豆瓣这个页面结构算是很稳定的但偶尔调整过样式类名比如早期是.grid_view后来微调过缩进和嵌套层级。版本更新后旧选择器失效了通过打印HTML能快速定位节点是否还存在。4.3 评价人数里的“万”字陷阱页面上有些电影的评价人数会显示成“2898313”这种纯数字但也有显示成“146.2万”之类的带单位写法吗在Top250里其实不分页面的逻辑但既然做分析就要考虑万一数据源格式变化。我在做数据清洗时发现过类似问题如果爬下来的votes字段里混入了“万”做单位的数据直接用pd.to_numeric会变成NaN。对应办法就是写个转换函数def parse_votes(value): if isinstance(value, str) and 万 in value: return float(value.replace(万, )) * 10000 return float(value) df[votes] df[votes].apply(parse_votes)这个坑在真实项目中相当常见不只是豆瓣很多评分网站的数值单位都会搞这种“万”“亿”化处理。提前做好防御性处理后面分析时就不会手忙脚乱。4.4 网站改版导致的解析失效爬虫圈子有一句话叫做“爬虫最怕的不是反爬是网站改版”。Top250这个页面总体稳定但也不排除某天结构微调。我的建议是不要把爬虫selector写得太死尽量用稳定的属性选择器而不是索引位置。比如用select_one(span[propertyv:votes])就比用select(span)再配合位置索引要稳健得多。如果一个节点有明确的属性标识优先用属性定位这样改版时不容易全盘崩溃。如果你想为自己的爬虫上一份保险就把解析做成独立函数并写一个简单的单元测试针对一页固定HTML验证字段是否都能提取到。这样网站一旦变化跑一次测试就知道哪里挂了。4.5 常见问题速查表问题现象可能原因解决思路请求返回200但解析不到数据被重定向到验证页检查UA和Cookie打印HTML确认中文乱码编码识别错误手动设置response.encoding utf-8CSV用Excel打开乱码缺少BOM头用utf-8-sig编码写入年份解析出来是空字符串正则写错或页面结构变化打印info_line原文逐步调试数据量不足250条部分条目解析异常被跳过在解析函数里打印异常并检查是否有整段结构变动5. 数据会说话Top250里的观影趋势与趣味结论5.1 从数据看黄金年代当年我跑完数据看到年代分布图时第一个直观感受就是90年代真的是封神年代。无论哪个国家的榜单90年代都贡献了大量经典电影。这个现象背后的逻辑其实很有意思一方面90年代数字特效还没完全占领工业化生产导演更依赖实拍、叙事、人物塑造这些基本功另一方面录像带和影碟市场的成熟让电影的商业回收期缩短创作者的尝试空间更大。数据从这个角度去解读就不只是堆砌柱状图了。5.2 制片国家的马太效应国家分布这块数据分析里有个值得注意的角度上榜数量前几名是国家梯队但平均评分最高的并非第一名。出现这种情况是因为部分国家靠少数精品上榜走的是质量路线。把“数量”和“均分”两个维度放在一个表里对比国家上榜数量平均评分美国1008.7左右日本30左右8.6左右英国20左右8.5左右法国10左右8.6左右从这个表能引出的结论是不同国家的电影工业生态不同有的国家高产高质有的国家小而美。做数据分析最忌讳只看单一指标交叉对比才会产生洞察。5.3 导演与类型那些隐藏的规律把director字段单独聚合你会发现上榜导演的重复率很高。某些导演一个人就贡献了三五部Top250这在国际影坛非常罕见。数据上透出的规律是能多次上榜的导演通常有着极强的个人风格标签作品在豆瓣社区的评价往往呈现高开高走的态势。类型方面剧情、犯罪、爱情这些偏叙事驱动的类型占比明显高于奇幻和动作。原因并不复杂评分体系本质上反映的是观众的情感共鸣度故事内核比视觉奇观更容易维持长期口碑。这个结论在给数据分析做总结时是可以拿出来单独讲一讲的因为它其实一定程度上反映了流量电影和口碑电影的评价逻辑差异。5.4 评分与评价人数的相关性如果你把rating和votes两列做一个相关系数计算print(df[rating].corr(df[votes]))大概率得到的相关系数只有0.2到0.3左右属于弱相关。这说明高分的电影评价人数不见得最多反过来评价人数爆棚的电影也不一定评分最高。顺着这个角度想一下很多商业大片的评价人数特别夸张但分值可能并没有进入9分俱乐部。这组数据能打破“越多人看好质量越好”的直觉在分享项目时是个不错的观察点。写在最后的一些经验这个项目做完之后我自己最大的感受是爬虫的价值不在爬到多少数据而在你拿到数据之后能不能做出让人信服的分析。250条数据看起来很少但它足够支撑你完成一次完整的“采集—清洗—分析—可视化”闭环而这个过程里每一步都有各自要避开的坑。如果你照着上面的代码跑通了我建议你下一步做两件事一是把榜单换成其他分类比如国产高分榜或者冷门佳片榜练练selector的迁移能力二是把静态数据存到SQLite里试试用SQL做分析为后续更复杂的数据项目打底。爬虫这行简单练习越扎实后面遇到奇葩网站心态越稳。
RELATED

相关推荐

国产大模型编程能力横评:GLM-5.1与Qwen-3.6首次反超海外标杆

国产大模型编程能力横评:GLM-5.1与Qwen-3.6首次反超海外标杆

过去半年我一直在做一件事:把市面上主流的大模型拉回同一个测试台,用同一批编程任务反复复试。编程能力已经成了大模型最硬核的试金石——代码生成、缺陷修复、工程理解,每一项都比聊天对话更难伪装。这次横评的主角是国产模型的两位代表 GLM…

📅 2026/10/21 18:57:43
零基础转行AI工程师:从后端开发到大模型应用的实战路径

零基础转行AI工程师:从后端开发到大模型应用的实战路径

1. 转型前夜:我一度以为大模型只属于数学天才我到现在还记得去年春天那个晚上,我在出租屋里盯着屏幕上那个开源模型跑出来的第一句对话发呆。那句话写得乱七八糟,错别字都有,但我整个人是颤的——不是因为它多聪明,而是…

📅 2026/10/21 18:57:43
树莓派边缘计算部署:轻量化DeepSeek模型推理实战指南

树莓派边缘计算部署:轻量化DeepSeek模型推理实战指南

简介:这份PDF资源面向希望在边缘设备上落地深度学习模型的开发者与研究人员,聚焦树莓派运行轻量化DeepSeek的完整部署方案。内容从边缘计算兴起背景与树莓派软硬件特性切入,系统讲解DeepSeek模型架构、剪枝量化与知识蒸馏等轻量化技术&#x…

📅 2026/10/21 18:57:43
MORE NEWS

更多资讯

📰

R语言常用函数汇总:数学统计、概率与字符处理全覆盖

简介:面向数据分析和统计学习者的R语言常用函数速查手册,以PDF格式整理,适合刚接触R语言、备考数据分析岗位,或在建模前需要快速检索函数用法的读者。内容按数学、统计、概率、字符处理与其他实用函数五类系统展开,覆盖…

📰

NAACL论文速览:大模型评测、RAG与可复现性的实践启示

论文放榜那几天,圈子里讨论最多的不是某篇模型涨了多少分,反而是“这个东西到底能不能复现”。我把某中心这30余篇NAACL论文从头到尾翻了一遍,发现这批工作有一个共同气质:与其堆一个更大的模型,不如把评测、数据、训练…

📰

电动汽车电机驱动控制系统核心技术与工程落地指南

简介:本资源是一份聚焦电动汽车电机驱动控制系统前沿发展的专业技术分析报告,面向新能源汽车领域工程师、高校车辆工程/电气自动化专业师生及行业研究人员,旨在系统梳理当前技术瓶颈与未来演进路径。报告深入剖析直流、交流感应、永磁同步及开…

📰

LiteLLM:一个统一多模型API调用的开源网关方案

1. LiteLLM 到底解决什么问题:一个 API 网关的诞生逻辑做 AI 应用做到某个阶段,你一定会遇到这样一个问题:代码里的模型调用五花八门,某家用 OpenAI 的格式,某家用 Anthropic 的格式,本地跑的去连 Ollama&a…

📰

从“ArtCraft”看手作创作:艺术灵感与工艺实现的缝合点

1. 拆解ArtCraft:艺术与手工的“缝合点”在哪我第一次看到“ArtCraft”这个词,第一反应是它像一个调色盘被摔碎后重新拼接的过程。Art是艺术,Craft是工艺,两者放在一起,既不是让艺术屈尊去迁就手工,也不是让…

📰

Java团队用LangChain4j打造医疗智能客服:多轮对话与RAG实战

做医疗智能客服这个项目的时候,我最大的感受是:AI框架的选型真的可以决定一个Java团队的开发节奏。我们内部代号叫"硅谷小智",说白了就是一个面向患者问诊前、问诊后的智能接待机器人,要能回答科室导诊、就诊流程、检查…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬