栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C# > C#教程

C#实现12306自动登录的方法

C#教程 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C#实现12306自动登录的方法

依然使用IE9的捕获参数,做了一个12306的登录功能。参照了网上童鞋们的做法。
其他都和前面几篇读取余票、票价一样,不过登录要用到证书的问题,这个参考了一个网上的例子。
不过12306会随时变化,下面的登录不一定一直都能成功。如果12306有变化,大家可以根据变化对代码做修改。总之使用的方法不变,就是捕获参数和url,然后自己补充参数。
效果如下:

项目名称:Test12306AutoLogin;
环境:.net 4.0,Visual studio 2010;
项目图:

核心代码如下,
信任证书代码:

 public class Messenger
  {
    public Messenger()
    {
    }

    public void Register(string message, Action callback)
    {
      this.Register(message, callback, null);
    }

    public void Register(string message, Action callback)
    {
      this.Register(message, callback, typeof(T));
    }


    void Register(string message, Delegate callback, Type parameterType)
    {
      if (String.IsNullOrEmpty(message))
 throw new ArgumentException("'message' cannot be null or empty.");

      if (callback == null)
 throw new ArgumentNullException("callback");

      this.VerifyParameterType(message, parameterType);

      _messageToActionsMap.AddAction(message, callback.Target, callback.Method, parameterType);
    }

    [Conditional("DEBUG")]
    void VerifyParameterType(string message, Type parameterType)
    {
      Type previouslyRegisteredParameterType = null;
      if (_messageToActionsMap.TryGetParameterType(message, out previouslyRegisteredParameterType))
      {
 if (previouslyRegisteredParameterType != null && parameterType != null)
 {
   if (!previouslyRegisteredParameterType.Equals(parameterType))
     throw new InvalidOperationException(string.Format(
"The registered action's parameter type is inconsistent with the previously registered actions for message '{0}'.nExpected: {1}nAdding: {2}",
message, 
previouslyRegisteredParameterType.FullName,
parameterType.FullName));
 }
 else
 {
   // One, or both, of previouslyRegisteredParameterType or callbackParameterType are null.
   if (previouslyRegisteredParameterType != parameterType)  // not both null?
   {
     throw new TargetParameterCountException(string.Format(
"The registered action has a number of parameters inconsistent with the previously registered actions for message "{0}".nExpected: {1}nAdding: {2}",
message,
previouslyRegisteredParameterType == null ? 0 : 1,
parameterType == null ? 0 : 1));
   }
 }
      }
    }

    public void NotifyColleagues(string message, object parameter)
    {
      if (String.IsNullOrEmpty(message))
 throw new ArgumentException("'message' cannot be null or empty.");


      Type registeredParameterType;
      if (_messageToActionsMap.TryGetParameterType(message, out registeredParameterType))
      {
 if (registeredParameterType == null)
   throw new TargetParameterCountException(string.Format("Cannot pass a parameter with message '{0}'. Registered action(s) expect no parameter.", message));
      }


      var actions = _messageToActionsMap.GetActions(message);
      if (actions != null)
 actions.ForEach(action => action.DynamicInvoke(parameter));
    }


    public void NotifyColleagues(string message)
    {
      if (String.IsNullOrEmpty(message))
 throw new ArgumentException("'message' cannot be null or empty.");


      Type registeredParameterType;
      if (_messageToActionsMap.TryGetParameterType(message, out registeredParameterType))
      {
 if (registeredParameterType != null)
   throw new TargetParameterCountException(string.Format("Must pass a parameter of type {0} with this message. Registered action(s) expect it.", registeredParameterType.FullName));
      }


      var actions = _messageToActionsMap.GetActions(message);
      if (actions != null)
 actions.ForEach(action => action.DynamicInvoke());
    }
   
    private class MessageToActionsMap
    {
      internal MessageToActionsMap()
      {
      }


      
      internal void AddAction(string message, object target, MethodInfo method, Type actionType)
      {
 if (message == null)
   throw new ArgumentNullException("message");


 if (method == null)
   throw new ArgumentNullException("method");


 lock (_map)
 {
   if (!_map.ContainsKey(message))
     _map[message] = new List();


   _map[message].Add(new WeakAction(target, method, actionType));
 }
      }


      internal List GetActions(string message)
      {
 if (message == null)
   throw new ArgumentNullException("message");


 List actions;
 lock (_map)
 {
   if (!_map.ContainsKey(message))
     return null;


   List weakActions = _map[message];
   actions = new List(weakActions.Count);
   for (int i = weakActions.Count - 1; i > -1; --i)
   {
     WeakAction weakAction = weakActions[i];
     if (weakAction == null)
continue;


     Delegate action = weakAction.CreateAction();
     if (action != null)
     {
actions.Add(action);
     }
     else
     {
// The target object is dead, so get rid of the weak action.
weakActions.Remove(weakAction);
     }
   }


   // Delete the list from the map if it is now empty.
   if (weakActions.Count == 0)
     _map.Remove(message);
 }


 // Reverse the list to ensure the callbacks are invoked in the order they were registered.
 actions.Reverse();


 return actions;
      }


      internal bool TryGetParameterType(string message, out Type parameterType)
      {
 if (message == null)
   throw new ArgumentNullException("message");


 parameterType = null;
 List weakActions;
 lock (_map)
 {
   if (!_map.TryGetValue(message, out weakActions) || weakActions.Count == 0)
     return false;
 }
 parameterType = weakActions[0].ParameterType;
 return true;
      }


      readonly Dictionary> _map = new Dictionary>();
    }


   
    private class WeakAction
    {
      
      internal WeakAction(object target, MethodInfo method, Type parameterType)
      {
 if (target == null)
 {
   _targetRef = null;
 }
 else
 {
   _targetRef = new WeakReference(target);
 }


 _method = method;


 this.ParameterType = parameterType;


 if (parameterType == null)
 {
   _delegateType = typeof(Action);
 }
 else
 {
   _delegateType = typeof(Action<>).MakeGenericType(parameterType);
 }
      }


      internal Delegate CreateAction()
      {
 // Rehydrate into a real Action object, so that the method can be invoked.
 if (_targetRef == null)
 {
   return Delegate.CreateDelegate(_delegateType, _method);
 }
 else
 {
   try
   {
     object target = _targetRef.Target;
     if (target != null)
return Delegate.CreateDelegate(_delegateType, target, _method);
   }
   catch
   {
   }
 }


 return null;
      }


      internal readonly Type ParameterType;
      readonly Type _delegateType;
      readonly MethodInfo _method;
      readonly WeakReference _targetRef;
    }


    readonly MessageToActionsMap _messageToActionsMap = new MessageToActionsMap();
  }

