wwroot1 发表于 2021-11-19 15:06

河南工职培训自动学习流程实现

研究的是河南公职,其他地区的可参考流程实现。开发语言:.net core3.1 一、流程梳理
   要想实现软件自动学习,我们就得像如何把大象塞进冰箱一样,对需要做的事情进行拆分。
   ①那到底如何实现呢?
      第一步:登陆,登陆后官网返回cookie或jwt的token,用于在下次请求时验证用户信息
      第二步:罗列所有需要学习的课程。通过访问我的课程接口,获取到用户下的所有课程
      第三步:发送学习数据包。很多初学者到了这一步大多都在研究视频播放进度,认为把课程的视频自动播放,就可以实现进度更新。然而并不是这样的,一般网站都会隔段时间进行一次发包请求,请求中必然携带课程信息和当前学习进度。
二、开始动工
   所有抓包信息均可通过浏览器F12获取
   第一步:抓登陆,点击登陆按钮后的第一条即为登陆包,简单易懂,发送了账号密码和验证码。获取验证码时会返回一个cookie,登陆时用此cookie作为发送cookie即可实现验证码验证
   
    在winform程序中我们可以这样拼接实现
   
   第二步:获取所有课程
   通过点击学习->筛选网络格式后,发现一条(/study.do?action=getStudyList),通过getstudylist可以轻松判断这就是获取课程的关键包
   
   
   第三步:发送关键数据,课程点进去后会有视频列表,此时返回的数据并非json格式,而是html格式,可以通过正则表达式获取,然后耐心看一下课,隔段时间会发一次数据包,分析数据包中的字段实现最后的关键方法
   
   


      private void UpdatetextBox4(object str)
      {
            if (textBox4.InvokeRequired)
            {

                Action<string> actionDelegate = (x) => { this.textBox4.AppendText(x.ToString() + "\r\n"); };
                this.textBox4.Invoke(actionDelegate, str);
            }
            else
            {
                this.textBox4.AppendText(str.ToString() + "\r\n");
            }
      }
      static string Url = "http://hnpi.newzhihui.cn";
      static string codeImageCookie = "";

      private void Form1_Load(object sender, EventArgs e)
      {
            piccheck();
      }
      string[] needLearnYear;
      void piccheck()
      {
            string url = "/validate.do";
            HttpHelper http = new HttpHelper();
            HttpItem item = new HttpItem()
            {
                URL = Url + url,
                Method = "GET",
                Accept = "text/html, application/xhtml+xml, */*",
                ContentType = "text/html",
                ResultType = ResultType.Byte,//返回数据类型,是Byte还是String
            };
            HttpResult result = http.GetHtml(item);
            codeImageCookie = result.Cookie;
            Bitmap bitmap = (Bitmap)byteArrayToImage(result.ResultByte);
            pictureBox1.Image = bitmap;
      }

      private Image byteArrayToImage(byte[] Bytes)
      {
            MemoryStream ms = new MemoryStream(Bytes);
            return Bitmap.FromStream(ms, true);
      }

      private void button1_Click(object sender, EventArgs e)
      {
            if (textBox5.Text.Trim().Length == 0)
            {
                MessageBox.Show("请填写需要学习的年度", "登陆失败");
                return;
            }
            needLearnYear = textBox5.Text.Trim().Split(',');
            string request = newCookiePost("/frontLogin.do", $"loginName={textBox1.Text.Trim()}&password={textBox2.Text.Trim()}&roleType=1&vcode={textBox3.Text.Trim()}&unittitle=1&unit_syscode=1&type=1");
            JObject jObject = JObject.Parse(request);
            if (jObject["result"].ToString() != "success")
            {
                MessageBox.Show(jObject["error"].ToString(), "登陆失败");
                return;
            }
            string classList = Post("/study.do?action=getStudyList", "studyState=", codeImageCookie);
            JObject JclassList = JObject.Parse(classList);
            if (JclassList["result"].ToString() != "success")
            {
                MessageBox.Show("获取课程信息失败", "提醒");
            }
            else
            {
                string list = JclassList["list"].ToString();
                if (list.Length == 0)
                {
                  MessageBox.Show("没有需要学习的课程", "提醒");
                  return;
                }
                JArray JAClassList = JArray.Parse(list);
                for (int a = 0; a < JAClassList.Count; a++)
                {
                  string year = JAClassList["year"].ToString();
                  if (!isusedLearn(year)) continue;
                  string name = JAClassList["name"].ToString();
                  string id = JAClassList["id"].ToString();
                  string userId = JAClassList["userId"].ToString();
                  UpdatetextBox4($"正在学习{year}年度-:{name}");
                  ToStudy(id, codeImageCookie);
                }
            }
            UpdatetextBox4("学习完成");
      }
      bool isusedLearn(string year)
      {
            for (int a = 0; a < needLearnYear.Length; a++)
            {
                if (needLearnYear == year) return true;
            }
            return false;
      }

      void ToStudy(string id, string _cookie)
      {
            string Html = Get("/study.do?action=toStudy&id=" + id, _cookie);
            string regexStr = "<div class=\"video-info\" onclick=['\"]*(\\S+)[\"']>";
            Regex regex = new Regex(regexStr);
            MatchCollection matchs = regex.Matches(Html);
            foreach (Match match in matchs)
            {
                string m = match.Groups.Value;
                string Id_1 = Between(m, "playVideo('", "','");
                string Id_2 = Between(m, "','", "')");
                int lastLearnTime = 0;
                if (!GetVideoTime(Id_1, out lastLearnTime, _cookie)) continue;
                int _nowLearn = lastLearnTime / 40;
                bool islearnOver = false;
                while (!islearnOver)
                {
                  string _data = $"id={Id_1}&itemRate={_nowLearn}&wareRate={_nowLearn}&time={_nowLearn * 40}";
                  string updateItemRate = Post("/study.do?action=updateItemRate", _data, _cookie, true);
                  int itemRate = 0;
                  try
                  {
                        JObject JEnd = JObject.Parse(updateItemRate);
                        itemRate = int.Parse(JEnd["itemRate"].ToString());
                        UpdatetextBox4("当前进度:" + itemRate);
                  }
                  catch (Exception ex)
                  {
                        Console.WriteLine();
                        UpdatetextBox4("网络访问错误,频繁出现此错误的话请退出重登");
                  }
                  finally
                  {
                        if (itemRate >= 100)
                        {
                            islearnOver = true;
                        }
                  }
                  _nowLearn++;
                }
            }
      }

      bool GetVideoTime(string id, out int lastlearnTime, string _cookie)
      {
            lastlearnTime = 0;
            string getWareItemDetail = Post("/study.do?action=getWareItemDetail", "id=" + id, _cookie, true);
            JObject jobject = JObject.Parse(getWareItemDetail);
            string data = jobject["data"].ToString();
            JObject jdata = JObject.Parse(data);
            int vTime = int.Parse(jdata["vtime"].ToString());
            int uTime = int.Parse(jdata["playTime"].ToString());
            lastlearnTime = uTime;
            if (vTime == 0)
            {
                lastlearnTime = 0;
                return true;
            }
            return vTime - uTime > 0 ? true : false;
      }

      string newCookiePost(string _url, string _data)
      {

            HttpHelper http = new HttpHelper();
            HttpItem item = new HttpItem()
            {
                URL = Url + _url,
                Cookie = codeImageCookie,
                Method = "POST",
                Accept = "text/html, application/xhtml+xml, */*",
                ContentType = "application/x-www-form-urlencoded",
                Postdata = _data,
                ResultType = ResultType.String,
            };
            HttpResult result = http.GetHtml(item);
            return result.Html;
      }

      string Post(string _url, string _data, string _cookie = "", bool iswww = false)
      {
            HttpHelper http = new HttpHelper();
            HttpItem item = new HttpItem()
            {
                URL = Url + _url,
                Postdata = _data,
                Method = "POST",
                Cookie = _cookie,
                Accept = "text/html, application/xhtml+xml, */*",
                ContentType = iswww ? "application/x-www-form-urlencoded" : "application/json",
                ResultType = ResultType.String,
            };
            HttpResult result = http.GetHtml(item);
            return result.Html;
      }

      string Get(string _url, string _cookie = "")
      {
            HttpHelper http = new HttpHelper();
            HttpItem item = new HttpItem()
            {
                URL = Url + _url,
                Method = "GET",
                Cookie = _cookie,
                Accept = "text/html, application/xhtml+xml, */*",
                ContentType = "application/json",
                ResultType = ResultType.String,
            };
            HttpResult result = http.GetHtml(item);
            return result.Html;
      }

      string Between(string str, string leftstr, string rightstr)
      {
            try
            {
                int i = str.IndexOf(leftstr) + leftstr.Length;
                string temp = str.Substring(i, str.IndexOf(rightstr, i) - i);
                return temp;
            }
            catch
            {
                return "";
            }
      }

      private void radioButton1_CheckedChanged(object sender, EventArgs e)
      {
            Url = "http://hnpi.newzhihui.cn";
            piccheck();
      }

      private void radioButton2_CheckedChanged(object sender, EventArgs e)
      {
            Url = "http://hnpizy.newzhihui.cn";
            piccheck();
      }

      private void pictureBox1_Click(object sender, EventArgs e)
      {
            piccheck();
      }

      private void checkBox1_CheckedChanged(object sender, EventArgs e)
      {
            if (checkBox1.Checked)
            {
                Url = "http://hnpi.newzhihui.cn:81";
                piccheck();
            }
      }
因为是winform程序,所以没有图形界面很难实现看懂代码,可以从后方链接中得到完整源码+可执行程序https://wwa.lanzoui.com/iUMGRwnr64h

明次 发表于 2021-11-19 17:18

现在有很多现成的工具

wwroot1 发表于 2021-11-19 17:39

明次 发表于 2021-11-19 17:18
现在有很多现成的工具

对的,工具有很多,实现方法也大同小异{:1_919:}{:1_919:}

xxl_hot 发表于 2021-11-20 15:50

高手 纯练手玩

smith168668 发表于 2021-11-20 19:35

有过程分析,不错!
页: [1]
查看完整版本: 河南工职培训自动学习流程实现