模拟网页登录的一种全能思路

原理就是从webbrowser拿到Cookie

一般做网页登录,比如登录QQ空间,则要破解登录的相关的一系列加密算法。

在给客户维护以前登录QQ空间采集好友访客的一个软件时,发现2015年的空间密码加密方式变了,由以前的MD5改为了RSA,找到了加密的JS文件,但懒的转为C#代码。本来想用Interop.MSScriptControl.dll在C#中调用JS,但是直接调用这个JS文件会报错。实在不想继续找下去,一直在想着有什么简单方便的方法。终于功夫不负有心人,还真让我找到了。

原来的方式是,是从UI界面上获取用户要登录的用户名和密码,C#代码经过系统的加密,转换为TX需要的格式,并发包的服务器,服务器反回一些cookie和一些有用的值(比如g_tk),然后后续的一些操作要带上这些cookie和g_tk。现在既然这些过程解不了密,那么是否可以用Webbrowser控件来登录,登录完成后从webbrowser中拿到cookie,后续的操作带上这些cooke即可。

经过动手尝试,证明是可行的。对于QQ空间的登录,过程是这样的:

webbrowser中进行登录,登录完成后,在恰当的时机,拿到webbrowser的cookie,然后在cookieContainer中找到skey

至此,所有cookie和skey都拿到了。然后还有一个重要的参数g_tk, 这个参数是根据skey计算出来的。算法如下:

/// <summary>
/// 获取空间登录的g_tk
/// </summary>
/// <param name="skey"></param>
/// <returns></returns>
public long g_tk(string skey)
{
        long hash = 5381;
        for ( int i = 0; i < skey.Length; i++)
       {
              hash += (hash << 5) + skey[i];
       }
        return hash & 0x7fffffff;
}

试了下,能用,还好,g_tk的算法没有改动。

这样,项目维护完成,600块钱到手。

下面附上webbrowser登录过程以及拿到cookie和相cookie中取skey的所有代码:

public partial class QZoneWebLogin : Form
{
    private bool flag = false;
    private string _skey = string.Empty;
    private CookieContainer _cookie = new CookieContainer();

    public string skey
    {
        get { return _skey; }
    }

    public CookieContainer cookie
    {
        get { return _cookie; }
    }

    public QZoneWebLogin()
    {
        InitializeComponent();
    }

    private void webBrowser1_DocumentCompleted( object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (webBrowser1.Url.ToString().Contains( "http://user.qzone.qq.com/") && webBrowser1.Url.ToString().Contains("?ptsig=" ))
        {
            if (!flag)
            {
                flag = true;
                _skey = GetSkey();
                this.DialogResult = System.Windows.Forms. DialogResult.OK;
            }

        }

    }


    private string GetSkey()
    {
        string skey = string.Empty;

        GetCookie();
        List< Cookie> listCookie = GetAllCookies(_cookie);
        foreach ( Cookie c in listCookie)
        {
            if (c.Name == "skey")
            {
                skey = c.Value;
                break;
            }
        }
        return skey;
    }

    private void GetCookie()
    {
        if (webBrowser1.Document.Cookie != null)
        {
            string cookieStr = webBrowser1.Document.Cookie;
            string[] cookstr = cookieStr.Split( ';');
            foreach ( string str in cookstr)
            {
                string[] cookieNameValue = str.Split( '=');
                Cookie ck = new Cookie(cookieNameValue[0].Trim().ToString(), cookieNameValue[1].Trim().ToString());
                ck.Domain = ".qq.com";
                _cookie.Add(ck);
            }
        }
    }


    /// <summary>
    /// 把CookieContainer所有的Cookie读出来
    /// </summary>
    /// <param name="cc"></param>
    /// <returns></returns>
    private List<Cookie> GetAllCookies( CookieContainer cc)
    {
        List< Cookie> lstCookies = new List< Cookie>();
        Hashtable table = ( Hashtable)cc.GetType().InvokeMember( "m_domainTable",
            System.Reflection. BindingFlags.NonPublic | System.Reflection.BindingFlags .GetField |
            System.Reflection. BindingFlags.Instance, null , cc, new object [] { });

        foreach ( object pathList in table.Values)
        {
            SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list" ,
                System.Reflection. BindingFlags.NonPublic | System.Reflection.BindingFlags .GetField
                | System.Reflection. BindingFlags.Instance, null , pathList, new object[] { });
            foreach ( CookieCollection colCookies in lstCookieCol.Values)
                foreach ( Cookie c in colCookies)
                    lstCookies.Add(c);
        }

