尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python爬虫实战:批量抓取微博转评赞数据全流程解析
最近接了个小需求想分析某个领域里一批博主的传播情况。最直接的思路就是看微博的转评赞也就是转发数、评论数、点赞数这组核心互动指标。手动一条条去点开详情页看几十条还能忍几百上千条下来绝对让人崩溃。用 Python 爬虫批量抓取微博转评赞 data是这类轻量级数据采集里非常典型的需求新手上手快老手拿来当工具脚本也很顺手。我这次的目标很简单给定一组微博链接或博主主页把每一条微博的正文、发布时间、转发数、评论数、点赞数抓下来存成结构化表格方便后续做数据分析或趋势判断。整个项目实施下来最关键的点其实不在代码本身而在请求接口的选型、登录态的处理和反爬规避策略上。下面把这套方案完整拆开讲从思路到落地再到遇到的问题和排查方法都给捋清楚。1. 方案选型为什么放弃页面解析直接走移动端接口很多人第一次写微博爬虫脑子里冒出来的第一个方案就是请求网页版微博的页面然后用 BeautifulSoup 或者 XPath 去解析 HTML。这个方案不是完全跑不通但真的不推荐作为首选。网页版微博的页面结构非常复杂正文、时间、转评赞分布在不同的 DOM 节点里而且不同时间段的页面结构还不一样。加上微博前端有大量的异步渲染你直接请求到的 HTML 里部分数据根本不在里面而是通过后续的 AJAX 请求加载出来的。这就意味着你要么得分析一堆 JS 调用要么就得借助无头浏览器比如 Selenium 或 Playwright去模拟真实浏览成本一下就上去了。移动端接口的方案完全绕开了这些坑。微博有一个面向移动端的接口返回的是结构化 JSON 数据字段按规则排列解析起来非常轻松。这个接口的路径和参数相对固定不需要模拟复杂的浏览器环境直接用 requests 就能拿到干净的数据。用移动端接口有几个非常明显的好处数据量小响应速度快。接口返回的是纯数据不像 HTML 页面那样带着一堆标签和无关脚本。结构稳定。JSON 字段名含义清晰转评赞数据、正文、发布时间都可以准确定位。反爬压力小。相比网页端频繁的验证码和登录墙移动端接口只要带上有效的 Cookie 并控制请求频率正常使用问题不大。当然这个方案的前提是我们抓的是公开可见的微博数据。涉及隐私、非公开的内容抓取是既不合法也不合理的行为。整个项目我只处理公开账号的公开微博信息并且严格控制请求频率不给目标服务器造成额外压力这个边界大家做的时候一定要有数。2. 动手前准备环境搭建、登录态获取与合规边界2.1 基础环境与依赖库这次项目用 Python 3 实现依赖库保持精简尽量少引入重量级模块。核心就三个requests负责发 HTTP 请求拿接口数据。jsonPython 标准库解析接口返回的 JSON。pandas用来做数据清洗和表格输出方便后续分析。如果你只是想要最低限度的实现甚至可以不装 pandas直接用标准库里的csv模块就能写文件。不过用 pandas 操作数据更顺手后续做去重、排序、筛选都方便我建议还是装一个。2.2 登录态 Cookie 的处理思路微博的接口特别是需要查看完整信息的接口通常要求登录态。但这不代表你必须得用账号密码去模拟登录那个过程涉及加密算法分析和验证码处理对新手来说门槛太高也容易惹上不必要的麻烦。最简单的方式是从你自己的浏览器里复制 Cookie 出来用。操作路径用浏览器登录微博网页版或者移动版打开开发者工具F12随便选择一个网络请求在请求头Request Headers里找到Cookie字段整段复制出来贴到脚本的配置变量里。这里有几个细节要注意Cookie 有效期有限。通常是几天到几周不等过期了请求就会返回登录失效或者数据异常。Cookie 不要到处贴也不要提交到公开的代码仓库里。这相当于是你账号的通行凭证泄露了别人可以冒用你的身份做各种操作。我一般把 Cookie 放在独立的配置文件里用config.py或者.env文件单独存放并加入.gitignore列表。如果某个接口必须登录才能看数据而你又不想用自己的账号可以专门注册一个小号来取 Cookie用完即弃风险隔离。2.3 请求头和请求参数的伪装接口请求时User-Agent是基础中的基础。默认的 Pythonrequests库的 UA 是一串很明显的标识比如python-requests/2.31.0服务器看到这种 UA 很容易识别为爬虫并直接拒绝服务。我习惯伪装成移动端的正常浏览器 UA整体请求头模仿真实用户的行为模式。我实际用的是headers { User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1, Accept: application/json, text/plain, */*, Accept-Language: zh-CN,zh;q0.9, Referer: https://m.weibo.cn/, X-Requested-With: XMLHttpRequest, Cookie: cookie_value }Referer设置为移动端首页X-Requested-With设置为XMLHttpRequest这两个值配合 UA 一起用请求看起来更像一个正常的移动端用户在浏览页面。这里还要强调一句头伪装的目的只是让请求看起来像正常用户绝对不是为了绕过什么安全机制去搞破坏。爬取公开数据的初衷是为了分析和学习不该用于任何干扰平台正常运营的行为。2.4 合规边界先想清楚做爬虫前先把合规边界划清楚省得后面被动。这次项目我给自己定了三条规矩只抓取公开账号的公开微博数据不碰私密内容、不碰用户隐私信息。严格控制请求频率每次请求之间加延时宁可慢一点绝不给服务器添乱。数据仅用于个人学习和分析不用于商业用途不对外公开原始数据集。这三条是底线。实际操作中我还会额外避免在短时间内大量请求同一个接口尽量把请求打散模拟人工浏览节奏。这样既保护了平台的服务稳定性也减少了自己 IP 被限制的风险。3. 核心代码实现从单条微博到批量抓取3.1 数据结构与字段解析移动端微博接口返回的数据是标准 JSON。要抓的核心字段主要通过mblog这个节点下的内容来获取。我以一条微博的详情接口为例它长这样import requests import json cookie_value 你的cookie headers { ... 上面提到的请求头 ... } weibo_id 5042085800575602 url fhttps://m.weibo.cn/statuses/show?id{weibo_id} resp requests.get(url, headersheaders, timeout10) data resp.json() mblog data[data][mblog] print(mblog[raw_text]) # 微博正文 print(mblog[created_at]) # 发布时间 print(mblog[reposts_count]) # 转发数 print(mblog[comments_count]) # 评论数 print(mblog[attitudes_count]) # 点赞数这几个字段是核心中的核心raw_text微博的正文内容。注意如果微博里有长图、链接、话题、用户正文里会带一些特殊标记后面清洗的时候需要处理。created_at发布时间格式类似于Tue Dec 12 10:30:00 0800 2024不是标准的 ISO 时间格式后面处理的时候需要转换一下。reposts_count转发数整数类型。comments_count评论数整数类型。attitudes_count点赞数。这个字段在不同的接口版本里名字可能有差异有的地方叫like_count有的叫attitudes_count我这次用的是移动端接口就是attitudes_count。除了这些核心字段mblog里还有id字符串形式的微博ID后面抓评论和转发详情时要用、user博主信息包含screen_name和用户ID、pic_num图片数量等具体需求具体取。3.2 从链接里提取微博 ID很多场景下用户拿到的是微博的完整分享链接比如https://weibo.com/6286500601/NvDPL6QmT这种。这种链接里并没有直接给出微博 ID需要解析。实际处理的思路分两种如果链接是weibo.com/数字/字母串的形式字母串部分是微博的短 ID需要调接口转换成真实的数字 ID。如果链接是m.weibo.cn/status/数字的形式那最后一段数字直接就是微博 ID直接拿来用即可。为了节省复杂度我建议在项目初期统一要求输入m.weibo.cn格式的链接或者在代码里做一次自动转换。转换逻辑不复杂我写了一个简单的函数def extract_weibo_id(url): if m.weibo.cn/status/ in url: return url.strip().split(status/)[-1].split(?)[0] # 其他格式的分享链接先用简单方式提取尾部的字母串 part url.strip().split(/)[-1].split(?)[0] return part短链和字母串的完整转换逻辑这里先不展开后面在“常见问题与排查”部分再细讲。3.3 批量抓取与进度控制单条微博的数据拿到手之后批量抓取就是循环加延时的事。但这里有个很关键的细节绝大多数情况下我们不是手动收集了一堆微博链接再去抓而是给定一个博主 ID把他最近几十上百条微博全部拉下来然后再针对每一条微博去取转评赞。这个场景需要用到另一个接口用户发布的微博时间线接口。请求路径是url fhttps://m.weibo.cn/api/container/getIndex?typeuidvalue{uid}containerid107603{uid}这个接口返回的是该用户最近发布的微博列表默认大概十几条一页每条微博在data.cards数组里每个card的mblog节点就是微博信息。翻页是通过since_id参数控制的具体值是上一次请求返回的data.cardlist_info.since_id。我的批量抓取逻辑是这样的def fetch_user_weibos(uid, max_pages5): all_weibos [] since_id for page in range(max_pages): params { type: uid, value: uid, containerid: f107603{uid}, since_id: since_id } resp requests.get(https://m.weibo.cn/api/container/getIndex, headersheaders, paramsparams, timeout10) data resp.json() cards data.get(data, {}).get(cards, []) if not cards: break for card in cards: if card.get(card_type) 9 and mblog in card: all_weibos.append(card[mblog]) # 解析下一页游标 since_id data.get(data, {}).get(cardlist_info, {}).get(since_id, ) if not since_id: break time.sleep(2 random.random() * 3) # 随机延时2~5秒之间 return all_weibostime.sleep这一步千万别省。很多爬虫脚本被限制不是因为没有伪装请求头而是因为请求频率太高一看就是机器行为。我在循环里加入随机延时让两次请求之间相隔 2 到 5 秒整体速度虽然慢了点但安全系数高很多。拿到全部微博列表之后转评赞数据就已经包含在每条mblog里了不需要再额外请求详情接口。因为时间线接口返回的mblog字段里本身就带着reposts_count、comments_count、attitudes_count这些数据。这给我们省了一大笔请求量也减少了对服务器的压力。3.4 数据清洗与表格输出数据抓下来之后直接拿来用肯定不行必须做一轮清洗。以我这次项目为例清洗步骤主要有四个去除正文里的 HTML 标签和特殊字符。部分微博的正文会带有a、span这类标签残片用正则表达式清理掉。统一时间格式。created_at字段是英文时间格式我把转成YYYY-MM-DD HH:MM:SS方便排序。处理空值。有些老微博没有点赞数据字段可能缺失填 0 就行。去重。如果多次抓取同一微博 ID 可能出现多次按微博 ID 去重保留最新记录。清洗这部分我用的是 pandas核心代码很简单import pandas as pd df pd.DataFrame(all_weibos) df df[[id, raw_text, created_at, reposts_count, comments_count, attitudes_count]] df.columns [weibo_id, content, publish_time, reposts, comments, likes] df[publish_time] pd.to_datetime(df[publish_time], format%a %b %d %H:%M:%S %z %Y) df[reposts] pd.to_numeric(df[reposts], errorscoerce).fillna(0).astype(int) df[comments] pd.to_numeric(df[comments], errorscoerce).fillna(0).astype(int) df[likes] pd.to_numeric(df[likes], errorscoerce).fillna(0).astype(int) df df.drop_duplicates(subset[weibo_id]) df.to_csv(weibo_data.csv, indexFalse, encodingutf-8-sig)输出用utf-8-sig而不是utf-8主要是为了解决 Excel 打开 CSV 时中文乱码的问题。这个小细节很多人容易忽略等打开文件看到一堆乱码才反应过来又要重新跑一遍脚本浪费时间。created_at的转换试了几次不同接口返回的格式略有差异建议先打印一条数据确认格式再写解析逻辑别直接套死模板。4. 数据存储与二次扩展除了表格还有什么玩法4.1 增量抓取与断点续抓如果只是想一次性拉一批数据上面提到的方案已经够用了。但实际使用中经常遇到的情况是第一次跑了 100 条过了一周想再跑一次拉取新增的微博如果每次都是全量抓不仅慢而且会重复拉取大量旧数据。我的做法是用本地文件做增量标记。每次抓取时先读取上次已经保存的微博 ID 集合新抓到的数据如果 ID 已经存在就跳过只把新增的追加到数据集里。实现逻辑是这样的import os import json seen_ids set() if os.path.exists(seen_ids.json): with open(seen_ids.json, r, encodingutf-8) as f: seen_ids set(json.load(f)) new_weibos [] for mblog in all_weibos: if mblog[id] in seen_ids: continue seen_ids.add(mblog[id]) new_weibos.append(mblog) with open(seen_ids.json, w, encodingutf-8) as f: json.dump(list(seen_ids), f, ensure_asciiFalse)这样每次跑完只处理新增部分几分钟就能完成增量更新。4.2 从转评赞到更深的互动数据转评赞只是互动数据的冰山一角。如果要做更深入的分析还可以针对每一条微博继续抓取评论列表和转发列表。比如评论列表的接口路径是url fhttps://m.weibo.cn/api/comments/show?id{weibo_id}page{page}拿到评论内容后可以做词频分析、情感分析甚至提取评论里的表情符号分布。这个扩展性强但请求量会大幅增加抓取时间翻好几倍建议按需使用。以我这次项目为例我额外抓了评论列表里的热评内容用来判断每条微博的讨论焦点配合转评赞数据一起看整体信息量丰富了很多。4.3 成果数据的可视化呈现数据拿到手里不做可视化等于白干。pandas 处理完的数据可以直接喂给 matplotlib 或 pyecharts 做图表。我最常用的几个展示角度按时间维度统计转评赞的趋势变化。按微博类型纯文字、带图、带视频对比互动量差异。转赞比、评赞比的计算识别出那些转发特别高但点赞一般的内容。这些可视化工作虽然不复杂但能让分析结果直观很多做汇报的时候也更好讲。5. 常见问题与排查技巧实录5.1 登录态失效返回数据里没有 mblog 节点最常见的问题之一。运行一段时间后突然发现返回的data是空的或者data.cards里没有mblog这时候大概率是 Cookie 过期了。排查思路很简单第一步先在浏览器里手动访问一次同样的接口看看能不能正常返回数据。如果能说明问题出在脚本的 Cookie 上更新一下 Cookie 就行。如果浏览器也看不到数据那考虑是不是账号本身权限问题比如被限制登录。我的习惯是每次写代码之前先手动在浏览器里确认一次接口能通再把 Cookie 贴进脚本省得代码问题还是权限问题分不清。5.2 微博 ID 解析失败短链和字母串 ID前面提到过weibo.com/6286500601/NvDPL6QmT这种链接里的尾部不是数字 ID而是字母串短 ID。直接用这个值去请求详情接口返回的结果为空。解决办法是找到短 ID 和真实 ID 之间的转换接口。比较靠谱的方式是请求这个链接观察重定向过程中携带的参数或者访问一个专门解析短链的接口。实际操作中我发现了https://weibo.com/ajax/statuses/show?id字母串这个接口可以直接返回真实数字 ID 和微博详情对于这个场景是够用的。如果转换接口不好使还有个土办法用移动端链接格式的 ID。即尝试https://m.weibo.cn/status/字母串这个链接手动打开看能不能正常访问。能访问的话有些场景下可以直接用字母串替代数字 ID因为部分接口兼容这种格式。5.3 部分字段缺失老微博没有点赞数抓一批老微博时发现早期的部分微博返回的数据里压根没有attitudes_count字段或者字段值为None。直接用int(None)必然会报错。解决方案上面代码里已经体现了一部分用pd.to_numeric(errorscoerce)把非数字值强制转成 NaN再fillna(0)补成 0。用纯 Python 写的话就是用mblog.get(attitudes_count, 0) or 0把None和0统一兜住。这个思路也可以推广到其他字段。凡是可能缺失的字段一律用get加默认值的方式处理不要直接下标访问。5.4 被限制访问请求频率过高表现是请求一段时间后接口开始大量返回 418 或者 403 状态码或者干脆返回一串看不懂的错误提示。这种情况通常不是程序逻辑问题而是访问频率过高被限制。处理办法比较朴素降低抓取频率延长延时时间。我个人的经验是微博移动端接口单次会话下每秒超过 1 个请求的风险较高最稳妥的做法是每次请求后至少间隔 2 到 3 秒。如果延时调低后还是频繁受限那就考虑分段抓取比如分多个时间段跑每次只跑一部分数据。把任务拆散了整体受控概率小很多。5.5 数据异常大或内存溢出这批数据正常情况下不会很大但如果抓取的用户微博有几万条全部堆在内存里再转 DataFrame可能会出现内存占用过高的情况。我的做法是分批写入 CSV。每抓完一定数量的微博比如 500 条就写一次文件然后释放内存。这样即使中断了前面保存的数据也不会丢。batch_size 500 for i in range(0, len(all_weibos), batch_size): batch all_weibos[i:i batch_size] df_batch pd.DataFrame(batch) # 处理字段并追加写入文件 df_batch.to_csv(weibo_data.csv, modea, headernot saved, indexFalse) saved True5.6 常见问题速查表现象可能原因解决方案接口返回data为空Cookie 过期在浏览器中重新登录并更新 Cookie返回状态码 403/418请求频率过高加大延时降低频率转评赞字段出现None老微博数据缺失用get 默认值兜底解析出来的时间是英文格式接口返回非标准时间格式自定义时间解析统一转标准格式CSV 用 Excel 打开乱码编码问题保存时用utf-8-sig微博短链接解析不了 ID链接是字母串短ID用转换接口或直接请求移动端链接验证写在最后的实操体会这个项目整体不大但从需求确认到数据落地踩过的坑一个不少。Cookie 过期、字段名不一致、时间格式混乱、请求频率把控每一类问题单独拎出来都不复杂但串在一起的时候排查起来还是挺花时间的。我个人最大的体会是写爬虫脚本之前一定要先在浏览器里手动把整个流程走一遍。拿真实的数据格式来逆推解析逻辑比凭空猜字段名靠谱得多。这个习惯看着笨但能帮你省掉大把调试时间。另外一个务实建议抓取频率宁慢勿快。很多限制不是因为爬虫识别得多准而是因为请求行为实在太不像是人。把延时加进去功能一样能完成但稳定性高出好几个级别。最后再提醒一句数据是抓下来了但怎么用、拿来做什么心里得有杆秤。公开数据的采集和学习是技术圈的正常需求但别拿它去做任何影响他人权益的事。守住这个边界这样的工具脚本才能用得安心。
RELATED

相关推荐

Istio快速入门:微服务通信治理与Service Mesh实践

Istio快速入门:微服务通信治理与Service Mesh实践

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

📅 2026/10/15 1:02:34
Qt子控件中QPainter绘图避坑指南:paintEvent、坐标系与缓存实战

Qt子控件中QPainter绘图避坑指南:paintEvent、坐标系与缓存实战

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

📅 2026/10/15 1:02:34
.NET Core Excel导出实战:性能、样式与兼容性工程指南

.NET Core Excel导出实战:性能、样式与兼容性工程指南

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

📅 2026/10/15 1:02:34
MORE NEWS

更多资讯

📰

PyTorch核心设计原理与工业级训练实践

1. 这不是“学个框架”那么简单:PyTorch到底在解决什么真实问题?很多人第一次听说PyTorch,是在某次技术分享会上听到“动态图好调试”“API设计更Pythonic”这类评价;也有人是从Kaggle竞赛排行榜上看到大量Top方案的代码仓库里&am…

📰

从零搭建大学生就业信息管理系统:需求、设计到实现

1. 这个系统解决什么问题:需求拆解与功能边界大学生就业信息管理系统我接触得比较多,每年都会看到不少计算机相关专业的同学拿它当毕设选题。第一反应往往是“这不就是一个信息管理的增删改查吗”,但真正动手做起来才会发现,角色权…

📰

TensorFlow全流程实战:从环境搭建到模型部署的完整链路

这不是一篇入门教程,也不是API文档搬运。从我第一次在项目里跑通TensorFlow,到现在能用它顺畅地完成从数据准备到模型部署的全流程,中间绕了很远的路,也踩了不少坑。这篇文章把你真正会用到的那些东西——环境、数据、模型、训练、…

📰

airllm:低显存机器跑超大语言模型的实践指南

实际测试完成的部署方案:如何在低内存机器上跑超大容量语言模型最近 AI 本地部署群里讨论最多的一个话题,不是新模型的评测,而是“我到底要多少显存才能跑得动这些模型”。动不动几十GB的权重,让很多人的消费级电脑直接劝退。如果…

📰

RAR归档文件解压全指南:从格式识别到批量处理与避坑

简介:GC-PowerStation 2019中文版是面向表面贴装工艺工程师的坐标导出与光绘文件处理工具,支持导入电子表格、文本等多种坐标文件格式,并完成多层光绘文件的预览、合并与校验,帮助电子制造从业者在生产前检查设计准确性&#xff0…

📰

易语言乐玩插件窗口句柄获取与后台绑定模式实战指南

1. 窗口句柄获取与后台绑定模式的核心逻辑拆解1.1 为什么窗口句柄是一切自动化操作的起点做桌面自动化或者辅助工具开发,绕不开的第一个坎就是拿到目标窗口的句柄。你可以把窗口句柄理解成操作系统给每个窗口发的一张身份证号,它是一个长整型数值&#x…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