Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 370|回复: 0

[网络编程学习]开心农场简易外挂实现

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-5 00:03:42 | 显示全部楼层 |阅读模式
    最近开心农场非常火,同学用C#模拟鼠标点击操作做了一个小外挂,但是这样做有如下缺点:1、计算机不能做其他事情,2、必须开着浏览器,3、对所有好友点一遍的时间太慢,4、对于开发者来说技术含量低了点,呵呵。    所以我尝试着改进这种实现,我的想法是:不用开启浏览器,直接运行一个应用程序,该程序将自己伪装成一个浏览器,与服务器连接,并发送浇水、除虫等命令。这样,甚至可以使用多线程向服务器发送命令,无需等待服务器返回一个结果之后再发送下一条命令。从而完全避开了上面几个缺点。    这样做首先要做的是分析在执行每一个浇水(及其他)动作的时候,浏览器向服务器发送了什么请求,有哪些参数,每一个参数的含义是什么,还有服务器端的返回值及其意义。分析完之后,就可以使用java模拟浏览器与服务器建立连接并发送类似的请求。(还有一点,在向服务器端发送浇水请求的时候,你需要知道好友的userId,所以首先需要从服务器获取当前用户的所有好友 userId,然后对每一个userId分别进行各种动作)。
      
       
       
         
       

         
       
      
        代码如下:
    1. import java.io.FileInputStream;  
    2. import java.io.IOException;  
    3. import java.io.PrintStream;  
    4. import java.io.PrintWriter;  
    5. import java.net.MalformedURLException;  
    6. import java.net.SocketTimeoutException;  
    7. import java.net.URL;  
    8. import java.net.URLConnection;  
    9. import java.util.Iterator;  
    10. import java.util.Properties;  
    11. import java.util.Scanner;  
    12. import java.util.Set;  
    13. import net.sf.json.JSONArray;  
    14. import net.sf.json.JSONObject;  
    15. /**
    16.   * 人人网开心农场机器人,能够自动获取好友列表,并对每一个好友的所有作物进行除草、除虫、浇水、摘菜等动作。
    17.   * @author without me
    18.   *
    19.   */  
    20. public class Robot  
    21. {  
    22.      //三个配置文件  
    23.      private static final String FARM_FILE = "f.properties"; // 存储向服务器发送的两个参数  
    24.      private static final String OWNER_FILE = "owner_robot.txt"; //存储好友userId列表  
    25.      private static final String CON_FILE = "c.properties";  ///存储连接的Header信息  
    26.       
    27.      //请求服务器的URL  
    28.      private static final String urlStr =
    29.         "http://xn.hf.fminutes.com/api.php?mod=farmlandstatus&act=&farmKey=&farmTime=&inuId=";  
    30.      private static final String getFriendUrl =
    31.          "http://xn.hf.fminutes.com/api.php?mod=friend&farmKey=&farmTime=&inuId=";  
    32.       
    33.      //POST参数  
    34.      private static final String postStr =
    35.         "Referer=http://xn.cache.fminutes.com/images/v3_3/module/Main.swf?
    36.         v=5&Content-type=application/x-www-form-urlencoded&Content-length: 31&ownerId=&place=";  
    37.      private static final String getFriPost =
    38.        "Referer=http://xn.cache.fminutes.com/images/v3_3/module/Main.swf?
    39.        v=5&Content-type+application/x-www-form-urlencoded&Content-length=26&fv=1261051588&refresh=true";  
    40.       
    41.      private static final int TIME_OUT = 4000;   //超时时间 4秒  
    42.       //出现IOException时的提示信息  
    43.      private static final String IOE_PROPMT = "无法连接至服务器,请检查网络连接,或者服务器地址是否已更改。";
    44.      private static final String[] action = { "clearWeed", "spraying", "water", "scrounge" };  
    45.       
    46.      private String[] owner;  
    47.      private Properties farmProp = new Properties();  
    48.      private Properties connProp = new Properties();  
    49.       
    50.      /**
    51.       * 用3个配置文件对当前的Robot进行初始化,
    52.       * 包括:从OWNER_FILE中读取所有好友信息,从 FARM_FILE中读取向服务器发送的两个参数farmKey,farmTime
    53.       * 从CON_FILE中读取连接的Header信息。
    54.       * @throws IOException
    55.       */  
    56.      public Robot() throws IOException  
    57.      {  
    58.          Scanner scan = new Scanner(new FileInputStream(OWNER_FILE));  
    59.          owner = new String[scan.nextInt()];  
    60.          int index = 0;  
    61.          scan.nextLine();  
    62.          while (scan.hasNext())  
    63.          {  
    64.              owner[index++] = scan.nextLine();  
    65.          }  
    66.          scan.close();  
    67.          farmProp.load(new FileInputStream(FARM_FILE));  
    68.          connProp.load(new FileInputStream(CON_FILE));  
    69.      }  
    70.      /**
    71.       * 获取所有当前用户的好友,并将好友ID保存至文件OWNER_FILE
    72.       */  
    73.      public void getFriends()  
    74.      {  
    75.          try  
    76.          {  
    77.              //新建一个URL连接,连接地址为 url  
    78.              String url = getFriendUrl.replaceFirst("", farmProp.getProperty("farmKey"));  
    79.              url = url.replaceFirst("", farmProp.getProperty("farmTime"));  
    80.              URLConnection con = new URL(url).openConnection();  
    81.              con.setConnectTimeout(TIME_OUT);  
    82.              con.setDoOutput(true);  
    83.                
    84.              //设置该链接的Header,Header的内容由Properties来定义  
    85.              setConnHeader(con, connProp);  
    86.                
    87.              //在连接中写入Post的内容  
    88.              PrintStream printStr = new PrintStream(con.getOutputStream());  
    89.              printStr.print(getFriPost);  
    90.              printStr.close();  
    91.                
    92.              //获取服务器返回内容并解析  
    93.              Scanner scan = new Scanner(con.getInputStream());  
    94.              StringBuilder fileBuilder = new StringBuilder();  
    95.              int cnt = 0;  
    96.              while (scan.hasNext())  
    97.              {  
    98.                String rtnStr = scan.nextLine();  
    99.                JSONArray jsonArray = JSONArray.fromObject("[" + rtnStr + "]").getJSONObject(0).getJSONArray("data");  
    100.                cnt += jsonArray.size();  
    101.                //将服务器返回的所有用户ID 加入fileBuilder中  
    102.                for(int i = 0; i < jsonArray.size(); ++ i)  
    103.                    fileBuilder.append(jsonArray.getJSONObject(i).getString("userId") + "
    104. ");  
    105.              }  
    106.              scan.close();  
    107.                
    108.              //将所有用户ID写入文件OWNER_FILE  
    109.              PrintWriter writer = new PrintWriter(OWNER_FILE);  
    110.              writer.write(String.valueOf(cnt) + "
    111. " + fileBuilder);  
    112.              writer.close();  
    113.          }  
    114.          catch (MalformedURLException e)  
    115.          {  
    116.              e.printStackTrace();  
    117.          }  
    118.          catch (IOException e)  
    119.          {  
    120.              System.out.println(IOE_PROPMT);  
    121.          }  
    122.      }  
    123.      /**
    124.       * 对所有好友的所有地进行4种操作:浇水、除虫等,每一个好友由单独一个线程完成
    125.       */  
    126.      public void work()  
    127.      {  
    128.          //为每一个好友建立一个线程并分别执行操作  
    129.          Thread[] thread = new Thread[owner.length];  
    130.          for (int k = 0; k < owner.length; ++k)  
    131.          {  
    132.              thread[k] = new Thread(new RobotThread(owner[k]));  
    133.              thread[k].start();  
    134.          }  
    135.      }  
    136.       
    137.      /**
    138.       * 机器人线程的内部类,一个这样的线程针对单独一个好友进行操作
    139.       * @author without me
    140.       *
    141.       */  
    142.      class RobotThread implements Runnable  
    143.      {  
    144.          private String owner;  
    145.          public RobotThread(String owner)  
    146.          {  
    147.              this.owner = owner;  
    148.          }  
    149.            
    150.          @Override  
    151.          public void run()  
    152.          {  
    153.              for (int j = 0; j < 4; ++j)  
    154.              {  
    155.                  for (int i = 0; i < 18; ++i)  
    156.                  {  
    157.                      URLConnection con;  
    158.                      try  
    159.                      {  
    160.                          //新建一个URL连接,连接地址为tmpUrlStr,将所有urlStr中未设置的参数(即)修改为 farmProp中的值  
    161.                          String tmpUrlStr = urlStr.replaceFirst("", action[j]);  
    162.                          tmpUrlStr = tmpUrlStr.replaceFirst("", farmProp.getProperty("farmKey"));  
    163.                          tmpUrlStr = tmpUrlStr.replaceFirst("", farmProp.getProperty("farmTime"));  
    164.                          URL url = new URL(tmpUrlStr);  
    165.                          con = url.openConnection();  
    166.                          con.setConnectTimeout(TIME_OUT);  
    167.                          //设置连接的 Header  
    168.                          setConnHeader(con, connProp);  
    169.                          con.setDoOutput(true);  
    170.                            
    171.                          //在连接中写入Post的内容  
    172.                          PrintStream printStr = new PrintStream(con.getOutputStream());  
    173.                          printStr.print(postStr.replace("", owner) + i);  
    174.                          printStr.close();  
    175.                            
    176.                          //获取服务器返回内容并解析  
    177.                          Scanner scan = new Scanner(con.getInputStream());  
    178.                          if (scan.hasNext())  
    179.                          {  
    180.                              JSONArray jsonArray = JSONArray.fromObject("[" + scan.nextLine() + "]");  
    181.                              JSONObject jsonObject = jsonArray.getJSONObject(0);  
    182.                               
    183.                              //将服务器返回的提示(或是错误信息)打印到客户端  
    184.                              if (jsonObject.has("direction"))  
    185.                                  System.out.println(owner + " : " +jsonObject.getString("direction"));  
    186.                              else if (jsonObject.has("error"))  
    187.                                  System.out.println(owner + " : " +jsonObject.getString("error"));  
    188.                          }  
    189.                          scan.close();  
    190.                      }  
    191.                      catch (SocketTimeoutException ste)  
    192.                      {  
    193.                          --i;    //如果某一操作超时了,返回继续执行该操作  
    194.                      }  
    195.                      catch (IOException e)  
    196.                      {  
    197.                          System.out.println(IOE_PROPMT);  
    198.                      }  
    199.                  }  
    200.              }  
    201.          }  
    202.      }  
    203.      /**
    204.       * 设置连接的Header,即设置RequestProperty
    205.       * @param conn 需要设置Header的 URLConnection
    206.       * @param prop Header内容存储的Properties
    207.       */  
    208.      private static void setConnHeader(URLConnection conn, Properties prop)  
    209.      {  
    210.          Set keySet = prop.keySet();  
    211.          Iterator iter = keySet.iterator();  
    212.          String key;  
    213.          //将Porperties中的所有内容都设置到连接的Header中  
    214.          while (iter.hasNext())  
    215.          {  
    216.              key = (String) iter.next();  
    217.              conn.setRequestProperty(key, prop.getProperty(key));  
    218.          }  
    219.      }  
    220.       
    221.       
    222. }  
    复制代码
    其中需要用到3个文件,分别是 1、FARM_FILE:
    farmKey=78247873dd911c736d3cb15603571c31
    farmTime=1261223397  farmKey=78247873dd911c736d3cb15603571c31
    farmTime=1261223397 存储向服务器端发送的两个参数(现在明确知道的是第二个参数:是指农场的全局时间,第一个参数应该是请求服务器的一个密钥,如果密钥错误会阻止操作――一般会返回重新登录的提示,一个密钥的可用时间是有限的,所以要过一个小时左右更新一次 farmKey,但可惜,我还不知道如何用程序自动更新这个密钥) 2、OWNER_FILE:
    46
    83***909
    72***788
    26***857
    //还有43个好友userId   是所有好友的userId,第一行是好友的数量。 3、CON_FILE: Host=xn.hf.fminutes.com
    User-Agent=
        Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 (.NET CLR 3.5.30729)
    Accept=text/HTML,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language=zh-cn,zh;q=0.5
    Accept-Encoding=gzip,deflate
    Accept-Charset=GB2312,utf-8;q=0.7,*;q=0.7
    Keep-Alive=300
    Connection=keep-alive
    Cookie=__utma=*********.2079770661.1261199924.*********.126122***63.*;
    __utmz=38185962.**********.9.9.utmcsr=apps.renren.com|utmccn=(referral)|utmcmd=referral|utmcct
    =/happyfarm; xn_sig_inu=b910579fd123cfef2d92f7d36bf9626c; xn_sig_user
    =********; xn_sig_session_key=2.1e8b614040cb******5f9395ae413.3600.1261227600-47305639; __utmc
    =38185962; __utmb=38185962.1.10.1261223363

          是每一个向服务器发送的请求的Header部分,Header部分包括用户的Cookie,通过Cookie服务器识别当前用户是谁,不同的用户该文件内容不一样。在程序中使用setConnectionHeader()方法将每一个请求的Header设置成文件中的内容。如果需要使用这个程序的话,必须用firebug获取到你的Cookie的内容,并修改这个文件。(由于Cookie中包含了我的用户信息,所以我用*屏蔽掉了一些内容) 程序核心的方法有两个:
    1、getFriends()用于第一次使用时获取当前用户的好友信息。
    2、work()对所有好友的每块地进行浇水等动作。我是对每一个好友都用一个线程单独操作,比如我有46个好友,就会有 46个线程同时请求服务器,这样效率高很多(如果想要更快,可以使用更多线程)。main函数就两行
    Robot r = new Robot();
    r.work();  这是第一次之后的调用,第一次应该先调用getFriends();    程序的含义看注释应该能够明白,如果要使用程序,一定要将 CON_FILE中的Cookie改为你自己的Cookie,其次,FARM_FILE中的farmKey和farmTime可能也需要修改。修改完着两个文件,程序应该是能够执行的。而好友列表文件,调用Robot的getFriends()方法就能够生成。 PS:程序中用到了JSON-lib来解析服务器返回的数据,JSON-lib下载地址:http://sourceforge.net/projects/json-lib/


      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/11/5/000342562.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 13:44 , Processed in 0.297285 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表