此项目是作者偶然看到,并非原创,特此声明。 项目地址:https://github.com/iikira/BaiduPCS-Go 特色百度账号多用户支持; 网盘内列出文件和目录, 支持通配符匹配路径, 通配符_百度百科; 下载网盘内文件, 支持网盘内目录 (文件夹) 下载, 支持多个文件或目录下载, 支持断点续传和高并发高速下载;
程序 编译/交叉编译 说明参见 编译/交叉编译帮助 程序 下载/运行 说明Go语言程序, 可直接下载使用, 点此查看发布页面 / 下载汇总. 如果程序运行时输出乱码, 请检查下终端的编码方式是否为 使用本程序之前, 建议学习一些 linux 基础知识 和 基础命令. 如果未带任何参数运行程序, 程序将会进入独有的 console 模式, 可直接运行相关命令. console 模式下, 光标所在行的前缀应为 程序会提供相关命令的使用说明. Windows 程序应在 命令提示符 (Command Prompt) 或 PowerShell 中运行. 也可直接双击程序运行, 具体使用方法请参见 命令列表及说明 和 例子. Linux / macOS 程序应在 终端 (Terminal) 运行. 具体使用方法请参见 命令列表及说明 和 例子. Android / iOS 安卓, 建议使用软件 Termux 或 NeoTerm 或 终端模拟器, 以提供终端环境. 示例: Android 运行本 BaiduPCS-Go 程序参考示例, 有兴趣的可以参考一下. 苹果iOS, 需要越狱, 在 Cydia 搜索下载并安装 MobileTerminal, 以提供终端环境. MobileTerminal 功能有限, 本人建议 设备安装 openssh 后使用 ssh 控制苹果设备, sftp 传输文件. 具体使用方法请参见 命令列表及说明 和 例子. 命令列表及说明注意 ! ! ! 命令的前缀 未带任何其他参数运行程序, 则程序进入 console 模式, 前缀为 登录百度账号 常规登录百度账号 支持在线验证绑定的手机号或邮箱, BaiduPCS-Go login 使用百度 BDUSS 来登录百度账号 关于 获取百度 BDUSS BaiduPCS-Go login -bduss=<BDUSS> 例子 BaiduPCS-Go login -bduss=1234567 BaiduPCS-Go login请输入百度用户名(手机号/邮箱/用户名), 回车键提交 > 1234567 获取当前账号, 和所有已登录的百度账号 BaiduPCS-Go loglist 切换已登录的百度账号 BaiduPCS-Go su -uid=12345678 BaiduPCS-Go su请输入要切换账号的 index 值 > 退出已登录的百度账号 BaiduPCS-Go logout -uid=12345678 BaiduPCS-Go logout请输入要退出账号的 index 值 > 获取配额, 即获取网盘总空间, 和已使用空间 BaiduPCS-Go quota 切换工作目录 BaiduPCS-Go cd <目录> 例子 # 切换 /我的资源 工作目录BaiduPCS-Go cd /我的资源BaiduPCS-Go cd 我的资源# 使用通配符BaiduPCS-Go cd /我的* 输出当前所在目录 BaiduPCS-Go pwd 列出当前工作目录的文件和目录或指定目录 BaiduPCS-Go ls BaiduPCS-Go ls <目录> 例子 BaiduPCS-Go ls 我的资源# 使用通配符BaiduPCS-Go ls /我的* 获取单个文件/目录的元信息 (详细信息) BaiduPCS-Go meta <文件/目录> # 默认获取根目录元信息BaiduPCS-Go meta 例子 BaiduPCS-Go meta 我的资源BaiduPCS-Go meta / 下载文件, 网盘文件或目录的绝对路径或相对路径 BaiduPCS-Go download <网盘文件或目录的路径1> <文件或目录2> <文件或目录3> ...BaiduPCS-Go d <网盘文件或目录的路径1> <文件或目录2> <文件或目录3> ... 支持多个文件或目录的下载. 下载的文件默认保存到 程序所在目录 的 download/ 目录, 支持设置指定目录, 重名的文件会自动跳过! 例子 # 设置保存目录, 保存到 D:Downloads (注意两个反斜杠 "" !!)BaiduPCS-Go set savedir D:\Downloads# 下载 /我的资源/1.mp4BaiduPCS-Go d /我的资源/1.mp4# 下载 /我的资源 整个目录!!BaiduPCS-Go d /我的资源# 下载网盘内的全部文件!!BaiduPCS-Go d /BaiduPCS-Go d * 上传文件 BaiduPCS-Go upload <本地文件或目录的路径1> <文件或目录2> <文件或目录3> ... <网盘的目标目录>BaiduPCS-Go u <本地文件或目录的路径1> <文件或目录2> <文件或目录3> ... <网盘的目标目录> 例子: # 将本地的 C:UsersAdministratorDesktop.mp4 上传到网盘 /视频 目录# 注意区别反斜杠 "" 和 斜杠 "/" !!!BaiduPCS-Go upload C:\Users\Administrator\Desktop\1.mp4 /视频# 将本地的 C:UsersAdministratorDesktop.mp4 和 C:UsersAdministratorDesktop.mp4 上传到网盘 /视频 目录BaiduPCS-Go upload C:\Users\Administrator\Desktop\1.mp4 C:\Users\Administrator\Desktop\2.mp4 /视频# 将本地的 C:UsersAdministratorDesktop 整个目录上传到网盘 /视频 目录BaiduPCS-Go upload C:\Users\Administrator\Desktop /视频 创建目录 BaiduPCS-Go mkdir <目录> 例子 BaiduPCS-Go mkdir 123 删除 单个/多个 文件/目录 BaiduPCS-Go rm <网盘文件或目录的路径1> <文件或目录2> <文件或目录3> ... 注意: 删除多个文件和目录时, 请确保每一个文件和目录都存在, 否则删除操作会失败. 例子 # 删除 /我的资源/1.mp4BaiduPCS-Go rm /我的资源/1.mp4# 删除 /我的资源/1.mp4 和 /我的资源/2.mp4BaiduPCS-Go rm /我的资源/1.mp4 /我的资源/2.mp4# 删除 /我的资源 内的所有文件和目录, 但不删除该目录BaiduPCS-Go rm /我的资源/*# 删除 /我的资源 整个目录 !!BaiduPCS-Go rm /我的资源 拷贝(复制) 单个/多个 文件/目录 BaiduPCS-Go cp <文件/目录> <目标 文件/目录>BaiduPCS-Go cp <文件/目录1> <文件/目录2> <文件/目录3> ... <目标目录> 注意: 拷贝(复制) 多个文件和目录时, 请确保每一个文件和目录都存在, 否则拷贝操作会失败. 例子 # 将 /我的资源/1.mp4 复制到 根目录 /BaiduPCS-Go cp /我的资源/1.mp4 /# 将 /我的资源/1.mp4 和 /我的资源/2.mp4 复制到 根目录 /BaiduPCS-Go cp /我的资源/1.mp4 /我的资源/2.mp4 / 移动/重命名 单个/多个 文件/目录 # 移动:BaiduPCS-Go mv <文件/目录1> <文件/目录2> <文件/目录3> ... <目标目录># 重命名:BaiduPCS-Go mv <文件/目录> <重命名的文件/目录> 注意: 移动多个文件和目录时, 请确保每一个文件和目录都存在, 否则移动操作会失败. 例子 # 将 /我的资源/1.mp4 移动到 根目录 /BaiduPCS-Go mv /我的资源/1.mp4 /# 将 /我的资源/1.mp4 重命名为 /我的资源/3.mp4BaiduPCS-Go mv /我的资源/1.mp4 /我的资源/3.mp4 设置 BaiduPCS-Go set OptionName Value 例子 # 查看所有可以设置的值BaiduPCS-Go set -h# 设置下载文件的储存目录BaiduPCS-Go set savedir D:\Downloads# 设置下载最大并发量为 150BaiduPCS-Go set max_parallel 150 举一些例子新手建议: 双击运行程序, 进入 console 模式; console 模式下, 光标所在行的前缀应为 以下例子的命令, 均为 console 模式下的命令 运行命令的正确操作: 输入命令, 按一下回车键 (键盘上的 Enter 键), 程序会接收到命令并输出结果 1. 查看程序使用说明 console 模式下, 运行命令 2. 登录百度账号 (必做) console 模式下, 运行命令 console 模式下, 运行命令 3. 切换网盘工作目录 console 模式下, 运行命令 目录支持通配符匹配, 所以你也可以这样: 运行命令 将工作目录切换为 为什么要这样设计呢, 举个例子, 假设 你要下载 d /我的资源/1.mp4d /我的资源/2.mp4 而切换网盘工作目录之后, 依次运行以下命令: cd /我的资源d 1.mp4d 2.mp4 这样就达到了简化输入的目的 4. 网盘内列出文件和目录 console 模式下, 运行命令 console 模式下, 运行命令 console 模式下, 运行命令 console 模式下, 运行命令 5. 下载文件 说明: 下载的文件将会保存到 download/ 目录 (文件夹) console 模式下, 运行命令 console 模式下, 运行命令 cd /我的资源d 1.mp4 现在已经支持目录 (文件夹) 下载, 所以, 运行以下命令, 会下载 d /我的资源 参见 例6 设置下载最大并发数 6. 设置下载最大并发数 console 模式下, 运行命令 console 模式下, 运行命令 下载最大并发数建议值: 50~500, 太低下载速度提升不明显甚至速度会变为0, 太高可能会导致程序和系统超负荷 7. 退出程序 运行命令 已知问题
TODO
部分请求核心源码: package requester import ( "bytes" "fmt" "io" "io/ioutil" "net/http" "net/url" "strings" ) // HTTPGet 简单实现 http 访问 GET 请求 func HTTPGet(urlStr string) (body []byte, err error) { resp, err := http.Get(urlStr) if err != nil { return nil, err } defer resp.Body.Close() return ioutil.ReadAll(resp.Body) } // Req 实现 http/https 访问, // 根据给定的 method (GET, POST, HEAD, PUT 等等), urlStr (网址), // post (post 数据), header (header 请求头数据), 进行网站访问。 // 返回值分别为 *http.Response, 错误信息 func (h *HTTPClient) Req(method string, urlStr string, post interface{}, header map[string]string) (resp *http.Response, err error) { var ( req *http.Request obody io.Reader ) if post != nil { switch value := post.(type) { case io.Reader: obody = value case map[string]string: query := url.Values{} for k := range value { query.Set(k, value[k]) } obody = strings.NewReader(query.Encode()) case string: obody = strings.NewReader(value) case []byte: obody = bytes.NewReader(value[:]) default: return nil, fmt.Errorf("requester.Req: unknown post type: %s", value) } } req, err = http.NewRequest(method, urlStr, obody) if err != nil { return nil, err } // 设置浏览器标识 req.Header.Set("User-Agent", UserAgent) if header != nil { for key := range header { req.Header.Add(key, header[key]) } } return h.Client.Do(req) } // Fetch 实现 http/https 访问, // 根据给定的 method (GET, POST, HEAD, PUT 等等), urlStr (网址), // post (post 数据), header (header 请求头数据), 进行网站访问。 // 返回值分别为 网站主体, 错误信息 func (h *HTTPClient) Fetch(method string, urlStr string, post interface{}, header map[string]string) (body []byte, err error) { resp, err := h.Req(method, urlStr, post, header) if err != nil { return nil, err } body, err = ioutil.ReadAll(resp.Body) resp.Body.Close() return } package requester import ( "crypto/tls" "net/http" "net/http/cookiejar" "time" ) // HTTPClient http client type HTTPClient struct { http.Client } // NewHTTPClient 返回 HTTPClient 的指针, // 预设了一些配置 func NewHTTPClient() *HTTPClient { jar, _ := cookiejar.New(nil) return &HTTPClient{ Client: http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, TLSHandshakeTimeout: 10 * time.Second, DisableKeepAlives: false, DisableCompression: false, // gzip ResponseHeaderTimeout: 10 * time.Second, ExpectContinueTimeout: 10 * time.Second, }, Jar: jar, Timeout: 30 * time.Second, }, } } // SetCookiejar 设置 cookie func (h *HTTPClient) SetCookiejar(c *cookiejar.Jar) { h.Jar = c } // ResetCookiejar 清空 cookie func (h *HTTPClient) ResetCookiejar() { h.Jar, _ = cookiejar.New(nil) } // SetHTTPSecure 是否启用 https 安全检查, 默认不检查 func (h *HTTPClient) SetHTTPSecure(b bool) { h.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify = !b } // SetKeepAlive 设置 Keep-Alive func (h *HTTPClient) SetKeepAlive(b bool) { h.Transport.(*http.Transport).DisableKeepAlives = !b } // SetGzip 是否启用Gzip func (h *HTTPClient) SetGzip(b bool) { h.Transport.(*http.Transport).DisableCompression = !b } // SetResponseHeaderTimeout 设置目标服务器响应超时时间 func (h *HTTPClient) SetResponseHeaderTimeout(t time.Duration) { h.Transport.(*http.Transport).ResponseHeaderTimeout = t } // SetTimeout 设置 http 请求超时时间, 默认30s func (h *HTTPClient) SetTimeout(t time.Duration) { h.Timeout = t } package requester var ( // UserAgent 浏览器标识 UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" // DefaultClient 默认 http 客户端 DefaultClient = NewHTTPClient() ) package uploader import ( "bytes" "github.com/iikira/BaiduPCS-Go/requester" "mime/multipart" "net/http" "strings" ) // Uploader 上传 type Uploader struct { URL string // 上传地址 IsMultiPart bool // 是否表单上传 Body *reader // 要上传的对象 client *requester.HTTPClient onExecute func() onFinish func() } // NewUploader 返回 uploader 对象, url: 上传地址, isMultipart: 是否表单上传,uploadReaderLen: 实现 uploader.ReaderLen 接口的对象, 例如文件 func NewUploader(url string, isMultipart bool, uploadReaderLen ReaderLen, h *requester.HTTPClient) (uploader *Uploader) { uploader = &Uploader{ URL: url, IsMultiPart: isMultipart, Body: &reader{ uploadReaderLen: uploadReaderLen, }, } if h == nil { uploader.client = requester.NewHTTPClient() } else { uploader.client = h } // 设置不超时 uploader.client.SetTimeout(0) uploader.client.SetResponseHeaderTimeout(0) return } // Execute 执行上传 func (u *Uploader) Execute(checkFunc func(resp *http.Response, err error)) { go func() { u.touch(u.onExecute) // 开始上传 resp, _, err := u.execute() if checkFunc != nil { checkFunc(resp, err) } u.touch(u.onFinish) }() } func (u *Uploader) execute() (resp *http.Response, code int, err error) { var contentType string if u.IsMultiPart { multipartWriter := &bytes.Buffer{} writer := multipart.NewWriter(multipartWriter) writer.CreateFormFile("uploadedfile", "") u.Body.multipart = multipartWriter u.Body.multipartEnd = strings.NewReader(" --" + writer.Boundary() + "-- ") contentType = writer.FormDataContentType() } else { contentType = "application/x-www-form-urlencoded" } req, err := http.NewRequest("POST", u.URL, u.Body) if err != nil { return nil, 1, err } req.Header.Add("Content-Type", contentType) // 设置 Content-Length 不然请求会卡住不动!!! req.ContentLength = u.Body.totalLen() resp, err = u.client.Do(req) if err != nil { return nil, 2, err } return resp, 0, nil } // touch 用于触发事件 func (u *Uploader) touch(fn func()) { if fn != nil { go fn() } } // OnExecute 任务开始时触发的事件 func (u *Uploader) OnExecute(fn func()) { u.onExecute = fn } // OnFinish 任务完成时触发的事件 func (u *Uploader) OnFinish(fn func()) { u.onFinish = fn } 欢迎大家 一起交流 网盘下载工具和方法。 |
|