用C#来实现QQ宠物自动挂机和投喂功能

其实这个想法在初中的时候就有了,当时因为什么都不会,所以也没有去做这个东西

昨天下午十分无聊,突然想起来了这件事,便打开vs写了一波

0x00、基本原理:

这个东西是利用3gqq来实现的,3gqq几乎都是纯文本,也方便进行封装来实现功能

在几年前,3gqq是使用sid来存储用户的登陆信息的,但是我昨天测试了一下,现在已经改为用cookie来保存登陆信息(虽然在网址里也保存了sid参数)

打开http://pet.3g.qq.com/后的界面:

我们可以很轻松地找到真正用来存储登陆信息的两个cookie值,后面的测试也证实了这一点:

我们记下这个uin和skey的值,在后面会经常用到

0x01、构造http请求函数:

我们可以根据上面来编写获取信息的方法:

/// <summary>  
/// GET 请求与获取结果  
/// </summary>  
public static string HttpGetPet(string Url, string postDataStr, string uin, string skey)
{
    try
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
        request.Method = "GET";
        request.ContentType = "text/html;charset=UTF-8";
        request.Headers.Add("cookie", "uin=" + uin + "; skey=" + skey);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        Stream myResponseStream = response.GetResponseStream();
        StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
        string retString = myStreamReader.ReadToEnd();
        myStreamReader.Close();
        myResponseStream.Close();
        return retString;
    }
    catch { }
    return "";
}

可以看到参数里有uin和skey的值,我们可以测试一下:

string html = HttpGetPet("http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet", "", "你的uin", "你的skey");
Console.WriteLine(html);
Console.ReadLine();

获取结果:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head>
<meta http-equiv="cache-control" content="no-cache"/>
</head>
    <card id="mainid" title="手机QQ宠物" ontimer="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=1">
    <timer value="9000"/>
    <p><a href="http://app.z.qq.com/app_list.jsp?B_UID=&amp;">应用</a>&gt;手机QQ宠物</p>
        <p>状态 | <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=2">资料</a> | <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=3">喂养</a> | <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=4">粉钻特权</a></p>
        <p>

</p>
<p>
<a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=30&amp;gift=0">我的礼包</a>&nbsp;&nbsp;<a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/invite?&amp;petid=281914025101042&amp;g_f=0">好友邀请</a>
</p>
<p>
<img src="http://img.pet.qq.com/phone_pet/img/index12.gif" alt="QQ宠物"/>
</p>
<p>
   我不是一个人看书,旅行,吃饭,因为有晨旭的陪伴!
</p>

<p>
    昵称:pet <img src="http://img.pet.qq.com/phone_pet/LV1_0.gif" alt="VIP"/> <a href="http://sqq.3g.qq.com/s?aid=bizp&amp;pt=page&amp;pc=qzonepetvip&amp;sid=%s"><img src="http://img.pet.qq.com/phone_pet/sq/L1_0.gif" alt="SUPERQ"/></a><br/>
    QQ号:961726194 <br/>
    等级:47<br/>
    状态:空闲

</p>
<p>
    <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=24">宠 物日志</a>
</p>
<p>
    成长值:926418/955400<br/>
    饥饿值:3570/6000 <br/>
    清洁值:3616/6000  <br/>
    健康值:5/5      <br/>
    心情:1000/1000 兴奋<br/>
    成长速度: 260/小时  <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=4">粉钻可加速</a><br/>

    刷新时间(分钟):<input type="text" size="2" maxlength="2" format="*N" value="15" name="curtime"/>
    <anchor>
        确定
        <go href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=1" method="post">
            <postfield name="freshtime" value="$curtime"/>
        </go>
    </anchor>
    <anchor>
        刷新
        <go href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=1" method="post">
            <postfield name="freshtime" value="$curtime"/>
        </go>
    </anchor>
</p>



        <p><a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=5">学习</a> | <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=6">打工</a> | <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=7">旅游</a> | <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/farm?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=10">农场</a> | <a href="http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/fish?&amp;petid=281914025101042&amp;g_f=0&amp;cmd=11">渔场</a> | <a href="http://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?cmd=index&amp;&amp;zapp_uin=961726194&amp;from=qqpet">大乐斗</a> | <a href="http://pet.gamebbs.qq.com/forum.php?&amp;">论坛</a> </p>

    <p> <a href="http://info60.z.qq.com/infocenter_v2.jsp?B_UID=0">个人中心</a>-<a href="http://blog60.z.qq.com/setting/console.jsp">设置</a>-<a href="http://blog60.z.qq.com/feedback/index.jsp">反馈</a>-<a href="http://blog60.z.qq.com/logout.jsp">退出</a><br/><a href="http://info.3g.qq.com/g/s?aid=index&amp;KqqWap_Act=6&amp;g_f=591&amp;g_ut=1">手机腾讯网</a>-<a href="http://info.3g.qq.com/g/s?aid=navigation&amp;KqqWap_Act=6&amp;g_f=592&amp;g_ut=1">导航</a>-<a href="http://wap.soso.com/navi.jsp?g_f=2119&amp;g_ut=2">搜索</a><br/>我的<a href="http://house60.3g.qq.com/g/s?aid=home_self&amp;KqqWap_Act=6&amp;g_f=595&amp;g_ut=1">家园</a>.<a href="http://f.qq.com/index.php?mod=login&amp;act=qzone&amp;qq=0&amp;&amp;g_f=2455">朋友</a>.<a href="http://ti50.3g.qq.com/g/s?g_f=2507&amp;aid=h&amp;&amp;g_ut=1">微博</a><br/>小Q报时(18:47)<br/> </p>
    </card>
