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

使用Requests和BeautifulSoup无法获取YouTube视频时长的问题求助

使用Requests和BeautifulSoup无法获取YouTube视频时长的问题求助

问题描述:

我想通过YouTube视频链接获取视频时长,在浏览器开发者工具里能看到页面上有一个class为ytp-time-duration的span标签(显示着视频时长内容)。

我尝试用requests和BeautifulSoup来抓取这个标签,但不管用find_all还是find都返回空结果,完全找不到这个标签。我的代码如下:

import requests
from bs4 import BeautifulSoup

url = "https://www.youtube.com/watch?v=ANYyoutubeLINK"

response = requests.get(url)
response.raise_for_status()

soup = BeautifulSoup(response.text, 'html.parser')

duration_span = soup.find_all('span', class_='ytp-time-duration')

print(duration_span)

请问这是哪里出问题了?


我的解答:

嘿,这个问题我之前也碰到过!核心原因其实很简单:YouTube的很多页面元素是通过JavaScript动态渲染出来的,你用requests.get()获取的只是服务器返回的初始静态HTML,这个阶段那个ytp-time-duration的span标签还不存在——它是等页面加载完成后,由前端JS动态生成的,所以BeautifulSoup自然找不到它。

给你几个可行的解决方案,按推荐程度排序:

方案1:从页面静态脚本中提取视频信息(无额外依赖)

YouTube会把视频的核心数据(包括时长)打包在页面的<script>标签里,比如ytInitialPlayerResponse这个变量,我们可以直接从静态HTML里匹配提取,不需要依赖动态渲染:

import requests
import re
import json

url = "https://www.youtube.com/watch?v=ANYyoutubeLINK"

response = requests.get(url)
response.raise_for_status()

# 匹配页面中的ytInitialPlayerResponse变量内容
pattern = re.search(r'var ytInitialPlayerResponse = ({.*?});', response.text)
if pattern:
    player_response = json.loads(pattern.group(1))
    # 提取时长(单位为秒)
    duration_seconds = player_response['videoDetails']['lengthSeconds']
    # 转换为友好的时分秒格式
    hours = int(duration_seconds) // 3600
    minutes = (int(duration_seconds) % 3600) // 60
    seconds = int(duration_seconds) % 60
    
    if hours > 0:
        duration = f"{hours}:{minutes:02d}:{seconds:02d}"
    else:
        duration = f"{minutes}:{seconds:02d}"
    print(f"视频时长:{duration}")
else:
    print("无法从页面中提取视频信息")

方案2:用Selenium模拟浏览器加载(适配动态渲染)

如果YouTube更新了页面结构导致方案1失效,可以用Selenium模拟真实浏览器的加载过程,这样就能获取到动态渲染后的元素:

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

url = "https://www.youtube.com/watch?v=ANYyoutubeLINK"

# 初始化Chrome浏览器(需提前安装对应版本的ChromeDriver)
driver = webdriver.Chrome()
driver.get(url)

try:
    # 等待时长元素加载完成(最多等10秒)
    duration_element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, 'ytp-time-duration'))
    )
    print(f"视频时长:{duration_element.text}")
finally:
    # 用完记得关闭浏览器
    driver.quit()

方案3:使用YouTube Data API(最稳定的长期方案)

如果你的需求是长期稳定获取视频信息,官方的Data API是最佳选择,不过需要先申请API密钥(免费额度足够个人使用)。示例代码如下(需先安装google-api-python-client库):

from googleapiclient.discovery import build
import isodate

API_KEY = "你的API密钥"
VIDEO_ID = "替换为视频链接中的v参数值"

# 初始化API客户端
youtube = build('youtube', 'v3', developerKey=API_KEY)

# 请求视频的内容详情
request = youtube.videos().list(
    part="contentDetails",
    id=VIDEO_ID
)
response = request.execute()

# 提取ISO 8601格式的时长并转换为秒
duration_iso = response['items'][0]['contentDetails']['duration']
duration_seconds = isodate.parse_duration(duration_iso).total_seconds()

# 转换为友好格式
hours = int(duration_seconds) // 3600
minutes = (int(duration_seconds) % 3600) // 60
seconds = int(duration_seconds) % 60

if hours > 0:
    duration = f"{hours}:{minutes:02d}:{seconds:02d}"
else:
    duration = f"{minutes}:{seconds:02d}"
print(f"视频时长:{duration}")

总结一下:用requests+BeautifulSoup抓不到是因为元素是动态生成的,优先试试方案1(无需额外工具),如果不行再用Selenium,长期项目推荐用官方API。


备注:内容来源于stack exchange,提问作者Mark K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 14:48:02