最近在学习新领域,想分析油管频道的视频,就想到写 Python 爬虫。目前我只爬取所有视频的标题。
实现方式:不用 RSS、官方 API 或 yt-dlp,直接从网页 HTML 获取视频标题并生成 CSV。
- 基于 RSSHub 爬取更简单,但 RSS 只返回 50 个结果,不够用。
- 官方 API 比较麻烦,这次使用量较小,不打算用。
- yt-dlp 网上推荐很多,我尝试后发现不太适合我这次的需求,后续需要再学习。
爬虫实现相对容易是因为油管平台开放包容,反爬力度较小。正如油管对 RSS 一直很友好,感谢油管平台以及优秀内容创作者!我这里展示的脚本仅用于个人学习和技术交流,非商业目的。
背景与使用场景
在分析一个频道时,可能希望快速获取所有视频的标题,例如:
- 做内容统计或主题分析
- 构建视频列表、生成数据 CSV
- 快速了解某个创作者的输出风格
(以小 lin 说频道为例)
可行方案 — Selenium 模拟浏览器
Selenium 是 Python 中常用的浏览器自动化工具,可以模拟用户操作,适合抓取需要滚动加载的网页内容。
- 官方文档:www.selenium.dev/documentati…
- 安装指令:
pip install selenium
- Chrome WebDriver 下载:chromedriver.chromium.org/downloads
实现步骤
- 打开频道视频页
- 模拟滚动到底部,加载所有视频
- 获取页面标题
- 保存为 CSV
思路:
ytd-grid-video-renderer已更新为ytd-rich-grid-media,兼容 2025 年最新布局- 视频需要滚动并等待 DOM 渲染,等待时间延长到 15 秒
- 滚动加载全部视频
- CSV 使用 UTF-8 BOM 保存,中文不会乱码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import csv
import time
channel_id = "xiao_lin_shuo" # 设置频道名称
channel_url = f"https://www.youtube.com/@{channel_id}/videos"
output_file = "youtube_titles.csv"
options = Options()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
options.add_argument("--log-level=3")
driver = webdriver.Chrome(options=options)
driver.get(channel_url)
# 等待至少一个视频加载出来
wait = WebDriverWait(driver, 15)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "ytd-rich-grid-media")))
# 滚动到底部,加载所有视频
last_height = driver.execute_script("return document.documentElement.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);")
time.sleep(2) # 等待新视频加载
new_height = driver.execute_script("return document.documentElement.scrollHeight")
if new_height == last_height:
break
last_height = new_height
# 获取视频标题
titles_elements = driver.find_elements(By.CSS_SELECTOR, "ytd-rich-grid-media #video-title")
titles = [t.text.strip() for t in titles_elements if t.text.strip()]
# 保存 CSV(UTF-8 BOM 避免中文乱码)
with open(output_file, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerow(["Title"])
for t in titles:
writer.writerow([t])
print(f"共抓取 {len(titles)} 个视频标题,已保存到 {output_file}")
driver.quit()
运行输出
共抓取 141 个视频标题,已保存到 youtube_titles.csv
期间遇到的问题
分享一些实践经验:
- 基于 RSSHub 爬取只能返回前 50 个,不容易扩展修改,因此直接换方法
- yt-dlp 在解析视频流时不断输出警告(SABR streaming、ffmpeg 未安装),而我们只想抓标题,不下载视频
- 只用简单 requests 方法,翻页请求返回 410 Gone,因为 YouTube 已废弃
/browse_ajax接口,旧方法无法继续获取 continuation token - 现在唯一可行的方法是模拟浏览器行为加载完整页面,因此选择了 Selenium 版本
附加 RSSHub 方法
虽然 RSSHub 方法只能返回最新的 50 个结果,但实现简单,也分享给大家:
import csv
import requests
import xml.etree.ElementTree as ET
channel_id = "xiao_lin_shuo" # 设置频道名
rss_url = f"https://rsshub.app/youtube/user/@{channel_id}"
output_file = "youtube_titles.csv"
# 获取 RSS 数据
response = requests.get(rss_url)
response.raise_for_status()
# 解析 XML
root = ET.fromstring(response.content)
# 提取视频标题
titles = [item.find("title").text for item in root.findall(".//item") if item.find("title") is not None]
# 写入 CSV
with open(output_file, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerow(["Title"])
for title in titles:
writer.writerow([title])
print(f"✅ 已保存 {len(titles)} 个视频标题到 {output_file}")
运行输出
✅ 已保存 50 个视频标题到 youtube_titles.csv
这次的 Selenium 实现版本只是刚好够用,还有许多改进空间,比如没有异步加速、爬取中没有计时输出、只爬取视频标题等等。之后有需要再改进。
最后再次感谢油管平台以及优秀内容创作者,在越来越封闭的网络生态下仍坚持互联互通!
接下来,我会分享更多帮助个人学习工作的轻量级脚本工具。