1. 为什么需要批量采集B站视频信息最近在做市场调研时我发现手动收集B站视频数据实在太费时间了。每次搜索关键词后都要一页页翻看记录视频标题、播放量这些基础信息。特别是当需要分析某个垂直领域的内容趋势时这种手工操作方式简直让人崩溃。这时候就需要用到自动化采集技术了。通过编写爬虫程序我们可以快速获取B站搜索结果页的视频信息。比如你想了解人工智能相关视频的播放量分布或者想分析某个UP主的内容发布规律批量采集数据就能帮上大忙。XPath作为XML路径语言特别适合用来解析HTML文档结构。相比正则表达式它的语法更直观定位元素也更精准。我在实际项目中测试过用XPath提取B站视频信息代码可读性和稳定性都比其他方法要好。2. 准备工作与环境搭建2.1 必备工具清单在开始写代码前我们需要准备好这些工具Python 3.6推荐3.8版本requests库用于发送HTTP请求lxml库解析HTML和XPath处理pandas库数据存储和处理安装这些库很简单用pip一行命令就能搞定pip install requests lxml pandas2.2 分析B站页面结构打开B站搜索页面按F12进入开发者工具。这里有个小技巧点击开发者工具左上角的箭头图标然后鼠标悬停在页面元素上就能自动定位到对应的HTML代码。我注意到B站的搜索结果页有几个特点视频卡片都包含在class为bili-video-card的div中第一页和第二页的DOM结构有细微差异分页参数是通过URL的query string控制的3. XPath定位实战技巧3.1 基础定位方法在开发者工具中右键点击元素选择Copy XPath可以快速获取定位路径。但直接复制的XPath往往过于具体容易受页面结构调整影响。我建议使用相对路径和属性组合的方式。比如获取视频标题可以用//div[contains(class,bili-video-card)]//h3/title这样即使外层容器变化只要class名称不变定位依然有效。3.2 处理动态分页B站的搜索结果页有个特点第一页的URL结构和其他页不同。经过测试我发现分页规律是这样的第一页URL示例https://search.bilibili.com/all?keyword人工智能第二页开始会添加page参数https://search.bilibili.com/all?keyword人工智能page2在代码中需要做判断处理if page not in url: # 第一页的特殊处理 items bs.xpath(//div[idsearch-result]//div[contains(class,video-card)]) else: # 其他页的通用处理 items bs.xpath(//div[contains(class,video-list)]//div[contains(class,video-card)])4. 完整代码实现与优化4.1 基础采集框架先来看核心代码结构import requests from lxml import etree import pandas as pd headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) } def parse_page(url): html requests.get(url, headersheaders).text bs etree.HTML(html) # 这里放XPath提取逻辑 videos [] return videos def main(): base_url https://search.bilibili.com/all?keyword{keyword}page{page} keyword 人工智能 all_videos [] for page in range(1, 6): # 采集前5页 url base_url.format(keywordkeyword, pagepage) videos parse_page(url) all_videos.extend(videos) df pd.DataFrame(all_videos) df.to_excel(b站视频数据.xlsx, indexFalse)4.2 异常处理与反爬策略在实际运行中我发现几个需要注意的问题请求频率控制连续快速请求容易被封建议添加随机延迟import time import random time.sleep(random.uniform(1, 3)) # 1-3秒随机延迟元素缺失处理不是所有视频都有弹幕数等信息try: barrage item.xpath(.//span[contains(class,barrage)]/text())[0] except IndexError: barrage 0代理设置如果IP被封可以考虑使用代理池proxies { http: http://your_proxy:port, https: https://your_proxy:port } response requests.get(url, headersheaders, proxiesproxies)5. 数据处理与存储优化5.1 数据清洗技巧采集到的原始数据往往需要清洗# 处理播放量字符串如12.3万转成123000 def clean_play_count(text): if 万 in text: return int(float(text.replace(万,)) * 10000) return int(text) df[播放量] df[播放量].apply(clean_play_count)5.2 存储方案选择根据数据量大小可以考虑不同存储方式小数据量1万条Excel或CSV中等数据量SQLite大数据量MySQL或MongoDB我常用的CSV存储代码import csv with open(data.csv, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnamesfieldnames) writer.writeheader() writer.writerows(data)6. 项目实战经验分享在实际项目中我遇到过几个典型问题XPath失效B站前端改版导致定位失效。解决方案是使用更宽松的定位策略比如用contains()匹配class名而不是完整路径。分页中断有时采集到第5页就停止了。后来发现是因为页码参数有特殊处理需要在URL中添加oxxx参数。数据不全部分视频信息加载较慢。可以尝试添加等待时间或使用Selenium等工具。一个健壮的采集脚本应该包含这些功能自动重试机制断点续采功能日志记录系统数据去重处理最后提醒一点采集数据时要注意遵守网站的使用条款控制请求频率避免对服务器造成过大压力。