使用C#和HtmlAgilityPack打造强大的Snapchat视频爬虫

news2024/12/23 0:42:50

亿牛云代理.png

概述

Snapchat作为一款备受欢迎的社交媒体应用,允许用户分享照片和视频。然而,由于其特有的内容自动消失特性,爬虫开发面临一些挑战。本文将详细介绍如何巧妙运用C#和HtmlAgilityPack库,构建一个高效的Snapchat视频爬虫。该爬虫能够从Snapchat网页版中提取视频链接,并将其下载保存到本地。为了提升爬虫的效率和可靠性,我们将使用代理IP技术和多线程技术,以规避Snapchat的反爬机制。

细节

C#和HtmlAgilityPack库

C#作为一门功能强大、易用的面向对象编程语言,适用于各类应用程序的开发。C#可以在.NET Framework或.NET Core上运行,这两者提供了丰富的类库和工具,方便开发者进行应用开发。

HtmlAgilityPack是一款专为.NET平台设计的HTML解析库,支持XPath和LINQ查询,能够轻松从HTML文档中提取数据。其强大之处在于能够处理不规范的HTML结构,同时支持对HTML文档结构和内容进行修改。HtmlAgilityPack是一个开源项目,源码和文档可在其官方网站查阅。

为使用HtmlAgilityPack库,我们需在Visual Studio中创建一个控制台应用项目,通过NuGet包管理器安装HtmlAgilityPack库。NuGet是.NET平台的包管理工具,可便捷管理项目依赖关系。

代理IP技术

代理IP技术是一种隐藏真实IP地址的方法,通过中间服务器访问目标网站,既可保护隐私安全,又能绕过地域限制和反爬机制,提高爬虫的成功率和效率。爬虫代理是一个专业服务平台,提供高质量的代理IP资源,支持多种协议和认证方式,适用于各种爬虫场景。

在C#中,使用HttpClient对象发送请求,可通过设置Proxy属性指定代理服务器的地址和认证信息,以实现代理IP的应用。

多线程技术

多线程技术是提高程序性能的有效手段,可同时执行多个任务,最大程度利用CPU资源,提高响应速度和吞吐量。对于爬虫而言,多线程技术有助于实现并发爬取,提高效率和覆盖范围。

在C#中,可通过创建Task对象,使用Task.Run方法启动新线程执行指定方法,并结合SemaphoreSlim对象限制并发线程数,保证程序稳定性。

Snapchat视频爬虫的实现

Snapchat网页版的地址是https://story.snapchat.com/,通过分析网页结构和请求,我们可以发现Snapchat网页是一个单页应用,使用React框架进行渲染。数据通过Ajax请求获取,其中包括一个token参数用于身份验证。在C#中,我们通过HttpClient对象发送请求,提取并保存token值。

主要请求为https://story.snapchat.com/api/v1/stories,获取故事列表。每个故事有id和title,可根据这些信息筛选感兴趣的故事。为获取故事的视频,需发送https://story.snapchat.com/api/v1/story/{story_id}请求,其中{story_id}是故事id。使用HttpClient对象发送这些请求,HtmlAgilityPack解析返回的JSON数据,提取视频链接,再用HttpClient对象下载并保存视频到本地。

为提升效率,采用多线程技术,为每个故事创建一个线程同时获取和下载视频。通过SemaphoreSlim对象控制线程数量,以避免Snapchat的反爬机制。

以下是完整代码,包含中文注释,可在Visual Studio中运行测试:

using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using HtmlAgilityPack;

namespace SnapchatVideoCrawler
{
    class Program
    {
        // 定义HttpClient对象,用于发送和接收HTTP请求和响应
        static HttpClient httpClient = new HttpClient();

        // 定义HtmlDocument对象,用于解析HTML文档
        static HtmlDocument htmlDocument = new HtmlDocument();

        // 定义SemaphoreSlim对象,用于控制并发线程数
        static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(10);

        // 定义Snapchat网页版的网址
        static string snapchatUrl = "https://story.snapchat.com/";

        // 定义Snapchat的token值,用于验证身份,需要从浏览器的本地存储中获取
        static string snapchatToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzbmFwY2hhdCIsInN1YiI6ImFub255bW91cyIsImF1ZCI6InN0b3J5LnNuYXBjaGF0LmNvbSIsImlhdCI6MTYxNjQ4MjE3NCwiZXhwIjoxNjE2NTY4NTc0LCJqdGkiOiI1ZjYyYzQ4Zi1kYjQyLTQ3ZjUtYjEzZC0wZjQwZjEzZjIwYjgifQ.0t7gqf7Z8p0VZyXQy0sXnOa7l0o0Z8fZ6Z0T0f0f0f0";

