微博爬虫避坑指南:如何高效获取个人主页数据(附完整Python代码)
微博数据采集实战:Python爬虫高效获取个人主页与评论数据
在社交媒体分析、舆情监测或学术研究中,微博数据采集一直是热门需求。本文将深入解析微博网页端的数据接口,提供一套完整的Python解决方案,帮助开发者绕过常见反爬机制,高效获取个人主页信息、微博列表及评论数据。
1. 微博数据采集基础准备
微博数据采集面临三大核心挑战:接口认证、频率限制和数据解析。与直接爬取HTML页面不同,现代微博采用前后端分离架构,数据通过JSON接口传输,这既提高了采集效率,也带来了新的技术门槛。
关键工具准备:
- Python 3.7+
- Requests库(处理HTTP请求)
- 浏览器开发者工具(分析网络请求)
- JSON解析工具
重要提示:所有采集行为应当遵守微博Robots协议,控制请求频率(建议≤1请求/秒),避免对服务器造成过大压力。
微博接口主要分为三类:
- 用户信息接口 - 获取基础资料
- 微博列表接口 - 获取用户发布的微博
- 评论接口 - 获取单条微博的评论
import requests headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 'Cookie': 'YOUR_COOKIE_HERE' # 需替换为有效cookie }2. 用户信息采集实战
微博用户信息存储在两个核心接口中,通过用户UID(唯一标识)即可获取:
接口地址对比:
| 接口URL | 数据类型 | 关键字段 |
|---|---|---|
ajax/profile/info | 基础信息 | screen_name(昵称), followers_count(粉丝数) |
ajax/profile/detail | 详细信息 | description(简介), ip_location(IP属地) |
def get_user_info(uid): base_url = f"https://weibo.com/ajax/profile/info?uid={uid}" detail_url = f"https://weibo.com/ajax/profile/detail?uid={uid}" base_info = requests.get(base_url, headers=headers).json() detail_info = requests.get(detail_url, headers=headers).json() return { **base_info['data'], **detail_info['data'] } # 示例:获取用户"李子柒"的数据(UID: 2970452952) user_data = get_user_info(2970452952)Cookie处理技巧:
- 仅需
SUB字段即可通过基础认证 - 通过浏览器登录后复制完整Cookie(有效期约1周)
- 建议使用多账号轮换避免单账号被封
3. 微博列表采集与分页策略
微博列表接口采用动态分页机制,关键参数包括:
uid: 用户IDpage: 当前页码(仅首页有效)since_id: 分页标识(核心参数)
def get_weibo_list(uid, since_id=""): base_params = { 'uid': uid, 'feature': '0' } url = "https://weibo.com/ajax/statuses/mymblog" if since_id: base_params['since_id'] = since_id response = requests.get(url, headers=headers, params=base_params) return response.json() # 首次请求(第一页) first_page = get_weibo_list(2970452952) since_id = first_page['data']['since_id'] # 后续分页处理 while since_id: next_page = get_weibo_list(2970452952, since_id) since_id = next_page['data']['since_id'] # 处理数据...数据结构解析:
{ "list": [ { "mid": "微博ID", "text_raw": "纯文本内容", "created_at": "发布时间", "reposts_count": 转发数, "comments_count": 评论数, "attitudes_count": 点赞数, "isLongText": False # 是否长文本 } ], "since_id": "下页标识" }4. 微博评论采集全解析
评论接口采用max_id分页机制,与微博列表的分页逻辑不同:
接口参数说明:
id: 微博ID(mid)max_id: 分页标识(初始为0)count: 每页数量(最大100)
def get_comments(mid, max_id=0): params = { 'is_reload': '1', 'id': mid, 'is_show_bulletin': '2', 'is_mix': '0', 'count': '20', 'max_id': str(max_id) if max_id else '0' } url = "https://weibo.com/ajax/statuses/buildComments" return requests.get(url, headers=headers, params=params).json() # 评论采集示例 comment_data = [] mid = "3957247706865941" # 示例微博ID current_max_id = 0 while True: resp = get_comments(mid, current_max_id) comment_data.extend(resp['data']) current_max_id = resp['max_id'] if current_max_id == 0: # 终止条件 break评论数据结构:
{ "id": "评论ID", "text": "评论内容(含HTML)", "text_raw": "纯文本内容", "user": { "id": "用户ID", "screen_name": "昵称" }, "reply_comment": { # 回复的评论 "text": "被回复内容", "user": {...} } }5. 反爬应对策略与优化方案
微博的反爬机制主要集中在频率限制和Cookie验证上,以下是实测有效的解决方案:
IP代理策略:
- 使用高质量HTTP代理(建议独享IP)
- 代理池规模建议≥50个IP
- 自动切换频率:每50请求切换1次
proxies = { 'http': 'http://user:pass@ip:port', 'https': 'http://user:pass@ip:port' } response = requests.get(url, headers=headers, proxies=proxies)请求频率控制:
import time import random def safe_request(url, params=None): time.sleep(random.uniform(1, 3)) # 随机延迟1-3秒 return requests.get(url, headers=headers, params=params)高级技巧:
- 动态User-Agent:轮换使用主流浏览器UA
- 请求间隔随机化:避免固定频率被识别
- 关键Cookie刷新:定期更新SUB值
- 错误重试机制:对429/403状态码自动重试
from fake_useragent import UserAgent ua = UserAgent() headers['User-Agent'] = ua.random def retry_request(url, max_retries=3): for i in range(max_retries): try: resp = safe_request(url) if resp.status_code == 200: return resp except Exception as e: print(f"Request failed: {e}") time.sleep(5 ** (i + 1)) # 指数退避 return None6. 数据存储与后续处理
采集到的数据建议采用结构化存储方案:
存储方案对比:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| CSV | 简单易用 | 无索引 | 小规模数据 |
| SQLite | 零配置 | 并发性能差 | 单机应用 |
| MySQL | 功能完善 | 需服务端 | 中大规模 |
| MongoDB | 灵活Schema | 内存占用高 | 非结构化数据 |
CSV存储示例:
import csv def save_to_csv(data, filename): with open(filename, 'w', encoding='utf-8', newline='') as f: writer = csv.DictWriter(f, fieldnames=data[0].keys()) writer.writeheader() writer.writerows(data) # 存储微博数据 weibo_list = [...] # 采集到的微博列表 save_to_csv(weibo_list, 'weibo_posts.csv')数据清洗技巧:
- HTML标签去除:使用
bs4.BeautifulSoup清理富文本 - 时间格式化:统一时间戳转换
- 表情符号处理:提取或替换emoji
- 去重处理:基于微博ID去重
from bs4 import BeautifulSoup def clean_html(text): soup = BeautifulSoup(text, 'html.parser') return soup.get_text() raw_html = '<a href="#">你好</a>世界' clean_text = clean_html(raw_html) # 输出:你好世界7. 典型问题解决方案
在实际开发中,开发者常遇到以下问题:
问题1:返回数据为空
- 检查Cookie是否过期(特别是SUB值)
- 验证UID是否正确(部分用户使用自定义域名)
- 确认接口URL是否变更(定期监控)
问题2:频率限制(429错误)
if response.status_code == 429: retry_after = int(response.headers.get('Retry-After', 60)) time.sleep(retry_after + random.randint(1, 10))问题3:数据不完整
- 长微博:通过
isLongText判断,调用扩展接口 - 图片/视频:解析
pic_ids和page_info字段 - 转发微博:检查
retweeted_status字段
def get_long_text(mid): url = f"https://weibo.com/ajax/statuses/longtext?id={mid}" return requests.get(url, headers=headers).json() # 使用示例 if weibo['isLongText']: full_text = get_long_text(weibo['mid'])['data']['longTextContent']通过本文介绍的技术方案,开发者可以构建稳定的微博数据采集系统。建议在实际应用中增加日志监控、异常报警等机制,确保采集任务的持续稳定运行。
