WayneShao 的博客

记录精彩的程序人生

一木禾网盘文件下载地址批量获取实现

流程清晰之后,我们就可以制作软件来对网盘地址链接批量处理得到下载链接。

选型

我们的整个操作流程类似模拟浏览器操作,最好的解决方法其实是使用Selenium直接操作浏览器抓取。不过这方面我还没什么研究,就直接用最近发现的木鱼大牛的 FSLib.Network 库来实现。这个类库是实现了HTTP访问过程中对Cookie的自动处理,在大多数情况下都可以模拟浏览器。
使用nuget在项目中安装 FSLib.Network 包:

Install-Package network.fishlee.net

获取流程实现

下面来依据流程完成通过页面地址来获得文件下载连接的方法:

private async void GetDownLoadUrl(string fileUrl)
{
    //建立HTTP客户端
    var client = new HttpClient();
    //用于接收验证码
    StringBuilder Result;
    //验证码的字符数组
    byte[] bytes;
    //用于接收下载链接
    string downPath = string.Empty;
    //通过正则匹配到链接中的 fileid
   int id = Convert.ToInt32(Extract(fileUrl, "\\d{7,}"));
    //有时会出现一级域名为ymhwp的情况,这里先做一下替换,以防不测
    fileUrl = fileUrl.Replace("ymhwp", "yimuhe");
    //创建展示页面请求
    var filecontext = client.Create<string>(HttpMethod.Get, fileUrl);
    //发送请求
    await filecontext.SendTask();
    if (filecontext.IsValid())//如果请求成功
    {
        //替换链接中的fil为down,使其成为下载页面地址
        fileUrl = fileUrl.Replace("file", "down");
        //创建下载页面请求
         var downcontext = client.Create<string>(HttpMethod.Get, fileUrl);
        await downcontext.SendTask();
        if (downcontext.IsValid())
        {
            //设置初始返回值为0,表示验证码输入错误,即识别失败
            int response = 0;
            while (response == 0)//循环识别,直到识别成功
            {
                //创建验证码图片请求
                   var vcode = client.Create<Byte[]>(HttpMethod.Get, "http://www.yimuhe.com/n_downcode.php");
                await vcode.SendTask();
                if (vcode.IsValid())
                {
                    //将获取到的验证码图片存入字节数组中
                    bytes = vcode.Result;
                    Result = new StringBuilder('\0', 256);
                    //识别验证码
                    GetVcodeFromBuffer(1, bytes, bytes.Length, Result);
                    //创建检验验证码请求
                    var resp = client.Create<string>(HttpMethod.Post,
                        "http://www.yimuhe.com/n_downcode.php", data: "action=yz&id=" + id + "&code=" + Result);
                    await resp.SendTask();
                    if (resp.IsValid())
                    {
                        //返回验证码校验值、成功为1失败为0
                        response = Convert.ToInt32(resp.Result);
                    }
                }
            }
            //创建获取下载地址请求
            var h1 = client.Create<string>(HttpMethod.Post,
                    "http://www.yimuhe.com/n_dd.php?file_id=" + id + "&ser=99", refer: "http://www.yimuhe.com/down-2546737.html", data: id.ToString());
            await h1.SendTask();
            if (h1.IsValid())
            {
                //通过HtmlAgilityPack库完成html解析,获得下载地址
                   HtmlDocument html = new HtmlDocument();
                html.LoadHtml(h1.Result);
                downPath = html.GetElementbyId("downs").Attributes["href"].Value;
                tBAfter.AppendText(downPath + NewLine);
            }
        }

    }
}

批量获取实现

我的批量实现思路为将要获取的链接加入一个队列当中,线程从队头移出数据一条进行地址获取,获取成功不进行操作,失败则将地址添回到队尾。循环获取直到队列为空。另一个队列储存正在处理的数据,仅当两个线程均为空时才会陆续结束所有线程。线程执行的方法在上边的方法基础上又做了一些修改。

具体实现代码如下:

private async void GetDownLoadUrl()
{
    //当链接队列和正在处理队列存在不为空时,循环执行以下代码
    while (_pathList.Count > 0 || _pathReady.Count > 0)
    {
        //当链接队列不为空时
        if (_pathList.Count > 0)
        {

            //从队头取出一条数据
            string fileUrl = _pathList[0];
            _pathList.RemoveAt(0);
            _pathReady.Add(fileUrl);
            //建立HTTP客户端
            var client = new HttpClient();
            //用于接收验证码
            StringBuilder Result;
            //验证码的字符数组
            byte[] bytes;
            //用于接收下载链接
            string downPath = string.Empty;
            //通过正则匹配到链接中的 fileid
            int id = Convert.ToInt32(Extract(fileUrl, "\\d{7,}"));
            //有时会出现一级域名为ymhwp的情况,这里先做一下替换,以防不测
            fileUrl = fileUrl.Replace("ymhwp", "yimuhe");
            //创建展示页面请求
            var filecontext = client.Create<string>(HttpMethod.Get, fileUrl);
            //发送请求
            await filecontext.SendTask();
            if (filecontext.IsValid())//如果请求成功
            {
                //替换链接中的fil为down,使其成为下载页面地址
                fileUrl = fileUrl.Replace("file", "down");
                //创建下载页面请求
                var downcontext = client.Create<string>(HttpMethod.Get, fileUrl);
                await downcontext.SendTask();
                if (downcontext.IsValid())
                {
                    //设置初始返回值为0,表示验证码输入错误,即识别失败
                    int response = 0;
                    while (response == 0)//循环识别,直到识别成功
                    {
                        //创建验证码图片请求
                        var vcode = client.Create<Byte[]>(HttpMethod.Get, "http://www.yimuhe.com/n_downcode.php");
                        await vcode.SendTask();
                        if (vcode.IsValid())
                        {
                            //将获取到的验证码图片存入字节数组中
                            bytes = vcode.Result;
                            Result = new StringBuilder('\0', 256);
                            //识别验证码
                            GetVcodeFromBuffer(1, bytes, bytes.Length, Result);
                            //创建检验验证码请求
                            var resp = client.Create<string>(HttpMethod.Post,
                                "http://www.yimuhe.com/n_downcode.php", data: "action=yz&id=" + id + "&code=" + Result);
                            await resp.SendTask();
                            if (resp.IsValid())
                            {
                                //返回验证码校验值、成功为1失败为0
                                response = Convert.ToInt32(resp.Result);
                            }
                        }
                    }
                    //创建获取下载地址请求
                    var h1 = client.Create<string>(HttpMethod.Post,
                            "http://www.yimuhe.com/n_dd.php?file_id=" + id + "&ser=99", refer: "http://www.yimuhe.com/down-2546737.html", data: id.ToString());
                    await h1.SendTask();
                    if (h1.IsValid())
                    {
                        //通过HtmlAgilityPack库完成html解析,获得下载地址
                        HtmlDocument html = new HtmlDocument();
                        html.LoadHtml(h1.Result);
                        downPath = html.GetElementbyId("downs").Attributes["href"].Value;
                        //将获取到的地址显示到界面
                        tBAfter.AppendText(downPath + NewLine);
                    }
                }
            }
            //如果downPath为空,则请求失败
            if (string.IsNullOrWhiteSpace(downPath))
            {
                //将请求链接添回队尾
                _pathList.Add(path);
            }
            //处理完毕,移出当前处理队列
            _pathReady.Remove(path);
        }
    }
}

结束

本文旨在抛砖引玉,因为一些都懂得的原因,就不给出成品的下载地址了,有需要的童鞋可以自行完成。

留下你的脚步