        // 定义亿牛云爬虫代理的域名、端口、用户名和密码,需要从官网获取
        static string proxyHost = "http://www.16yun.cn";
        static int proxyPort = 9010;
        static string proxyUser = "16YUN";
        static string proxyPass = "16IP";

        // 定义视频保存的文件夹路径
        static string videoFolder = @"C:\SnapchatVideos\";

        static async Task Main(string[] args)
        {
            // 创建视频保存的文件夹,如果不存在
            Directory.CreateDirectory(videoFolder);

            // 设置HttpClient对象的默认请求头,添加token值
            httpClient.DefaultRequestHeaders.Add("token", snapchatToken);

            // 获取Snapchat的故事列表
            var stories = await GetStoriesAsync();

            // 遍历每个故事
            foreach (var story in stories)
            {
                // 获取故事的id和title
                var storyId = story.Id;
                var storyTitle = story.Title;

                // 打印故事的信息
                Console.WriteLine($"Story: {storyTitle} ({storyId})");

                // 创建并启动一个新的线程,执行GetAndDownloadVideos方法,传入故事的id和title
                Task.Run(() => GetAndDownloadVideos(storyId, storyTitle));
            }

            // 等待所有线程完成
            await semaphoreSlim.WaitAsync();
            semaphoreSlim.Release();

            // 打印完成信息
            Console.WriteLine("All videos downloaded!");
        }

        // 定义一个异步方法,用于获取Snapchat的故事列表
        static async Task<HtmlNodeCollection> GetStoriesAsync()
        {
            // 定义Snapchat的故事列表的请求地址
            string storiesUrl = snapchatUrl + "api/v1/stories";

            // 发送GET请求,获取故事列表的JSON数据
            var storiesJson = await httpClient.GetStringAsync(storiesUrl);

            // 使用HtmlDocument对象解析JSON数据,返回一个HtmlNode对象
            var storiesNode = htmlDocument.Parse(storiesJson);

            // 使用XPath查询,从HtmlNode对象中提取故事列表,返回一个HtmlNodeCollection对象
            var stories = storiesNode.SelectNodes("//stories/story");

            // 返回故事列表
            return stories;
        }

        // 定义一个异步方法,用于获取并下载一个故事的视频
        static async Task GetAndDownloadVideos(string storyId, string storyTitle)
        {
            // 使用SemaphoreSlim对象的WaitAsync方法,尝试进入该区域,如果成功则返回一个Task对象,否则等待直到有空位
            await semaphoreSlim.WaitAsync();

            try
            {
                // 定义一个故事的详细信息的请求地址,使用故事的id替换占位符
                string storyUrl = snapchatUrl + $"api/v1/story/{storyId}";

                // 创建一个新的HttpClient对象,用于发送该请求
                var storyClient = new HttpClient();

                // 设置HttpClient对象的默认请求头,添加token值
                storyClient.DefaultRequestHeaders.Add("token", snapchatToken);

                // 创建一个新的WebProxy对象,用于设置代理服务器的地址和认证信息,使用亿牛云爬虫代理的域名、端口、用户名和密码
                var proxy = new WebProxy(proxyHost, proxyPort);
                proxy.Credentials = new NetworkCredential(proxyUser, proxyPass);

                // 设置HttpClient对象的Proxy属性,指定代理服务器
                storyClient.Proxy = proxy;

                // 发送GET请求,获取故事的详细信息的JSON数据
                var storyJson = await storyClient.GetStringAsync(storyUrl);

                // 使用HtmlDocument对象解析JSON数据,返回一个HtmlNode对象
                var storyNode = htmlDocument.Parse(storyJson);

                // 使用XPath查询,从HtmlNode对象中提取视频列表,返回一个HtmlNodeCollection对象
                var videos = storyNode.SelectNodes("//story/snaps/snap/media/video");

                // 遍历每个视频
                foreach (var video in videos)
                {
                    // 获取视频的链接
                    var videoUrl = video.GetAttributeValue("url", "");

                    // 打印视频的链接
                    Console.WriteLine($"Video: {videoUrl}");

                    // 下载并保存视频到本地,使用故事的title和视频的url作为文件名
                    await DownloadVideoAsync(videoUrl, videoFolder + storyTitle + "_" + videoUrl.Split('/').Last());
                }
            }
            catch (Exception ex)
            {
                // 如果发生异常,打印异常信息
                Console.WriteLine($"Error: {ex.Message}");
            }
            finally
            {
                // 使用SemaphoreSlim对象的Release方法,离开该区域,释放一个空位
                semaphoreSlim.Release();
            }
        }

