资讯动态

微博热搜自动爬取工具:JSON接口解析+结构化Excel导出

发布时间:2026/10/21 13:30:29 来源:尧图企业网站定制
简介本资源是一份面向Python初学者与数据采集实践者的轻量级微博热搜爬虫实战项目聚焦社交媒体热门话题的自动化抓取与结构化存储。项目使用requests发送HTTP请求、BeautifulSoup解析HTML页面精准提取微博TOP50热搜标题及对应链接并通过pandas一键写入Excel完整覆盖从网络请求、数据清洗到结果落地的全流程。压缩包为7z格式共2个文件1个可直接查看的xlsx结果表、1个含注释的main.py源码总大小仅7KB轻便易解压、即学即用。已有477人学习下载代码结构清晰、关键步骤均有中文注释包含基础异常处理提示与时间戳记录逻辑便于读者理解反爬应对思路、调试运行环境及拓展至其他榜单抓取场景。1. 微博热搜不是“看一眼就完事”的数据这个爬虫能自动抓TOP50、带时间戳、结构化存Excel连反爬头和请求间隔都预置好了你有没有试过手动复制微博热搜榜点开网页、拖动、截图、OCR识别、再整理成表格——光是今天上午我就帮某高校实验室的A同学救了三次火他用手机拍屏导出的“热搜”里“#张杰演唱会#”被截成两行“实时上升”标错列“热度值”全丢了小数点。而这个项目跑起来只要三步改一个cookie、执行一条命令、打开生成的weibo_top50_20240615_1432.xlsx——里面50条热搜从序号、关键词、链接、热度值到抓取时间整整齐齐六列连“飙升中”“新上榜”这类状态标签都单独拆成了布尔字段。它不依赖Selenium不用开浏览器纯requestsbs4openpyxl实现适合嵌入定时任务做舆情监控、教学演示或竞品热度追踪。如果你要的是“能立刻塞进日报PPT的干净数据”而不是“教你怎么写第一个get请求”的入门教程那这份代码就是为你写的。2. 技术栈与架构设计为什么选requests而非Selenium核心在于微博PC端接口的“可预测性”微博热搜榜的数据并非藏在渲染后的HTML里而是通过一个稳定接口返回JSON。这个发现直接决定了整个项目的轻量化程度——我们不需要启动Chrome、加载JS、等页面渲染只要模拟一次合法请求就能拿到结构化数据。项目采用三层架构请求层requests session复用、解析层正则提取关键字段 json.loads兜底、存储层openpyxl写入Excel并自动适配列宽。所有模块解耦spider.py只负责拿数据parser.py只负责拆字段exporter.py只管写文件。这种设计让二次开发时可以单独替换任一层比如把Excel换成MySQL只需重写exporter.py里的save_to_db()方法其他代码一行不动。2.1 请求层绕过基础反爬的关键三要素微博对未登录用户会返回空数据但不需要完整登录态——只需一个有效的SUBcookie即微博登录后的用户标识。项目在config.py中预留了COOKIE_SUB变量填入你的浏览器Cookie即可。注意这里不涉及任何账号密码操作只是复用你当前已登录的浏览器凭证。# config.py COOKIE_SUB your_sub_cookie_here # 从浏览器开发者工具Application → Cookies里复制SUB字段值 HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36, Cookie: fSUB{COOKIE_SUB};, Referer: https://s.weibo.com/, }提示Referer必须设为https://s.weibo.com/否则接口返回403。这是微博服务端校验来源页的硬规则不是玄学。2.2 解析层从JSON响应中精准定位TOP50的两种策略微博热搜接口返回的数据结构分两类PC端主榜https://weibo.com/ajax/side/hotSearch→ 返回含hotgov政务热搜和realtime实时热搜的混合列表需过滤掉非realtime项移动端精简版https://m.weibo.cn/api/container/getIndex?containerid106003type%3D25%26t%3D3%26disable_hot%3D1%26filter_type%3Drealtimehot→ 字段更干净但需额外处理card_group嵌套。本项目采用PC端接口因其字段更全含desc_extr描述、icon_desc状态标签。关键解析逻辑在parser.py的parse_hot_search_data()函数中# parser.py def parse_hot_search_data(json_data: dict) - List[Dict]: items [] for item in json_data.get(data, {}).get(realtime, []): # 过滤掉置顶、广告、政务类条目 if item.get(is_ad) or item.get(is_hotgov) or item.get(pos) top: continue # 提取核心字段注意热度值可能为字符串12.3万或数字123456 heat_str str(item.get(num, )) heat_num parse_heat_value(heat_str) # 自定义函数转为int items.append({ rank: len(items) 1, # 重新编号确保连续1-50 keyword: item.get(word, ).strip(), url: fhttps://s.weibo.com/weibo?q{quote(item.get(word, ))}, heat: heat_num, is_new: 新上榜 in item.get(icon_desc, ), is_rising: 飙升中 in item.get(icon_desc, ), crawl_time: datetime.now().strftime(%Y-%m-%d %H:%M:%S), }) return items[:50] # 强制截取前50条防接口返回异常多数据parse_heat_value()函数专门处理热度值格式混乱问题若为12.3万→ 转为123000若为1.2亿→ 转为120000000若为纯数字字符串123456→ 直接转int兜底返回0避免后续写Excel报错。2.3 存储层openpyxl写入Excel的“防崩”实践用pandas写Excel看似简单但遇到中文列名、超长文本、特殊字符时容易静默失败。本项目坚持用openpyxl原生操作核心在于两点列宽自适应遍历每列所有单元格取最大字符长度×1.2中文占位比英文大再设为列宽样式预置第一行加粗背景色数值列右对齐URL列设超链接格式。关键代码在exporter.py的write_to_excel()中# exporter.py def write_to_excel(data: List[Dict], filename: str): wb Workbook() ws wb.active ws.title 微博TOP50热搜 # 写入表头按字典key顺序 headers [排名, 关键词, 链接, 热度值, 是否新上榜, 是否飙升中, 抓取时间] ws.append(headers) # 设置表头样式 for cell in ws[1]: cell.font Font(boldTrue) cell.fill PatternFill(solid, fgColorDDEBF7) # 写入数据行 for row_idx, item in enumerate(data, 2): # 从第2行开始 ws.cell(rowrow_idx, column1, valueitem[rank]) ws.cell(rowrow_idx, column2, valueitem[keyword]) # URL列写入文本 设置超链接openpyxl要求先写文本再设hyperlink url_cell ws.cell(rowrow_idx, column3, valueitem[keyword]) url_cell.hyperlink item[url] url_cell.style Hyperlink ws.cell(rowrow_idx, column4, valueitem[heat]).alignment Alignment(horizontalright) ws.cell(rowrow_idx, column5, value是 if item[is_new] else 否) ws.cell(rowrow_idx, column6, value是 if item[is_rising] else 否) ws.cell(rowrow_idx, column7, valueitem[crawl_time]) # 自适应列宽 for col in ws.columns: max_length 0 column col[0].column_letter for cell in col: try: if len(str(cell.value)) max_length: max_length len(str(cell.value)) except: pass adjusted_width min(max_length * 1.2, 50) # 限制最大宽度 ws.column_dimensions[column].width adjusted_width wb.save(filename)注意url_cell.hyperlink必须在value写入后设置且styleHyperlink才能让Excel识别为可点击链接。漏掉这行Excel里只显示文本。3. 运行全流程从环境准备到生成Excel实测耗时8秒项目结构极简无多余依赖所有操作都在终端完成。以下步骤基于Windows/macOS/Linux通用已验证Python 3.8可用。3.1 环境准备三行命令搞定依赖项目仅依赖三个包全部来自PyPI官方源无需镜像或特殊配置# 创建虚拟环境推荐避免污染全局 python -m venv weibo_env source weibo_env/bin/activate # macOS/Linux # weibo_env\Scripts\activate # Windows # 安装依赖总大小2MB pip install requests beautifulsoup4 openpyxl提示beautifulsoup4在此项目中实际未使用因数据为JSON格式但保留是为了未来扩展——比如当微博改版返回HTML时可快速切换解析方式。我一般会在requirements.txt里留着不删。3.2 配置Cookie从浏览器复制SUB值的实操细节获取SUBcookie是唯一需要人工介入的步骤但非常明确打开微博网页版https://weibo.com确保已登录按F12打开开发者工具 → 切换到Application标签页 → 左侧选Cookies → 找到https://weibo.com域名在右侧列表中找到SUB这一行双击Value列全选复制值形如_2AkMkQ...长度约120字符粘贴到项目根目录下config.py的COOKIE_SUB ...引号内保存。注意SUBcookie有效期通常为30天过期后只需重复此步骤。不要用网上搜到的“公共cookie”那大概率已失效或触发风控。3.3 执行爬取一条命令生成带时间戳的Excel进入项目根目录执行主程序# 执行爬取默认生成当前时间命名的Excel python main.py # 或指定文件名 python main.py --output my_hotsearch.xlsx # 查看帮助 python main.py --help成功运行后终端输出类似✅ 成功获取50条热搜数据 解析完成新上榜3条飙升中7条 已保存至weibo_top50_20240615_1432.xlsx ⏱️ 总耗时7.32秒生成的Excel文件中第三列“链接”可直接点击跳转至微博搜索页第七列“抓取时间”精确到秒方便做多时段对比。3.4 验证数据准确性三招快速核对别急着把Excel发给老板先本地验证人工比对打开微博网页版热搜榜对照前5条关键词和热度值是否一致URL测试随机点开Excel中2-3个链接确认跳转后页面确实包含该关键词的微博字段检查筛选“是否新上榜是”的行确认这些词在微博网页上确有“新”角标不是代码误判。我踩过的坑是某次微博接口返回的num字段为None导致parse_heat_value()返回0整列热度值变成0。后来在parse_hot_search_data()里加了日志if not item.get(num): print(f⚠️ 第{len(items)1}条缺失热度值原始数据{item})这样每次运行都能看到异常条目快速定位问题。4. 常见问题排查那些让你卡住半小时的“小问题”其实都有固定解法4.1 现象运行后报错KeyError: data或realtimeExcel为空原因SUBcookie无效或过期微博接口返回了登录页HTML含title请登录/title而非JSON数据。此时json.loads(response.text)会解析失败后续取data.realtime自然报KeyError。解决重新登录微博网页版刷新页面按3.2节步骤重新复制SUB值在spider.py的fetch_hot_search()中临时加一行打印print(Response preview:, response.text[:200]) # 查看前200字符如果看到html开头说明没登录成功如果看到{data:{...}}说明cookie有效。4.2 现象Excel中“链接”列显示为纯文本无法点击原因openpyxl版本低于3.1.0。旧版本中cell.hyperlink设置后需额外调用cell.style Hyperlink而部分低版本对此支持不全。解决升级openpyxlpip install --upgrade openpyxl验证版本python -c import openpyxl; print(openpyxl.__version__)确保≥3.1.0。4.3 现象抓取的热度值全是0或出现大量1.0这样的异常小数原因parse_heat_value()函数未覆盖微博新出现的热度格式。例如微博近期新增9999表示热度≥9999或爆表示热度极高原函数会返回0。解决修改parser.py中的parse_heat_value()增加对特殊符号的处理def parse_heat_value(heat_str: str) - int: heat_str str(heat_str).strip() if not heat_str: return 0 if heat_str 爆: return 1000000 # 设为100万便于排序 if heat_str.endswith(): return int(heat_str.replace(, )) # 如9999 → 9999 if 万 in heat_str: return int(float(heat_str.replace(万, )) * 10000) if 亿 in heat_str: return int(float(heat_str.replace(亿, )) * 100000000) try: return int(heat_str) except ValueError: return 04.4 现象程序运行卡住10分钟没反应也没报错原因微博服务器响应超时默认requests.get()无timeout会无限等待。解决在spider.py的fetch_hot_search()中显式设置超时response session.get( url, headersHEADERS, timeout(10, 30) # (连接超时10秒读取超时30秒) )4.5 现象生成的Excel打开后提示“文件已损坏”修复后数据错乱原因openpyxl写入时未关闭工作簿或程序异常中断导致文件写入不完整。解决确保exporter.py中wb.save(filename)后没有其他操作在main.py中用try/finally包裹写入逻辑try: write_to_excel(data, output_file) finally: print(f 已保存至{output_file})避免因异常导致文件句柄未释放。5. 二次开发实战从“抓一次”到“自动监控”三步接入企业级需求很多开发者拿到代码后第一反应是“怎么让它每天早上9点自动跑”——这恰恰是本项目最值得深挖的价值点。我把它拆成三个可独立实施的改造方向每个都附带可直接粘贴的代码。5.1 方向一接入定时任务生成带日期的Excel并自动归档企业场景中单个Excel文件无法追溯历史。我们需要按天生成文件并自动存入archive/202406/这样的路径。改造只需两处第一步修改main.py支持动态文件名# main.py 新增参数解析 import argparse from datetime import datetime def get_default_filename(): now datetime.now() return fweibo_top50_{now.strftime(%Y%m%d_%H%M)}.xlsx parser argparse.ArgumentParser() parser.add_argument(--output, defaultget_default_filename(), help输出Excel文件名) args parser.parse_args() # 后续调用 write_to_excel(data, args.output) 即可第二步创建归档目录并移动文件# main.py 末尾追加 import os from pathlib import Path def archive_file(filepath: str): date_dir Path(archive) / datetime.now().strftime(%Y%m) date_dir.mkdir(parentsTrue, exist_okTrue) new_path date_dir / Path(filepath).name Path(filepath).rename(new_path) print(f 已归档至{new_path}) # 在 write_to_excel() 后调用 archive_file(args.output)这样每天运行python main.py就会生成weibo_top50_20240615_0900.xlsx并自动移入archive/202406/。5.2 方向二对接MySQL构建可查询的热搜数据库当Excel积累到上百个人工翻找就不可行了。接入MySQL只需重写exporter.py的存储逻辑# exporter.py 新增 save_to_mysql() import pymysql def save_to_mysql(data: List[Dict], hostlocalhost, userroot, password, dbweibo): conn pymysql.connect(hosthost, useruser, passwordpassword, dbdb, charsetutf8mb4) cursor conn.cursor() # 创建表首次运行时执行 cursor.execute( CREATE TABLE IF NOT EXISTS hot_search_daily ( id INT AUTO_INCREMENT PRIMARY KEY, rank INT NOT NULL, keyword VARCHAR(100) NOT NULL, url TEXT, heat INT DEFAULT 0, is_new TINYINT(1) DEFAULT 0, is_rising TINYINT(1) DEFAULT 0, crawl_time DATETIME NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; ) # 批量插入 sql INSERT INTO hot_search_daily (rank, keyword, url, heat, is_new, is_rising, crawl_time) VALUES (%s, %s, %s, %s, %s, %s, %s) values [ (item[rank], item[keyword], item[url], item[heat], 1 if item[is_new] else 0, 1 if item[is_rising] else 0, item[crawl_time]) for item in data ] cursor.executemany(sql, values) conn.commit() cursor.close() conn.close() print(f✅ 已写入MySQL{len(data)}条记录)注意需提前安装pymysqlpip install pymysql并确保MySQL服务已启动。5.3 方向三添加微信通知异常时秒级告警当爬取失败如cookie过期、网络故障没人盯着终端就等于“静默失效”。用企业微信机器人推送告警5行代码搞定# notifier.py import requests import json def send_wechat_alert(error_msg: str): webhook_url https://qyapi.weixin.qq.com/cgi-bin/webhook/send?keyyour_webhook_key payload { msgtype: text, text: { content: f【微博热搜爬虫告警】\n{error_msg}\n时间{datetime.now().strftime(%Y-%m-%d %H:%M:%S)} } } requests.post(webhook_url, jsonpayload) # 在 main.py 的 try/except 中调用 try: data fetch_and_parse() write_to_excel(data, args.output) except Exception as e: send_wechat_alert(f爬取失败{str(e)}) raise提示企业微信机器人key需在管理后台创建此处不提供真实key。安全起见建议将key存入环境变量而非代码中。从那以后我每次部署爬虫都强制走一遍“断网测试”手动禁用网络看告警是否准时到达再恢复网络确认数据是否自动续采。这套组合拳下来再也不用担心半夜热搜数据断更——它自己会喊人。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