【Python爬虫实战】手把手教你爬取B站美食区数据,构建分析基础——数据采集篇
参数的作用就是:指定接口的查询条件。参数名含义说明rid分区 ID,1020是 B 站美食分区的专属 IDtype排序类型,all表示 “全时段排行榜”网页定位参数,用于标识访问场景w_rid前端生成的签名类参数,用于接口校验(若失效需重新抓包获取最新值)wts时间戳参数,用于接口时效性验证,需实时生成(可通过获取当前时间戳)美食排行榜视频数据是动态更新的,这一分钟和上一分钟抓取的数据可能就会产生
引言
在内容爆炸的时代,B 站美食区凭借多元的创作生态(从探店测评到厨艺教学)成为观察饮食文化与用户偏好的重要窗口,而数据正是破解 “什么样的内容更受欢迎” 的关键钥匙。用爬虫技术沉淀真实数据,既能为创作者提供内容方向的量化参考,也能为行业分析打下客观基础 —— 这正是我聚焦 B 站美食区数据爬取的核心意义。
技术选型
核心采用 requests 库发起网络请求,结合 json 库解析返回的接口数据;用 pandas 实现数据清洗与结构化存储,采用time.sleep()用于控制请求间隔以应对反爬虫机制。针对 B 站反爬策略,除了设置合理的请求频率,还会通过随机 User - Agent 模拟浏览器行为,避免单一 IP 高频访问触发限制,确保爬取过程稳定合规。
爬虫核心逻辑
1.构造API请求
想要去餐厅吃饭,首先就得知道餐厅地址——》告诉服务员你的口味偏好——》点单,那对应在网络抓包调取数据中就是:API的URL——》请求头headers(cookie你的身份、Accept-Language指定接收语言、User-Agent指的就是模拟下单设备),这样一套下来就构造好了API请求,“服务员”就可以给你匹配服务了。
①确定API的URL
你想要的数据是什么?它在哪里?
本次请求的 API 地址为:https://api.bilibili.com/x/web-interface/ranking/v2?
该接口用于获取 B 站各分区的排行榜数据,通过参数指定 “美食分区” 即可定位到目标数据。
②配置请求头Headers
请求头用于将机器模拟为真实浏览器行为:
accept:表示客户端可接受的响应内容类型,*/* 表示任意类型;
accept-encoding:指定可接受的压缩编码格式,用于数据压缩传输;
accept-language:设置语言偏好,模拟用户的语言环境;
cookie:携带用户的身份标识,模拟真实用户登录状态,降低被反爬拦截的概率;
origin、referer:标识请求的来源页面(此处为 B 站美食区排行榜页 面 https://www.bilibili.com/v/popular/rank/food),证明请求的合法性;
sec-ch-ua系列字段:用于标识浏览器的品牌、版本等信息,进一步模拟真实浏览器;
user-agent:核心标识字段,明确浏览器类型(如 Chrome)、系统(Windows)及版本,让请求更贴近人类操作。
③定义请求参数Parameters
参数的作用就是:指定接口的查询条件。
| 参数名 | 含义说明 |
|---|---|
rid |
分区 ID, |
type |
排序类型,all 表示 “全时段排行榜” |
web_location |
网页定位参数,用于标识访问场景 |
w_rid |
前端生成的签名类参数,用于接口校验(若失效需重新抓包获取最新值) |
wts |
时间戳参数,用于接口时效性验证,需实时生成(可通过int(time.time())获取当前时间戳) |
美食排行榜视频数据是动态更新的,这一分钟和上一分钟抓取的数据可能就会产生变化。
2.发起请求
import requests
import pandas as pd
import time
url='https://api.bilibili.com/x/web-interface/ranking/v2?'
headers={
'accept':'*/*',
'accept-encoding':'gzip, deflate, br, zstd',
'accept-language':'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
"cookie":"buvid3=225B10CF-FD35-13E5-4032-48DB7D51B8E734051infoc; b_nut=1743328234; _uuid=110958410C-3851-D43F-D87C-9461925F4C51035742infoc; buvid4=C2A5C017-EE61-F9F9-3E98-64002895B9F635623-025033009-SYqneRNpiDwvv9kNt4UpXQ%3D%3D; rpdid=|(k|Y~|km~~J0J'u~RJJk)kR|; header_theme_version=CLOSE; enable_web_push=DISABLE; enable_feed_channel=ENABLE; CURRENT_FNVAL=2000; SESSDATA=bb403fa9%2C1763713782%2Cc56d0%2A51CjDWG7fErFmFfyWiD6j23xBBeyFzBOAcPJAyuOcnbYPmh8516yX383Ti6t4nnQrrphUSVkRLQzAyVnAtRHMwX2JZMnNpaWV6TXlsd1VTMXR5eXpEdGYwYUNPazZ4dHZkb2x4YU11SHNKUm84dnlTc2ZzSFFLeXBpTXR6Mi1aeEU3M3R1TWVvanJ3IIEC; bili_jct=150f4a5a2c90db1efeebfc0229612085; DedeUserID=3546783728798120; DedeUserID__ckMd5=cd4615b04892aac5; bsource=search_bing; fingerprint=6d96c0154b8b1368cdd273e89a07c268; buvid_fp_plain=undefined; bp_t_offset_3546783728798120=1071508565560131584; hit-dyn-v2=1; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDg1Nzc2MzcsImlhdCI6MTc0ODMxODM3NywicGx0IjotMX0.DOcWd02L0LutR1e6RrVf9f3Gm8LNaskKs-J1xaicu_Y; bili_ticket_expires=1748577577; home_feed_column=5; browser_resolution=1784-994; b_lsid=A8A93E107_1971099D0BF; sid=7t6gi0n6; buvid_fp=6d96c0154b8b1368cdd273e89a07c268",
'origin':"https://www.bilibili.com",
'priority':'u=1, i',
'referer':'https://www.bilibili.com/v/popular/rank/food',
'sec-ch-ua':'"Chromium";v="136", "Microsoft Edge";v="136", "Not.A/Brand";v="99"',
'sec-ch-ua-mobile':'?0',
'sec-ch-ua-platform':'Windows',
'sec-fetch-dest':'empty',
'sec-fetch-mode':'cors',
'sec-fetch-site':'same-site',
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'
}
parameter={
'rid':'1020',
'type':'all',
'web_location':'333.934',
'w_rid':'c627f7cfb500f194743f7f8b1ec5c429',
'wts':'1748834467',
}
res=requests.get(url,headers=headers,params=parameter)
time.sleep(10)
res=requests.get(url,headers=headers,params=parameter)
反爬策略说明:反爬主要通过请求头伪装和请求延时实现:
请求头伪装:通过headers中的User-Agent、Cookie、Referer等字段,模拟真实浏览器的请求特征,让 B 站服务器认为是真实用户在访问,而非爬虫程序。
请求延时:使用time.sleep(10)设置每次请求后休眠 10 秒,降低请求频率,避免因短时间内高频访问触发 B 站的反爬机制。
PS:增强爬虫稳定性以及批量采集大量数据可以使用——》随机浮动延时:用random.uniform(2,5)生成 2-5 秒的随机间隔或自定义更久,模拟真人浏览时 “有时快、有时慢” 的不确定性,让请求节奏更像真实用户。
3.解析JSON数据及保存
JSON数据:是花括号包裹的字符串形式的字典,是一种文本格式,解析之后才能成为python字典这样的内存结构。
解析JSON数据要看清楚包裹的外壳,层层拆分找到需要的数据所在处。对于不在同一data下的数据,我们可以采用index.get()方法获取。
最后将分装出来的信息汇总到一个大列表all_data内,用pandas将列表转换为表格DataFrame(二维数组的形式),将各列及数据整齐排列,导出格式为EXCEL文件(数据量大或者可直接导为.CSV文件在Anaconda里清洗分析很方便)。
data=res.json()['data']['list']
all_data=[]
for index in data:
owner = index.get('owner', {})
stat = index.get('stat', {})
dit = {
'标题': index.get('title', 'Unknown'),
'up': owner.get('name', 'Unknown'),
'视频id': index.get('bvid', 'Unknown'),
'播放': stat.get('view', 'Unknown'),
'点赞': stat.get('like', 'Unknown'),
'投币': stat.get('coin', 'Unknown'),
'弹幕': stat.get('danmaku', 'Unknown'),
'评论': stat.get('reply', 'Unknown'),
'转发': stat.get('share', 'Unknown'),
'时长': index.get('duration', 'Unknown'),
'核心角色':index.get('tname','Unknow'),
'细分领域':index.get('tnamev2','Unknow'),
}
all_data.append(dit)
df=pd.DataFrame(all_data)
df.to_excel(excel_writer='美食排行榜.xlsx',index=False)
本文代码仅用于 Python 爬虫技术学习与交流,仅供个人研究使用。读者使用时需严格遵守 B 站用户协议及相关法律法规,不得用于商业用途或恶意爬取行为,违规使用产生的法律责任与本文作者无关。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)