        // 定义一个异步方法,用于下载并保存一个视频
        static async Task DownloadVideoAsync(string videoUrl, string videoPath)
        {
            // 创建一个新的HttpClient对象,用于发送该请求
            var videoClient = new HttpClient();

            // 设置HttpClient对象的默认请求头,添加token值
            videoClient.DefaultRequestHeaders.Add("token", snapchatToken);

            // 创建一个新的WebProxy对象,用于设置代理服务器的地址和认证信息,使用亿牛云爬虫代理的域名、端口、用户名和密码
            var proxy = new WebProxy(proxyHost, proxyPort);
            proxy.Credentials = new NetworkCredential(proxyUser, proxyPass);

            // 设置HttpClient对象的Proxy属性,指定代理服务器
            videoClient.Proxy = proxy;

            // 发送GET请求,获取视频的字节数据
            var videoBytes = await videoClient.GetByteArrayAsync(videoUrl);

            // 使用File类的WriteAllBytes方法,将视频的字节数据写入到指定的文件路径
            File.WriteAllBytes(videoPath, videoBytes);
        }
    }
}

结束语

通过本文,我们深入探讨了如何使用C#和HtmlAgilityPack库构建一个高效的Snapchat视频爬虫。代理IP技术和多线程技术的巧妙应用使得爬虫更具稳定性和高效性。希望这篇文章对你理解爬虫技术和应用有所帮助,欢迎在实际项目中应用并根据需要进行定制。祝愿你的爬虫项目取得圆满成功!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JOSEF约瑟 大功率抗干扰继电器\NR0521\220VDC 导轨安装

NR系列大功率继电器 系列型号&#xff1a; NR0521B大功率继电器 NR0521A大功率继电器 NR0521型大功率继电器 用途 大功率继电器NR0521220VDC 导轨安装在电力工程实际应用中&#xff0c;为防止母线电压经过PT二次侧反馈至高压侧&#xff0c;需要在PT二次侧串接PT刀闸重动接…

SAP SD 创建交货单 报错 VL461 VL248

因为生产环境已经被改好了&#xff0c;无法跟踪 所以换到测试环境重现一把&#xff0c;如何追根究底 对比正常订单发现 计划行 VBEP-LMENG,VBEP-BMENG这两个字段上的值跟 订单数量不一致。 尝试修改2者的数据跟订单数据一致&#xff0c;则可以正常创建交货单 实际原因是&a…

app广告变现如何提高变现收益?提高广告点击率

在广告变现实践过程中&#xff0c;我们往往会遇到一些问题&#xff0c;比如广告的填充不够、eCPM太低&#xff0c;该展示的广告没有展示出来&#xff0c;又或者广告位选择不合理导致用户负面反馈变多&#xff0c;这些种种问题都会影响我们的广告变现效率。 广告三大要素&#…

16.9%份额,启明星辰集团连续21年IDS/IPS排名第一

近日&#xff0c;赛迪顾问发布《2022-2023年中国网络信息安全市场研究年度报告》。报告显示&#xff1a;2022年&#xff0c;启明星辰集团IDS/IPS以16.9%的份额占据市场第一。至今&#xff0c;启明星辰集团IDS/IPS已连续21年保持市场占有率第一。 多年来&#xff0c;启明星辰集团…

postman打开白屏

现状&#xff1a;postman打开白屏如下图 window环境变量&#xff1a; Win R 快捷键打开 sysdm.cpl 增加环境变量&#xff1a; 变量名&#xff1a;POSTMAN_DISABLE_GPU 值&#xff1a;true 重新打开postman

Aurora8B10B(一) 从IP配置界面学习Aurora

一. 简介 哈喽&#xff0c;大家好&#xff0c;好久没有给大家写FPGA技术的文章&#xff0c;是不是已经忘记我是做FPGA的啦&#xff0c;O(∩_∩)O哈哈~。 这里将会给大家分享我学习到的第一个高速接口Aurora8B10B&#xff0c;有点复杂&#xff0c;但不是特别复杂&#xff0c;对…

WPF实战项目十八(客户端):添加新增、查询、编辑功能

1、ToDoView.xmal添加引用&#xff0c;添加微软的行为类 xmlns:i"http://schemas.microsoft.com/xaml/behaviors" 2、给项目添加行为 <i:Interaction.Triggers><i:EventTrigger EventName"MouseLeftButtonUp"><i:InvokeCommandAction Com…

软件开发:基础源代码分享与入门指南

一、引言 软件开发是当今信息时代的一个热门领域&#xff0c;广泛应用于各个行业和领域&#xff0c;本文将向大家介绍软件开发的基础知识&#xff0c;并通过分享一些基础源代码&#xff0c;帮助大家更好地入门软件开发。 二、软件开发概述 软件开发是指通过编程语言和开发工…

