记一次使用 Python 爬取 B 站 UP 主信息的经历

记一次使用 Python 爬取 B 站 UP 主信息的经历

使用 Python 编写的 B 站爬虫实战教程。使用 Selenium 和 BeautifulSoup 实现对美食区 UP 主粉丝数、UID 等数据的抓取与分析。

需求

尽可能获取 B 站美食博主列表,按照粉丝数排序,最终目的是能找出粉丝数前列 UP 主的 ID 和昵称。

思路

  • 将几个包含很多美食区视频的网页的 URL 存起来
  • 通过请求 URL 拿到尽可能多的投稿视频的链接
  • 通过视频链接拿到 UP 主的主页链接,并分析出 UP 主的 UID
  • 通过 UID 请求信息接口,拿到 UP 主的 ID 以及粉丝数

用到的库及其作用

  • csv:读写 CSV 文件
  • json:读写 JSON 文件
  • time:进行延时操作
  • random:随机数功能实现
  • codecs:打开文件(解决中文写入文件后乱码问题)
  • requests:HTTP 请求库
  • selenium:模拟浏览器操作
  • fake_useragent:随机 User-Agent 库
  • threading:多线程库
  • BeautifulSoup:解析 HTML 与 XML 的库

遇到的问题以及解决方案

拿不到 HTML 结构

可能是因为没有设置 User-Agent,服务器无法确认请求是否由用户发出。提前设置好请求头 User-Agent(浏览器标识),伪装成浏览器,模拟用户正常请求,防止 IP 被封禁。这里可以自己设置 User-Agent 为指定浏览器标识,也可以用库来随机生成。建议使用 fake_useragent 库来随机生成 User-Agent 标识

安装 fake_useragent

bash
pip install fake_useragent

使用示例:

py
from fake_useragent import UserAgent

UA = UserAgent().random
headers = {'User-Agent': UA}

拿到的 HTML 结构不完整

可能是因为网页动态加载(拿到网页并用浏览器解析之后还需要 JavaScript 来动态更新网页内容),导致拿到的网页 HTML 结构残缺,拿不到想要的数据。可以使用 selenium 库来模拟浏览器爬虫,这样会等到网页加载完全再获取网页的 HTML。

安装 selenium

bash
pip install selenium

下载对应版本的浏览器驱动:

使用示例:

py
from selenium import webdriver

# 创建浏览器实例
browser = webdriver.Chrome()  # Chrome 浏览器
# browser = webdriver.Firefox()  # Firefox 浏览器
# browser = webdriver.Edge()  # Edge 浏览器

# 访问网页
browser.get(url)

# 获取网页 HTML 结构
html = browser.page_source

数据保存和中文乱码问题

为了方便后续处理数据,这里使用 CSV 文件格式存储数据,同时使用 codecs 模块打开文件来防止中文乱码。CSV 格式文件很简单,Excel 也能打开并处理,Python 标准库里有 csv 模块来读写 CSV 格式文件。

注意csvcodecs 都是 Python 标准库的一部分,无需额外安装。

使用示例:

py
import csv
import codecs

filename = "data.csv"

# 'ab' 为追加模式,'wb' 为覆盖模式
csv_file = codecs.open(filename, 'ab', "gbk")

# 创建 CSV 写入器
csv_writer = csv.writer(csv_file)

# 写入表头
csv_writer.writerow(("第一项", "第二项"))

# 写入一行数据
info = (1, 2)
csv_writer.writerow(info)

# 写入多行数据
infos = [(1, 2), (3, 4)]
csv_writer.writerows(infos)

# 关闭文件
csv_file.close()

返回的数据是 JSON 格式

使用 json 模块处理 JSON 数据。

注意json 是 Python 标准库的一部分,无需额外安装。

使用示例:

py
import json

jsonData = '{"name": "Viki"}'

# JSON 字符串转为 Python 字典(或其他数据类型)
data = json.loads(jsonData)
print(data['name'])  # 输出:Viki

# Python 字典(或其他数据类型)转为 JSON 字符串
jsonStr = json.dumps(data)
print(jsonStr)  # 输出:{"name": "Viki"}

爬取速度太慢

使用 threading 模块实现多线程并发爬取。

注意threading 是 Python 标准库的一部分,无需额外安装。

使用示例:

py
import threading

lst = [123, 456, 789]

def double(n):
    result = n * n
    print(f"{n} 的平方是 {result}")
    return result

# 为每个任务创建线程
for n in lst:
    double_thread = threading.Thread(target=double, args=(n,))
    double_thread.start()

完整代码实现

以下是完整的爬虫代码:

注意事项

  • 本代码仅供学习交流使用,请勿用于商业用途
  • 爬取时请注意控制频率,避免对 B 站服务器造成过大压力
  • B 站的页面结构和 API 可能会发生变化,代码需要相应调整
  • 建议添加更完善的异常处理和日志记录

参考资料

新年攒台海景房
绕过 B 站"应版权方要求,本片仅支持 App 观看"的限制