一木禾网盘下载分析及批量获取下载地址的实现(下)

分析过后,我们接着来做一下代码实现

三、获取流程实现

近期正巧看到了木鱼在自己博客里发布的一个HTTP客户端库,困扰于原生HttpWebRequest的我立马就下来用了用,效果果然不错,所以本项目的HTTP请求就由

FSLib.Network 类库来完成,语法差别不大,不太懂的地方可以回复。

添加类库可以使用nuget:

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('', 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('', 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);
        }
    }
}

到此程序就基本完成了,其他的细节,如识别类库载入等也不再赘述,有问题可以回复问我,新人发博客,排版很差,不好意思。

原文地址:https://www.cnblogs.com/WayneShao/p/5175567.html