1. 这个项目到底在做什么:不只是爬虫,而是一条完整的数据处理流水线
先交代一下背景。我在做爬虫技术调研的时候,发现很多教程只讲“怎么把网页抓下来”,然后就没有然后了。但实际业务里,抓取永远只是最前面的一环。真正有价值的东西,在数据清洗、内容解读和可视化展示这些后续步骤里。所以当我看到“爬取某教育领域知名博主微博并进行情感分析与词云可视化”这个标题时,觉得特别典型——它不是一个单点技术演示,而是一条从数据采集到数据呈现的完整流水线。
这个项目实际做的事情可以拆成三层:
- 采集层:用Python爬虫抓取该名人的微博内容,包括正文、发布时间、互动数据(转发、评论、点赞)等字段。
- 分析层:对微博文本做情感倾向判断,区分正面、负面和中性情绪,统计整体情感分布。
- 呈现层:用词云图把高频关键词可视化,让你一眼看出这个人最近在聊什么话题。
这里有个容易被忽略的点:很多人以为“情感分析”就是调个现成的库,跑一下出个分数就完事。其实不是的,尤其对于微博这种短文本、网络用语密集、口语化严重的语料,直接套模型会得到一堆莫名其妙的结论。比如“牛”这个词,在传统词典里是名词,但在微博语境里是强烈的正向评价;再比如“醉了我”这种表达,字面看是负面,实际可能是调侃。这些都是这个项目里需要认真处理的细节。
先说清楚边界:本项目仅用于技术研究和个人学习,展示的是公开数据和通用技术路线。针对微博平台,我们只采集公开页面数据、控制请求频率、不涉及用户隐私字段,这也是任何爬虫项目都应该守住的底线。下面的内容里,我会把每一步怎么做、为什么这么做、会遇到什么坑、怎么排查,从头到尾说道说道。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 准备工作:环境搭建和工具选型的真实思考
2.1 基础环境:别在环境配置上浪费时间
这个项目所需的第三方库不多,但每一个都有讲究。先看一张我实际使用的环境清单:
| 库名 | 版本建议 | 用途 |
|---|---|---|
| requests | >=2.25 | HTTP请求库,负责抓取页面和接口数据 |
| beautifulsoup4 | >=4.9 | 解析HTML,提取微博正文和元数据 |
| jieba | >=0.42 | 中文分词,把长文本切成词 |
| snownlp | >=0.12.3 | 中文情感分析,输出情感倾向和概率 |
| wordcloud | >=1.8 | 词云图生成 |
| matplotlib | >=3.3 | 绘图展示,配合wordcloud输出图片 |
| pandas | >=1.3 | 数据清洗和结构化存储 |
| openpyxl | >=3.0 | 把结果导出成Excel |
安装方式很简单,建议用venv或conda建一个独立环境,避免污染全局Python环境:
bash复制python -m venv weibo_analysis
source weibo_analysis/bin/activate # Windows下执行 weibo_analysis\Scripts\activate
pip install requests beautifulsoup4 jieba snownlp wordcloud matplotlib pandas openpyxl
这里多说一句版本选择的原因。wordcloud这个库有一个隐形的坑——它依赖numpy和Pillow,如果你直接用pip安装,可能会拉到最新版numpy,导致某些旧版本wordcloud报编译错误。所以我的习惯是先装numpy和Pillow的稳定版,再装wordcloud,顺序颠倒会出现莫名其妙的“module 'numpy' has no attribute 'int'”之类的报错。这个坑在新版numpy(1.24+)移除了np.int之后尤其常见,如果你遇到了,基本就是版本不兼容。
2.2 为什么要用requests而不是scrapy:这个体量的项目不需要重武器
市面上爬虫框架很多,scrapy功能强大、支持分布式、自带调度器和去重机制,看起来是“正规军”。但在这个项目里我用的是requests+BeautifulSoup的轻量组合,原因有三:
- 目标页面单一:只需要爬一个人的微博列表,不需要维护复杂的爬虫工程结构。
- 不需要高并发:微博对频繁请求有封禁策略,我们反而要控制请求速度,scrapy的并发优势在这里是劣势。
- 调试方便:requests的请求-响应模型非常直观,出错了可以直接在IPython里逐行排查,scrapy的异步链路在小项目里反而增加排查成本。
小项目的核心原则是:能用简单方案解决的,绝不上复杂的架构。这不是技术能力的问题,而是工程效率的问题。你写30行requests代码就能跑通的事,没必要写300行scrapy脚手架。
2.3 爬虫合规性和平台边界:动手之前先想清楚这几个问题
爬虫项目最怕的不是技术难,而是跑着跑着账号被封、甚至惹上法律问题。在写代码之前,有几条红线必须明确一下:
- 只爬公开数据:不需要登录即可访问的公开页面和公开API接口,属于合理使用范围;需要登录才能看到的内容,原则上不碰。
- 控制请求频率:设置合理的下载间隔,不要暴力抓取。正常人的浏览速度就是最好的参考标准。
- 遵守robots协议:先检查目标网站的robots.txt,尊重网站声明的不允许抓取的路径。
- 用途限制:抓下来的数据仅用于个人学习和技术研究,不用于商业用途,不批量存储转发。
这个项目里,我设置了每次请求间隔2-3秒,每次抓取页数不超过20页。这样既拿到了足够的样本量,又不会给目标服务器造成压力。记住一个原则:爬虫的本质是模拟普通用户的浏览行为,如果你的行为不是一个正常用户会做的,那就说明你的爬虫设计有问题。
3. 爬虫核心实现:从页面结构分析到数据落地
3.1 微博页面结构分析:先看懂目标再动手写代码
很多人一上来就写代码,结果被页面结构绕得晕头转向。我的习惯是先打开浏览器开发者工具,花15分钟看清楚目标页面的结构。这里以微博手机版为例子,因为它的HTML结构比PC版更规范,很适合教学场景。
第一步,访问某用户的主页(m.weibo.cn/u/用户ID),打开开发者工具(F12),切到Network面板,刷新页面。你会看到一个名为profile?uid=xxx的XHR请求,返回的是JSON格式数据。这就是我们要爬的核心接口。
接口地址大致如下(出于安全考虑不贴完整URL,只说结构规律):
code复制https://m.weibo.cn/api/container/getIndex?type=uid&value={用户ID}&containerid=107603{用户ID}
返回的JSON里,data.cards数组就是微博列表。每张card的mblog字段包含微博正文(text)、发布时间(created_at)、转发数(reposts_count)、评论数(comments_count)、点赞数(attitudes_count)等关键信息。这种接口式爬取比解析HTML要稳定得多,因为JSON格式不会因为网页改版而剧烈变化。
还有一个小技巧:翻页是通过since_id参数控制的。第一页返回的数据里会带一个since_id,把它拼到下一次请求的URL里,就能拿到第二页数据。这个参数在JSON的data.cardlistInfo.since_id里,找不到时返回空字符串说明翻到底了。
3.2 登录态和Headers伪装:为什么直接请求会拿不到数据
如果你拿着requests直接请求上面的接口,大概率会得到一个包含ok: -100的JSON,提示需要登录或者请求被拒绝。原因很简单:微博的反爬机制会校验请求头里的User-Agent、Referer和Cookie。
我第一次跑这个项目时就被这个问题卡住了,requests返回的页面内容是个验证码页面,一开始还以为是代码写错了。后来排查才发现是请求头的问题。解决方案是在请求头里带上一个合规的浏览器UA,并设置Referer为https://m.weibo.cn/。
如果你发现加了UA还是被拦截,那大概率是触发了频率限制。这时可以做一些规避措施,但注意方式要做到合理:比如在请求间加入time.sleep(2-3)随机延迟,或者使用代理IP池。不过对于个人学习项目,我的建议是老老实实加延时,别动代理IP的念头——那些IP池质量参差不齐,反而可能带你进入更严格的风控名单。
3.3 完整爬虫代码:分步实现一次能跑的版本
下面贴一段我当时跑通的简化版本代码,加了详细的注释。代码的逻辑是:请求接口 → 解析JSON → 提取字段 → 追加到CSV。分步看其实很简单:
python复制import requests
import time
import csv
import re
from bs4 import BeautifulSoup
# ── 1. 配置区 ──
USER_ID = "你的目标用户ID"
UA = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) "
"App
