当前位置: 首页 > news >正文

用Go的resty库批量下载公开网站视频

用户可能已经了解了一些爬虫的基础知识,现在想用Go来实现更高效或更复杂的任务。Resty是一个HTTP客户端库,适合处理请求,但下载视频需要考虑不同的因素,比如大文件处理、并发控制、可能的反爬机制等。

在这里插入图片描述

需要确认用户是否了解Go语言的基础,或者是否需要代码示例中的详细注释。另外,用户提到的“公开网站视频”需要强调合法性,必须遵守网站的使用条款和robots.txt,避免法律问题。

以下是一个使用Go语言配合resty库进行批量视频下载的示例代码,包含并发控制、错误处理和进度显示:

package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/go-resty/resty/v2"
)

const (
	concurrency    = 3                // 并发下载数量
	downloadDir    = "./videos"       // 下载目录
	userAgent      = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
	requestTimeout = 30 * time.Second // 请求超时时间
)

// 视频下载任务结构
type DownloadTask struct {
	URL      string
	FileName string
}

func main() {
	// 创建下载目录
	if err := os.MkdirAll(downloadDir, 0755); err != nil {
		panic(err)
	}

	// 示例视频URL列表(替换为实际需要下载的URL)
	videoUrls := []string{
		"https://example.com/video1.mp4",
		"https://example.com/video2.mp4",
		"https://example.com/video3.mp4",
	}

	// 创建任务队列
	tasks := make(chan DownloadTask, len(videoUrls))
	
	// 添加下载任务
	go func() {
		defer close(tasks)
		for _, url := range videoUrls {
			tasks <- DownloadTask{
				URL:      url,
				FileName: filepath.Base(url),
			}
		}
	}()

	var wg sync.WaitGroup
	wg.Add(concurrency)

	// 启动工作池
	for i := 0; i < concurrency; i++ {
		go func(workerID int) {
			defer wg.Done()
			client := resty.New().
				SetTimeout(requestTimeout).
				SetHeader("User-Agent", userAgent).
				SetRetryCount(2).
				SetRetryWaitTime(5 * time.Second)

			for task := range tasks {
				downloadVideo(client, task, workerID)
			}
		}(i + 1)
	}

	wg.Wait()
	fmt.Println("\n所有下载任务完成!")
}

// 下载视频文件
func downloadVideo(client *resty.Client, task DownloadTask, workerID int) {
	filePath := filepath.Join(downloadDir, task.FileName)
	
	// 创建文件
	file, err := os.Create(filePath)
	if err != nil {
		fmt.Printf("[Worker %d] 创建文件失败: %s\n", workerID, err)
		return
	}
	defer file.Close()

	// 发起请求
	resp, err := client.R().
		SetDoNotParseResponse(true).
		Get(task.URL)

	if err != nil {
		fmt.Printf("[Worker %d] 请求失败: %s\n", workerID, err)
		return
	}
	defer resp.RawBody().Close()

	// 获取文件大小(可能不可用)
	contentLength := resp.Size()
	
	// 创建进度写入器
	counter := &WriteCounter{
		Total:     contentLength,
		WorkerID:  workerID,
		FileName:  task.FileName,
		StartTime: time.Now(),
	}

	// 写入文件并显示进度
	_, err = io.Copy(file, io.TeeReader(resp.RawBody(), counter))
	if err != nil {
		fmt.Printf("\n[Worker %d] 下载失败: %s\n", workerID, err)
		os.Remove(filePath) // 删除不完整文件
		return
	}

	fmt.Printf("\n[Worker %d] 下载完成: %s\n", workerID, task.FileName)
}

// 进度统计结构
type WriteCounter struct {
	Total     int64
	Downloaded int64
	WorkerID  int
	FileName  string
	StartTime time.Time
}

// 实现Write接口
func (wc *WriteCounter) Write(p []byte) (int, error) {
	n := len(p)
	wc.Downloaded += int64(n)
	wc.printProgress()
	return n, nil
}

