You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用bs4爬取YouTube趋势视频时find_all返回空列表,如何修复?

解决YouTube热门视频爬取返回空列表的问题

问题原因

  1. 动态内容渲染:YouTube的页面内容是通过JavaScript动态生成的,requests.get()只能获取初始的静态HTML文档,此时视频对应的ytd-video-renderer元素还未被渲染出来,所以BeautifulSoup找不到目标元素。
  2. 反爬机制拦截:直接用requests请求可能会被YouTube识别为非浏览器请求,返回的内容不完整或被限制。

解决方案

方法一:用Selenium模拟浏览器加载动态内容

Selenium可以模拟真实浏览器的行为,等待页面完全加载后再获取源码,这样就能拿到包含视频元素的完整HTML。

  1. 先安装依赖:
pip install selenium

同时需要下载对应浏览器的驱动(比如ChromeDriver,要和你的Chrome版本匹配),并配置到系统路径中。

  1. 示例代码:
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

# 初始化Chrome浏览器驱动
driver = webdriver.Chrome()
driver.get("https://www.youtube.com/feed/explore")

# 等待页面加载完成,确保目标元素出现
try:
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.TAG_NAME, "ytd-video-renderer"))
    )
    time.sleep(2)  # 额外等待确保内容加载完全
    page_source = driver.page_source
    soup = BeautifulSoup(page_source, "lxml")
    trendings = soup.find_all("ytd-video-renderer", attrs={"class": "style-scope ytd-expanded-shelf-contents-renderer"})
    print(f"找到{len(trendings)}个热门视频")
    # 遍历输出视频标题
    for video in trendings:
        title = video.find("yt-formatted-string", id="video-title")
        if title:
            print(title.text.strip())
finally:
    driver.quit()  # 关闭浏览器

方法二:使用YouTube Data API(更合规)

直接爬取YouTube网页可能违反其服务条款,使用官方API是更稳妥的方式,还能获取结构化的视频数据。

  1. 准备工作:
  • 前往Google Cloud控制台创建项目,启用YouTube Data API v3,生成专属API密钥。
  • 确保已安装requests:pip install requests
  1. 示例代码:
import requests

API_KEY = "你的API密钥"
# 获取美国地区热门视频,可修改regionCode参数切换地区(如CN代表中国)
url = f"https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&chart=mostPopular&regionCode=US&maxResults=20&key={API_KEY}"

response = requests.get(url)
if response.status_code == 200:
    data = response.json()
    for item in data["items"]:
        title = item["snippet"]["title"]
        view_count = item["statistics"]["viewCount"]
        print(f"标题:{title},播放量:{view_count}")
else:
    print(f"请求失败,状态码:{response.status_code}")

原代码的小问题

  • soup.prettify()只是格式化HTML内容,不会修改原soup对象,这行代码可以直接去掉,不影响结果。
  • 即使静态HTML里存在目标元素,类名也可能随YouTube页面更新而变化,但核心问题还是动态加载导致的元素缺失。

内容的提问来源于stack exchange,提问作者Dilara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:36:19