登录的所有方法类:

public class Login12306Manager
  {
    private static readonly Messenger s_messenger = new Messenger();

    public static Messenger SMessenger { get { return s_messenger; } }

    public const string APPEND_MESSAGE = "append_message";

    public static string afterLogincookie;

    private static string beforLogincookie;

    static Login12306Manager()
    {
      SetCertificatePolicy();
    }

    /// 
    /// 登 录
    /// 
    public static string Login(string userName,string password, string randomCode)
    {
      string resultHtml = string.Empty;

      try
      {
 string loginRand= DoGetLoginRand();

 HttpWebRequest request = (HttpWebRequest)WebRequest.Create
   (@"https://dynamic.12306.cn/otsweb/loginAction.do?method=login");

 request.Accept = @"text/html, application/xhtml+xml, **;q=0.5";

 request.UserAgent = @"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)";

 request.Referer = @"https://dynamic.12306.cn/otsweb/loginAction.do?method=init";
 
 request.Method = "GET";

 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
 {
   beforLogincookie = response.GetResponseHeader("Set-cookie");

   beforLogincookie = Regex.Replace(beforLogincookie, "path(?:[^,]+),?", "", RegexOptions.IgnoreCase);
 
   using (Stream reader = response.GetResponseStream())
   {
     string path = Path.Combine(AppDomain.CurrentDomain.baseDirectory, new Random().Next(10000, 99999) + @"loginRandCode.JPEG");


     using (FileStream file = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
     {
reader.CopyTo(file);
     }

     randImageUrl = path;
   }
 }
      }
      catch { }

      return randImageUrl;
    }

    private static string DoGetLoginRand()
    {
      string loginRand=string.Empty;

      try
      {
 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"https://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest");

 request.Accept = @"application/json, text/javascript, */*";

 request.UserAgent = @"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)";
 
 request.Referer = @"https://dynamic.12306.cn/otsweb/loginAction.do?method=init";

 request.Headers[HttpRequestHeader.cookie] = beforLogincookie;

 request.Method = "POST";

 byte[] buffer = new byte[0];

 buffer = Encoding.UTF8.GetBytes(string.Empty);

 request.ContentLength = buffer.Length;

 using (Stream writer = request.GetRequestStream())
 {
   writer.Write(buffer, 0, buffer.Length);

   writer.Flush();
 }

 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
 {
   using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
   {
     string result = reader.ReadToEnd();

     var loginRandContent = JsonConvert.DeserializeObject(result);

     loginRand = loginRandContent.loginRand;
   }
 }
      }
      catch {}

      return loginRand;
    }
    /// 
    /// 处理登录结果
    /// 
    /// 登录后返回的html文本
    private static string ProcessLoginResult(string html)
    {
      string m_msgPattern = "message[^"]+"(?'message'[^"]+)";";

      string m_isLoginPatter = "isLogin\s*=\s*(?.+)n";

      string m_loginUserNamePattern = "u_name\s*=\s*['"](?.+)['"]";

      if (html.Contains("请输入正确的验证码"))
      {
 return "验证码错误";
      }
      else if (html.Contains("当前访问用户过多"))
      {
 return "当前访问用户过多,请稍后再试...";
      }
      else
      {
 var match0 = Regex.Match(html, m_msgPattern, RegexOptions.Compiled);

 if (match0.Success)
 {
   string text = match0.Groups["message"].Value;

   if (text.Contains("密码") || text.Contains("登录名不存在"))
   {
     return "用户名或者密码错误";
   }
   else
   {
    return text;
   }
 }

 var match = Regex.Match(html, m_isLoginPatter, RegexOptions.Compiled);

 if (match.Success && (match.Groups["val"].Value.Trim().ToLower() == "true"))
 {
   match = Regex.Match(html, m_loginUserNamePattern, RegexOptions.Compiled);
   if (match.Success)
   {
     string name = match.Groups["name"].Value;


     return "登录成功:" + name;
   }
   else
   {
     return "登录失败,未知错误";
   }
 }
 else
 {
   return "登录失败!!!";
 }
      }
    }

    /// 
    /// Sets the cert policy.
    /// 
    private static void SetCertificatePolicy()
    {
      ServicePointManager.ServerCertificatevalidationCallback
     += RemoteCertificatevalidate;
    }


    /// 
    /// Remotes the certificate validate.
    /// 
    private static bool RemoteCertificatevalidate(
      object sender, X509Certificate cert,
      X509Chain chain, SslPolicyErrors error)
    {
      SMessenger.NotifyColleagues(APPEND_MESSAGE, "信任任何证书...");
      return true;
    }
  }

  public class BeforLoginRnad
  {
    public string loginRand { get; set; }


    public string randError { get; set; }
  }

