python实现YouTube关键词爬虫(2025/02/11)

在当今数字化时代,YouTube作为全球最大的视频分享平台之一,拥有海量的视频资源。无论是进行市场调研、内容创作还是学术研究,能够高效地获取YouTube上的相关视频信息都显得尤为重要。今天,我将为大家介绍一个基于Python实现的YouTube视频搜索爬虫,帮助大家快速获取特定关键词相关的视频基本信息。

废话不多说,先上结果:

一、项目背景与需求

随着信息的爆炸式增长,如何从海量的YouTube视频中快速找到符合特定需求的内容成为了一个挑战。例如,对于内容创作者来说,了解某一热门话题下的视频趋势和优秀作品能够为自己的创作提供灵感;对于市场研究人员而言,分析特定品牌或产品的相关视频数据有助于洞察市场动态和用户反馈。因此,开发一个能够自动搜索并提取YouTube视频信息的爬虫工具具有重要的应用价值。

二、技术选型与实现思路

1.技术选型

  • Python语言:Python以其简洁易读的语法和强大的库支持,成为了爬虫开发的首选语言。它提供了丰富的网络请求库(如requests)、数据处理库(如pandas)以及JSON解析等功能,能够高效地实现爬虫的各项功能。

  • requests:用于发送HTTP请求,获取YouTube网页的响应数据。它支持自定义请求头、参数和数据,能够灵活地模拟浏览器行为,从而获取到我们需要的视频搜索结果数据。

  • pandas:主要用于数据的存储和处理。在爬取到视频信息后,我们可以将其存储为DataFrame对象,方便后续的数据分析、筛选和导出为CSV文件等操作。

2.实现思路

  • 模拟搜索请求:通过分析YouTube的搜索功能,我们发现其搜索结果是通过向特定的API接口发送请求并携带相应的参数和数据来获取的。因此,我们需要构造类似的请求,包括设置合适的请求头(如User-AgentReferer等)、参数(如搜索关键词、分页令牌等)以及请求体(包含搜索的上下文信息等),以模拟用户在浏览器中进行搜索的行为。

  • 解析响应数据:YouTube返回的搜索结果数据是JSON格式的,其中包含了视频的基本信息,如视频链接、标题、播放量、发布时间、作者昵称和主页链接等。我们需要编写解析逻辑,从JSON数据中提取出这些有用的信息,并将其整理成结构化的数据格式,以便后续的存储和分析。

  • 分页爬取与数据存储:由于YouTube的搜索结果通常会有很多页,为了完整地获取所有相关视频信息,我们需要实现分页爬取的功能。在每次请求中,我们可以通过解析返回数据中的分页令牌来判断是否存在下一页,并循环发送请求直到获取到所有页面的数据。同时,我们将爬取到的视频数据存储到CSV文件中,方便用户后续查看和使用。

三、代码实现

1.发送搜索请求

我们实现了get方法,用于发送搜索请求并获取YouTube的响应数据。在这个方法中,我们根据是否是首次请求(通过token参数判断),构造不同的请求体数据。首次请求时,我们直接传递搜索关键词;后续分页请求时,则使用分页令牌来获取下一页的数据。