容器有挂载目录的时候,容器反向生成为镜像,挂载的内容不会保留。只有实打实拷贝进容器的反向生成镜像才会保留。

无容器目录挂载 1、也就是说宿主机未与容器进行路径映射&#xff0c;故我们可以直接使用指令: docker commit 容器名称/容器ID 像名:标签号&#xff0c;把容器保存为镜像; (其中镜像名和标签号是我们随机取的&#xff0c;新镜像名以及我们的标签号!) 2、我们在不能判断容器与宿…

spring RedisTemplate RedisLockRegistry opsForXxx 基本使用总结以及介绍

一、基本介绍 RedisTemplate 为 spring 对 redis 操作的高度封装&#xff0c;基本已经满足所有使用场景。 若存在其他拓展使用我们可以自行封装工具类对基本操作进行组装。 RedisLockRegistry 对 redis 锁的一些封装 二、不同环境下依赖以及基本配置 2.1 spring-boot 下依赖…

【python】当当书籍数据抓取分析与可视化(代码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Java多线程-第20章

Java多线程-第20章 1.创建线程 Java是一种支持多线程编程的编程语言。多线程是指在同一程序中同时执行多个独立任务的能力。在Java中&#xff0c;线程是一种轻量级的子进程&#xff0c;它是程序中的最小执行单元。Java的多线程编程可以通过两种方式实现&#xff1a;继承Threa…

【李肯C语言小册.目录】小册价值、内容目录汇总、加群方法 | 必看收藏.

小册订阅戳这里&#xff1a;【C语言小册 必读】为什么有这份专栏&#xff1f;解决什么问题&#xff1f;有哪些价值&#xff1f;是否值得订阅&#xff1f;-CSDN社区 订阅后&#xff0c;记得加微VX找我&#xff0c;发zhi付截图&#xff0c;备注【C语言小册】&#xff0c;拉你进本…

关于 SLO,我们需要了解什么?

什么是 SLO&#xff1f; SLO&#xff08;Service Level Objective&#xff09;是服务质量目标的短语缩写。它通常指的是维护系统的最高级别的目标&#xff0c;或服务等级协议&#xff08;SLA&#xff09;中的服务质量目标。它能够定义客户和用户在使用软件系统时所期望的服务质…

在直播间抢到好多实惠东东,全靠抖音支付

前不久我特别喜欢的一位主播的直播间做活动,很多我放在购物车里好久的心仪好物都有秒杀惊喜价。更让我开心的是,在拼手速抢这些秒杀好物的时候,我都成功了!这主要是因为我用了抖音支付,付款环节特别丝滑顺畅,让我在抖音的购物体验直接原地提升了几个level! 可能有朋友现在还是…

使用Docker安装Jenkins,解决插件安装失败,版本太低等问题

如果已经遇到插件安装部分失败&#xff0c;Jenkins版本太低&#xff0c;又要换什么清华镜像地址&#xff0c;不要犹豫&#xff0c;直接以下步骤卸载重装就好了 开始安装 yum 更新到最新 yum update到Jenkins官网查找最新的LST版本 最后的版本号一定要带&#xff0c;指定下载具…

9款高效绘图神器,提升你的工作效率

在日常工作或生活中&#xff0c;我们必须绘制各种图表、流程图、思维导图等图形&#xff0c;或者想用画笔描述自己的想法。然而&#xff0c;我们在许多绘图软件面前感到困惑。我们不知道哪个绘图软件好&#xff0c;也没有足够的时间一一尝试 在接下来的空间里&#xff0c;我们…

jmeter做接口自动化测试,你可能只是个新手!

jmeter 这个工具既可以做接口的功能测试&#xff0c;也可以做自动化测试&#xff0c;还可以做性能测试&#xff0c;其主要用途就是用于性能测试。但是&#xff0c;有些公司和个人&#xff0c;就想用 jmeter 来做接口自动化测试。 你有没有想过呢&#xff1f; 下面我就给大家讲…

深入了解小程序设计,六个关键要点全解析!

微信小程序开启了互联网软件的新使用模式。在各种微信小程序争相抢占流量的同时&#xff0c;如何设计微信小程序&#xff1f;让用户感到舒适是设计师在产品设计初期应该考虑的问题。那么如何做好微信小程序的设计呢&#xff1f;即时设计总结了以下设计指南&#xff0c;希望对准…

ProgrammingError: nan can not be used with MySQL

该错误怎么发生的&#xff1f; 我们先在本地创建测试表&#xff1a; CREATE TABLE users_test (id int NOT NULL AUTO_INCREMENT COMMENT 主键,trade_account varchar(50) DEFAULT NULL COMMENT 交易账号,username varchar(50) DEFAULT NULL,email varchar(100) DEFAULT NULL…