注意登录时,主要的正文是:

               string parameter =
@"loginRand={0}&refundLogin=N&refundFlag=Y&isClick=&form_tk=null&loginUser.user_name={1}&nameErrorFocus=&user.password={2}&passwordErrorFocus=&randCode={3}&randErrorFocus=&NDU0NzY4NA%3D%3D=Nzg4ZDAxMGNkYTZlMTRjZA%3D%3D&myversion=undefined",它有三个参数,登录时的随机码,用户名,密码和验证码组成。

调用如下:

前台wpf代码:


  
    
      
 
   
   
   
 


 
   
   
   
   
 


 
   
   
   
   
 
      
      
 
 
 
 
      


      
 
 
      


      
      


      
      


      
      
 
 
 

后台代码:

public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();


      this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }


    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
      DoRefreshRandCode();
    }


    private void DoRefreshRandCode()
    {
      string imageRandUrl = Login12306Manager.RefreshCode();


      if (File.Exists(imageRandUrl))
      {
 ImageSource src = (ImageSource)(new ImageSourceConverter().ConvertFromString(imageRandUrl));


 this.imageRandCode.Source = src;
      }


      this.txtRandCode.Text = string.Empty;
    }


    /// 
    /// 登录
    /// 
    /// 
    /// 
    private void ButtonLogin_Click(object sender, RoutedEventArgs e)
    {
      string userName = this.txtUserName.Text;


      string password = this.txtPassword.Password;


      string randCode = this.txtRandCode.Text;


      if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(randCode))
      {
 MessageBox.Show("请填写完整信息");


 return;
      }

      string html = Login12306Manager.Login(userName, password, randCode);


      System.Windows.documents.Flowdocument doc = this.rtxResultContent.document;


      doc.Blocks.Clear();


      this.rtxResultContent.AppendText(html); 
    }


    /// 
    /// 刷新验证码
    /// 
    /// 
    /// 
    private void ButtonRefreshRandCode_Click(object sender, RoutedEventArgs e)
    {
      DoRefreshRandCode();
    }
  }

以上就是本文的全部内容,希望对大家的学习有所帮助。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/124882.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号