def get(self, keyword, token):
    url = "https://www.youtube.com/youtubei/v1/search"
    params = {
        "prettyPrint": "false"
    }
    if token != "-1":
        data = {
            "context": {
                "client": {
                    "hl": "zh-CN",
                    "gl": "HK",
                    "remoteHost": "103.17.98.17",
                    "deviceMake": "",
                    "deviceModel": "",
                    "visitorData": "CgthSS1jZ09JTTY3ayj44Iy9BjIKCgJISxIEGgAgWg%3D%3D",
                    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36,gzip(gfe)",
                    "clientName": "WEB",
                    "clientVersion": "2.20250203.06.01",
                    "osName": "Windows",
                    "osVersion": "10.0",
                    "originalUrl": f"https://www.youtube.com/results?search_query={quote(keyword)}&themeRefresh=1",
                    "platform": "DESKTOP",
                    "clientFormFactor": "UNKNOWN_FORM_FACTOR",
…………}
    else:
        data = {
            "context": {
                "client": {
                    "hl": "zh-CN",
                    "gl": "HK",
                    "remoteHost": "103.17.98.17",
                    "deviceMake": "",
                    "deviceModel": "",
                    "visitorData": "CgthSS1jZ09JTTY3ayj44Iy9BjIKCgJISxIEGgAgWg%3D%3D",
                    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36,gzip(gfe)",
                    "clientName": "WEB",
                    "clientVersion": "2.20250203.06.01",
                    "osName": "Windows",
                    "osVersion": "10.0",
                    "originalUrl": f"https://www.youtube.com/results?search_query={quote(keyword)}",
                    "platform": "DESKTOP",
                    "clientFormFactor": "UNKNOWN_FORM_FACTOR",
…………}
    data = json.dumps(data, separators=(',', ':'))
    response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data, timeout=(3, 10))
    return response.json()

2.解析响应数据

在获取到YouTube的响应数据后,我们需要从中提取出有用的视频信息。这部分逻辑由parse_data方法实现。我们首先解析出视频的基本信息,如视频链接、标题、播放量、发布时间、作者昵称和主页链接等,并将这些信息存储到一个列表中。同时,我们还会尝试从响应数据中获取分页令牌,以便后续进行分页爬取。

def parse_data(self, keyword, contents):
    token = None
    contents_1 = contents[0]['itemSectionRenderer']['contents']
    result_list = []
    for c in contents_1:
        videoRenderer = c.get('videoRenderer')
        if videoRenderer:
            videoId = videoRenderer.get('videoId')
            video_url = f"https://www.youtube.com/watch?v={videoId}"
            title = "".join([tt['text'] for tt in videoRenderer['title'].get('runs', [])])
            viewCountText = videoRenderer.get('viewCountText', {}).get('simpleText', '')
            publishedTimeText = videoRenderer.get('publishedTimeText', {}).get('simpleText', '')
            username = videoRenderer['ownerText']['runs'][0]['text']
            uid_ = videoRenderer['ownerText']['runs'][0]['navigationEndpoint']['browseEndpoint']['canonicalBaseUrl']
            p_url = f"https://www.youtube.com{uid_}"
            item = {
                "关键词": keyword,
                "视频链接": video_url,
                "标题": title,
                "发布时间": publishedTimeText,
                "播放量": viewCountText,
                "昵称": username,
                "主页链接": p_url,
            }
            self.log(f"找到视频:{title}")
            result_list.append(item)

    try:
        token = contents[1]['continuationItemRenderer']['continuationEndpoint']['continuationCommand']['token']
    except:
        pass
    if result_list:
        self.save_data(self.saveFileName, result_list)

    return token

3.主逻辑与分页爬取

最后,我们实现了run方法和main方法。run方法用于控制爬虫的运行逻辑,包括发送搜索请求、解析响应数据、存储数据以及分页爬取等功能。main方法则用于读取关键词文件,并依次对每个关键词启动爬虫。

 

def run(self, keyword, token="-1"):
    self.current_token = token
    self.saveFileName = keyword

    while self.is_running and self.current_token:
        try:
            # 检查页数限制
            if self.max_pages and self.current_page >= self.max_pages:
                self.log(f"已达到设定的{self.max_pages}页限制,停止爬取")
                break

            self.log(f"正在爬取第 {self.current_page + 1} 页")
            dataJson = self.get(keyword, self.current_token)
            if self.current_token == "-1":
                contents = dataJson["contents"]["twoColumnSearchResultsRenderer"]["primaryContents"]["sectionListRenderer"]["contents"]
            else:
                contents = dataJson["onResponseReceivedCommands"][0]["appendContinuationItemsAction"]["continuationItems"]
            self.current_token = self.parse_data(keyword, contents)
            self.current_page += 1
        except Exception as e:
            self.log(f"发生错误:{str(e)}")
            break

def main(self):
    keyword_list = [k.strip() for k in open('关键词.txt', encoding='utf-8').readlines() if k.strip() != ""]
    xuhao = 0
    for index, keyword in enumerate(keyword_list[xuhao:], xuhao):
        print((index, keyword))
        self.run(keyword)

 

四、总结

通过以上代码的实现,我们成功地开发了一个能够自动搜索并提取YouTube视频信息的爬虫工具。它可以帮助我们快速获取特定关键词相关的视频数据,并将其存储到CSV文件中,方便后续的分析和使用。在实际应用中,我们还可以根据需求对爬虫进行进一步的优化和扩展,例如增加代理支持、设置爬取频率等,以提高爬虫的稳定性和效率。


希望这篇文章能够帮助你更好地理解和实现YouTube视频搜索爬虫。如果有任何问题或建议,欢迎在评论区留言交流!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/969277.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins 配置 Git Parameter 四

Jenkins 配置 Git Parameter 四 一、开启 项目参数设置 勾选 This project is parameterised 二、添加 Git Parameter 如果此处不显示 Git Parameter 说明 Jenkins 还没有安装 Git Parameter plugin 插件,请先安装插件 Jenkins 安装插件 三、设置基本参数 点击…

自然语言处理NLP入门 -- 第三节词袋模型与 TF-IDF

目标 了解词袋模型(BoW)和 TF-IDF 的概念通过实际示例展示 BoW 和 TF-IDF 如何将文本转换为数值表示详细讲解 Scikit-learn 的实现方法通过代码示例加深理解归纳学习难点,并提供课后练习和讲解 3.1 词袋模型(Bag of Words, BoW&a…

C++模板编程——typelist的实现

文章最后给出了汇总的代码,可直接运行 1. typelist是什么 typelist是一种用来操作类型的容器。和我们所熟知的vector、list、deque类似,只不过typelist存储的不是变量,而是类型。 typelist简单来说就是一个类型容器,能够提供一…

fastadmin 接口请求提示跨域

问题描述 小程序项目,内嵌h5页面,在h5页面调用后端php接口,提示跨域。网上查找解决方案如下: 1,设置header // 在入口文件index.php直接写入直接写入 header("Access-Control-Allow-Origin:*"); header(&q…

只需三步!5分钟本地部署deep seek——MAC环境

MAC本地部署deep seek 第一步:下载Ollama第二步:下载deepseek-r1模型第三步:安装谷歌浏览器插件 第一步:下载Ollama 打开此网址:https://ollama.com/,点击下载即可,如果网络比较慢可使用文末百度网盘链接 注:Ollama是…

idea 错误: 找不到或无法加载主类 @C:\Users\admin\AppData\Local\Temp\idea_arg_file1549212448

idea 错误: 找不到或无法加载主类 C:\Users\admin\AppData\Local\Temp\idea_arg_file1549212448 该错误往往和左下角爱弹出的如下提示是一个意思 Error running ‘PayV3Test1.testTransferBatchesBatchId’ Error running PayV3Test1.testTransferBatchesBatchId. Command lin…

Excel 笔记

实际问题记录 VBA脚本实现特殊的行转列 已知:位于同一Excel工作簿文件中的两个工作表:Sheet1、Sheet2。 问题:现要将Sheet2中的每一行,按Sheet1中的样子进行转置: Sheet2中每一行的黄色单元格,为列头。…

【故障处理】- ora-39126

【故障处理】- ora-39126 一、概述二、报错原因三、解决方法 一、概述 使用xtts迁移源端12.1.0.2版本,进行全库导入时(目标端19c),报错ORA-39126. 二、报错原因 根据mos反馈,是数据库bug导致,该bug会在20.…

C#运动控制——轴IO映射

1、IO映射的作用 该功能允许用户对专用 IO 信号的硬件输入接口进行任意配置,比如轴的急停信号,通过映射以后,可以将所有轴的急停信号映射到某一个IO输入口上,这样,我们只要让一个IO信号有效就可以触发所有轴的急停。 进…

MongoDB 扩缩容实战:涵盖节点配置、服务启动与移除操作

#作者:任少近 文章目录 一、扩容在245节点上配置配置config server:配置mongos启动config server安装工具mongosh添加245新节点到副本集配置分片副本集启动路由并分片 二、缩容Conf server上去掉server4shard上去掉server4mongos上去掉server4 一、扩容…

【NLP】第十一章:隐马尔可夫模型 HMM (Hidden Markov Model)

本来是想讲BERT的,但是BERT的重点是部署应用,而且用BERT跑一些NLP领域的很多任务时,一般做法都是BERT后面再串一个概率模型来约束输出,比如串联一个条件随机场CRF模型。而我们还没讲CRF呢,而且要了解CRF需要首先了解隐…

APP端网络测试与弱网模拟!

当前APP网络环境比较复杂,网络制式有2G、3G、4G网络,还有越来越多的公共Wi-Fi。不同的网络环境和网络制式的差异,都会对用户使用app造成一定影响。另外,当前app使用场景多变,如进地铁、上公交、进电梯等,使…

使用k3s高可用部署rancher

本次部署采用3节点的etcd服务2master节点的k3s使用helm部署的ranchervip(keepalived) 一、安装etcd服务 # 准备 3 个节点部署 etcd cd /hskj/tmp wget https://github.com/etcd-io/etcd/releases/download/v3.3.15/etcd-v3.3.15-linux-amd64.tar.gz tar xzvf etcd-v3.3.15-…

Nginx进阶篇 - nginx多进程架构详解

文章目录 1. nginx的应用特点2. nginx多进程架构2.1 nginx多进程模型2.2 master进程的作用2.3 进程控制2.4 worker进程的作用2.5 worker进程处理请求的过程2.6 nginx处理网络事件 1. nginx的应用特点 Nginx是互联网企业使用最为广泛的轻量级高性能Web服务器,其特点是…

uniapp开发h5部署到服务器

1.发行>网站-PC Web或手机H5(仅适用于uniapp) 2.填写网站域名 3.编译成功后会生成一个unpackage文件夹找到下面的h5 4.接下来会使用一个工具把h5里面的文件放到服务器上面(WinSCP使用其他能部署的工具也行) 5.登录 6.登录成功后…

【C/C++算法】从浅到深学习---滑动窗口(图文兼备 + 源码详解)

绪论:冲击蓝桥杯一起加油!! 每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 绪论​: 本章是算法训练的第二章----滑动窗口,它的本质是双指针算法的衍生所以我将…

AWTK-WEB 快速入门(4) - JS Http 应用程序

XMLHttpRequest 改变了 Web 应用程序与服务器交换数据的方式,fetch 是 XMLHttpRequest 继任者,具有更简洁的语法和更好的 Promise 集成。本文介绍一下如何使用 JS 语言开发 AWTK-WEB 应用程序,并用 fetch 访问远程数据。 用 AWTK Designer 新…

html 点击弹出视频弹窗

一、效果: 点击视频按钮后,弹出弹窗 播放视频 二、代码 <div class="index_change_video" data-video-src="</

FPGA实现UltraScale GTH光口视频转USB3.0传输,基于FT601+Aurora 8b/10b编解码架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 GT 高速接口解决方案本博已有的FPGA驱动USB通信方案 3、工程详细设计方案工程设计原理框图输入Sensor之-->OV5640摄像头动态彩条输入视频之-->ADV…

HCIA项目实践--静态路由的总结和简单配置

七、静态路由 7.1 路由器获取未知网段的路由信息&#xff1a; &#xff08;1&#xff09;静态路由&#xff1a;网络管理员手工配置的路由条目&#xff0c;它不依赖网络拓扑的变化进行自动更新&#xff0c;而是根据管理员预先设定的路径来转发数据包。其优点是配置简单、占用系…