</wml>

如果获取到了正确信息,向上面那样,说明试验成功

0x02、把正则封装好:

根据我的习惯,因为我没有用过dom树解析,所以我在这里用的是正则,封装的函数如下:

/// <summary>
/// 直接获取正则表达式的最后一组匹配值
/// </summary>
/// <param name="str"></param>
/// <param name="regstr"></param>
/// <param name="name"></param>
/// <returns></returns>
public static string Reg_get(string str, string regstr, string name)
{
    string result = "";
    MatchCollection matchs = Reg_solve(str, regstr);
    foreach (Match item in matchs)
    {
        if (item.Success)
        {
            result = item.Groups[name].Value;
        }
    }
    return result;
}
public static MatchCollection Reg_solve(string str, string regstr)
{
    Regex reg = new Regex(regstr, RegexOptions.IgnoreCase);
    return reg.Matches(str);
}

0x03、获取&返回信息:

因为我是放到qq机器人上面用的,所以先设置好统一回复语句:

public static string pleaseLogin = "请设置登陆信息!";
public static string petMore = "更多宠物命令请回复“宠物助手”";

获取基本信息的方法如下:

/// <summary>
/// 获取宠物基本信息
/// </summary>
/// <param name="uin"></param>
/// <param name="skey"></param>
/// <returns></returns>
public static string GetPetState(string uin, string skey)
{
    string result = "";
    string html = HttpGetPet("http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet", "", uin, skey);
    html = html.Replace("\r", "");
    html = html.Replace("\n", "");
    if (html.IndexOf("手机统一登录") != -1)
        return pleaseLogin;
    result += Reg_get(html, "alt=\"QQ宠物\"/></p><p>(?<say>.*?)<", "say").Replace(" ", "") + "\r\n"
            + "宠物名:" + Reg_get(html, "昵称:(?<level>.*?)<", "level").Replace(" ", "") + "\r\n"
            + "等级:" + Reg_get(html, "等级:(?<level>.*?)<", "level").Replace(" ", "") + "\r\n"
            + "状态:" + Reg_get(html, "状态:(?<now>.*?)<", "now").Replace(" ", "") + "\r\n"
            + "成长值:" + Reg_get(html, "成长值:(?<now>.*?)<", "now").Replace(" ", "") + "\r\n"
            + "饥饿值:" + Reg_get(html, "饥饿值:(?<now>.*?)<", "now").Replace(" ", "") + "\r\n"
            + "清洁值:" + Reg_get(html, "清洁值:(?<now>.*?)<", "now").Replace(" ", "") + "\r\n"
            + "心情:" + Reg_get(html, "心情:(?<now>.*?)<", "now").Replace(" ", "") + "\r\n" + petMore;
    return result;
}

列出宠物喂养物品:

/// <summary>
/// 喂养宠物选择页面
/// </summary>
/// <param name="uin"></param>
/// <param name="skey"></param>
/// <returns></returns>
public static string FeedPetSelect(string uin, string skey,string page)
{
    string result = "";
    string html = HttpGetPet("http://qqpet.wapsns.3g.qq.com/qqpet/fcgi-bin/phone_pet", "cmd=3&page=" + page, uin, skey);
    html = html.Replace("\r", "");
    html = html.Replace("\n", "");
    if (html.IndexOf("手机统一登录") != -1)
        return pleaseLogin;
    result += "我的账户:" + Reg_get(html, "我的账户:(?<name>.*?)<", "name").Replace(" ", "") + "\r\n";
    int i = 0;
    MatchCollection matchs = Reg_solve(Reg_get(html, "元宝(?<name>.*?)上页", "name").Replace(" ", ""), "<p>(?<name>.*?)<br");
    string[] name = new string[matchs.Count];
    string[] id = new string[matchs.Count];
    foreach (Match item in matchs)
    {
        if (item.Success)
        {
            name[i++] += item.Groups["name"].Value;
        }
    }
    i = 0;
    matchs = Reg_solve(Reg_get(html, "元宝(?<name>.*?)上页", "name").Replace(" ", ""), "goodid=(?<id>.*?)\"");
    foreach (Match item in matchs)
    {
        if (item.Success)
        {
            id[i++] += "物品id:" + item.Groups["id"].Value;
        }
    }
    
    for(int j = 0; j < i;j++)
    {
        result += name[j] + "\r\n" + id[j] + "\r\n";
    }
    if(Reg_get(html, "上页</a>(?<name>.*?)/", "name").Replace(" ", "") != "")
    {
        result += "第" + Reg_get(html, "上页</a>(?<name>.*?)/", "name").Replace(" ", "") + "页,共"
               + Reg_get(html, "上页</a>(.*?)/(?<name>\\d+)", "name").Replace(" ", "") + "页" + "\r\n";
    }
    else
    {
        result += "第" + Reg_get(html, "上页(?<name>.*?)/", "name").Replace(" ", "") + "页,共"
                + Reg_get(html, "上页(.*?)/(?<name>\\d+)", "name").Replace(" ", "") + "页" + "\r\n";
    }
    return result + petMore;
}

基本就是这些了,再贴代码的话,这篇文章的字数就超过最大字数限制了

所有代码都在此处:

https://gist.github.com/chenxuuu/d9d682b58a40ead00250c00c43f1a7f3

欢迎各位大佬进行二次开发,如果开发出来了成果,请在此处留言,谢谢!

发表评论

您的电子邮箱地址不会被公开。