        return lstCookies;
    }
}

从WebBrowser控件中获取CookieContainer

从WebBrowser控件中获取CookieContainer

private CookieContainer _cookie = new CookieContainer();
private void GetCookie()
{
    if (webBrowser1.Document.Cookie != null)
    {
        string cookieStr = webBrowser1.Document.Cookie;
        string[] cookstr = cookieStr.Split( ';');
        foreach ( string str in cookstr)
        {
            string[] cookieNameValue = str.Split( '=');
            Cookie ck = new Cookie(cookieNameValue[0].Trim().ToString(), cookieNameValue[1].Trim().ToString());
            ck.Domain = ".qq.com";
            _cookie.Add(ck);
        }
    }
}

从CookieContainer中获取所有Cookie

从CookieContainer中获取所有Cookie:

/// <summary>
/// 把CookieContainer所有的Cookie读出来
/// </summary>
/// <param name="cc"></param>
/// <returns></returns>
private List <Cookie > GetAllCookies(CookieContainer cc)
{
    List<Cookie> lstCookies = new List< Cookie>();
    Hashtable table = ( Hashtable)cc.GetType().InvokeMember( "m_domainTable",
        System.Reflection. BindingFlags.NonPublic | System.Reflection.BindingFlags .GetField |
        System.Reflection. BindingFlags.Instance, null , cc, new object [] { });

    foreach (object pathList in table.Values)
    {
        SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list" ,
            System.Reflection. BindingFlags.NonPublic | System.Reflection.BindingFlags .GetField
            | System.Reflection. BindingFlags.Instance, null , pathList, new object[] { });
        foreach ( CookieCollection colCookies in lstCookieCol.Values)
            foreach ( Cookie c in colCookies)
                lstCookies.Add(c);
    }

    return lstCookies;
}


///////////////////////////////////////////////////以下是使用样例代码:
private string GetSkey()
{
    string skey = string.Empty;

    GetCookie();
    List<Cookie> listCookie = GetAllCookies(_cookie);
    foreach (Cookie c in listCookie)
    {
        if (c.Name == "skey")
        {
            skey = c.Value;
            break;
        }
    }
    return skey;
}

lua的.NET实现: NeoLua

NeoLua 可以让你在 .NET 的应用中使用 Lua 语言或者反过来(当前支持的 Lua 版本是 5.2),其目的是遵循 C-Lua 实现并且合并完整的 .NET 框架支持。你可以很方便在 Lua 程序中调用 .NET 的 functions/classes/interfaces/events ,同时也可以轻松在 .NET 应用中调用 Lua 的变量和函数。

github: https://github.com/neolithos/neolua

codeplex: https://neolua.codeplex.com/

Django安装过程

Django安装过程

  1. 在官网下载安装包,并解压
  2. 找到setup.py所在的目录,执行python setup.py install
  3. 上面的命令执行完成,django 就安装完了,安装目录在%Phthon的安装目录%\Lib\site-packages
  4. 运行程序  python manage.py runserver

检查django版本:

import django
django.VERSION

或

python -c "import django; print(django.get_version())"

WinForm listView自动滚动

WinForm listView自动滚动,使用EnsureVisible可以让listView控件自动滚动。

如下:

ListViewItem item = new ListViewItem (info.CompanyName); //这个是第一行第一列
item.SubItems.Add(info.ZiHao); //第一行第二列
item.SubItems.Add(info.Pinyin);
item.SubItems.Add(info.Attribute);
listView1.Items.Add(item);
listView1.EnsureVisible(item.Index); //自动滚动

SQLite时间操作

获取当前时间:

select CURRENT_TIMESTAMP;  –以格林尼治标准时间为基准

select datetime('now');  –以格林尼治标准时间为基准

获取本地当前时间:

select datetime('now', 'localtime');
-- 将UNIX时间戳转化为时间日期格式
SELECT datetime(1092941466, 'unixepoch');
-- 将UNIX时间戳转化为本地时间
SELECT datetime(1092941466, 'unixepoch', 'localtime');

获取时间差,以秒为单位,格林尼治标准时间为基准

select strftime('%s',datetime('now')) - strftime('%s','2015-03-03 19:50:00');

获取时间差,以天为单位,当前时区时间为基准

select strftime('%J', datetime('now', 'localtime')) - strftime('%J','2015-03-03 20:08:00');