// 显示下载进度
func (wc *WriteCounter) printProgress() {
	duration := time.Since(wc.StartTime).Seconds()
	speed := float64(wc.Downloaded) / 1024 / 1024 / duration

	progress := ""
	if wc.Total > 0 {
		percent := float64(wc.Downloaded) / float64(wc.Total) * 100
		progress = fmt.Sprintf("%.2f%% [%.2f MB/s]", percent, speed)
	} else {
		progress = fmt.Sprintf("%.2f MB [%.2f MB/s]", 
			float64(wc.Downloaded)/1024/1024, speed)
	}

	fmt.Printf("\r[Worker %d] %s => %s", 
		wc.WorkerID, wc.FileName, progress)
}

代码说明:

1、核心功能:

  • 并发控制:通过工作池模式控制并发数量
  • 断点续传:通过os.Create直接写入文件(需自行实现断点逻辑)
  • 进度显示:实时显示下载速度和进度
  • 错误重试:内置2次重试机制
  • 超时控制:30秒请求超时

2、使用方法:

# 安装依赖
go get github.com/go-resty/resty/v2

# 运行程序
go run main.go

重要参数调整:

const (
    concurrency    = 5      // 根据网络情况调整并发数
    requestTimeout = 60 * time.Second  // 大文件需要更长时间
)
  1. 注意事项:
    • 遵守目标网站的robots.txt规则
    • 尊重版权和内容使用协议
    • 避免高频请求(可添加time.Sleep
    • 大文件下载建议增加:
      • 断点续传功能
      • MD5校验
      • 代理支持

扩展建议:

添加代理支持:

client.SetProxy("http://proxy-server:port")

增加请求头伪装:

client.SetHeaders(map[string]string{
    "Referer":    "https://example.com",
    "Accept":     "video/webm,video/ogg,video/*;q=0.9",
})

实现断点续传:

// 检查已下载大小
if info, err := os.Stat(filePath); err == nil {
    client.SetHeader("Range", fmt.Sprintf("bytes=%d-", info.Size()))
}

增加文件校验:

// 下载完成后验证
if resp.Size() > 0 && fileInfo.Size() != resp.Size() {
    fmt.Println("文件大小不匹配")
}

请确保遵守目标网站的服务条款,合法合规使用此代码。实际使用时需要根据具体网站的页面结构解析出真实的视频下载地址。

总结下来,用户需要的是一个用Go语言,使用resty库,能够批量下载公开视频的程序。需要包括:并发下载、错误处理、速率限制、Headers设置、文件保存等功能。同时需要提醒法律和道德规范,确保用户遵守目标网站的规定。

相关文章:

  • 基于Python实现的智能旅游推荐系统(Django)
  • 【C++教程】C++中的基本数据类型
  • Amlogic USB Burning Tool v2.2.5_晶晨线刷烧录工具v2.2.5_晶晨S905L3S-S905L3SB芯片_专用线刷烧录工具分享
  • 使用ASIWebPageRequest库编写Objective-C下载器程序
  • python学习笔记-day4(解决实际问题)
  • 我的技术十年
  • SHELL32!CDefView::_OnFSNotify函数是如何被调用的
  • MySQLvs Redis 事务:核心差异详解(简单易懂)
  • 49.日常算法
  • 深入解析MyBatis中一对一与一对多映射的实现方法与区别
  • Golang的代码注释规范指南
  • 计算机毕业设计SpringBoot+Vue.js众筹网站系统(源码+文档+PPT+讲解)
  • JavaScript实现著名的“两数之和”问题
  • C# Enumerable类 之 数据(类型)转换
  • Linux之kernel(1)系统基础理论(5)
  • 详细探索如何用脚本实现M小ySQL一键安装与配置,提升运维效率!
  • # 【Unity】【游戏开发】赛车游戏中碰撞加速的实现方法
  • LeetCode 692. 前K个高频单词:多种解法与实现技巧
  • YOLO11改进-模块-引入多尺度小波池化变压器MWPT 通过结合小波变换、多尺度池化以及门控机制等技术解决多尺度、小目标、边缘模糊等问题
  • 【GNN】第二章:图数据
  • 怎样建立商贸网站/可口可乐网络营销策划方案
  • 自己做网站可以揽业务吗/专业优化网站排名
  • 南京鼓楼做网站/软文交易平台
  • 烟台做网站的/seo站长工具是什么
  • 邯郸贴吧网站/杭州网站推广找哪家
  • 实验仪器销信应做何网站/网站收录提交