从零开始编写农场助手-1

分类: Python, Web 2.0, 笔记 | 标签: , , | 日期:2010-03-31 | 967 views

前言(废话若干)如下

但凡腾讯涉足的产业,必然会导致另一个产品的被“借鉴”和“二次开发”。QQ农场亦如是。

在开心农场刚从开心网挖过来的时候,所有一切都是照搬的,后来名字改了,道貌岸然的成了QQ农场。之后的QQ牧场已经分不清楚究竟是从山寨的开心牧场中偷过来的还是仿造的阿里旺旺的牧场了。

总之,在中国一切都很均质化,一旦有了一点新颖和不同,广大的围观者立刻围而攻之,纷纷效仿。就这样你也有,我也有,大家全都有。可这不是水浒传,梁山108好汉也是各有特色的。

你抄过来我抄过去,我造出了你没有的,几天后你有了;几天前你有我没有的,几天后我一样可以有。这不是知识产权的问题也不是抄袭,这说明中国国情决定了所有人都有红眼病,见不得别人超越自己,只是这样子反超越有点小人之嫌。

扯远了,我们今天说的是农场助手。从来没有这样一款“精品养成类游戏”获得如此巨大的成功,不管你是否愿意,正如腾讯宣称的,养成的游戏养成了几乎从老到小的全民偷菜,即使高学历的教授也照样会为了守住自己的一块地而废寝忘食。不得不承认,在用户群如此巨大的优势下,腾讯可以稳坐农场、牧场第一把交椅。而且,它还在不断的推陈出新,来挽回一些放弃这款游戏的QQ用户,即使,有不少人已经对这种周而复始、精神紧绷的、“白领一族”、办公室游戏开始感到厌倦,因为,为了保持等级,你的眼睛要时刻关注地球时间,随时警惕周围投射出的觊觎眼光和第三只手。

个人觉得,与之类似的所有办公室类精品养成游戏都在无形之中,增加了所有中小企业的运作成本:你的员工要24小时高度警觉,保护好自己的阵地不让他人侵犯,即使回到家里,半夜起床也会惦记着他人地里的某个稀有物品。这对GDP的增长是很有影响的,因为影响了员工的起居生活,影响了员工的心理健康,改变了员工的工作态度,有些员工还有可能因此而互相算计,勾心斗角,这些都是值得注意的潜在危机。

所以,广大的程序爱好者为偷菜种菜者“减负”所做出的努力是显著和无法磨灭的,他们应该受到教育部、民政部、工业与信息化部等部门的鼓励,不管那是精神上还是物质上的。这些帮助使用者减少或者免于频繁使用鼠标和键盘来操作QQ农场和牧场的准环保程序(之所以准,是因为很多软件内嵌广告,这是令人唾弃和无可奈何的,毕竟程序员要吃饭要生存),被腾讯冠以外挂的头衔。

什么叫外挂?以前的网游游戏中,通过同时打开第三方程序,来实现自动刷经验和自动打怪以及作弊的行为算外挂。那,腾讯通过浏览器和Flash来部署的QQ农场有客户端吗?回答是没有。没有任何方便用户使用的客户端,某种程度上,腾讯逃避为用户制作简洁和高效的客户端,这在QQ客户端上就能体现出来。(QQ客户端从2003年的不到10M增加到2010年的不少于30M,其中核心功能并没有本质的改变,增加的网盘功能只有很小部分,大部分功能用于花瓶功能-如QQ秀、QQ宠物、以及背着用户替goverment搜集各种证据的后台程序等等-也许他们会称之为收集用户使用习惯)没有客户端,何来外挂一说,往哪挂,挂在谁那?

下面开始从零开始着手编写助手,而不是外挂。或者我们可以称其为机器人。

腾讯使用网页的cookie来检测用户id,用flash来联络服务器实现用户操作。因此,首先需要知道的是flash和服务器的通信方式。这点可以下载腾讯的swf然后反编译查看其中的函数,cookie则相对容易,只要使用特定的用户名密码获取一个cookie之后在联络中使用即可,虽然可能还涉及到验证码以及图像识别的处理,但那是后话了。

为了获得swf,首先要查看qzone的网页源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<span style="line-height: normal; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-size: x-small;"> var helpBtn = $('help_btn');
  /**
  * 切换农场牧场
  * @param {String} module 模式的名称 nc 表示农场, mc表示牧场(特此声明:鄙视拼音啊,切此函数命名不是我写的)
  *广告
  *"ShopHeadLink" : "&lt;u&gt;疯抢!上拍拍充话费送化肥!&lt;/u&gt;|http://www.paipai.com/chong/charge_index_event.shtml?PTAG=30764.1.3"
  */
  var switchfarm = function(module){
  curModule = module;
  var app_id_map = {"mc":358,"nc":353};
  var invite_title_map = {"mc":"邀请好友开通牧场","nc":"邀请好友开通农场"};
   
  if(helpBtn){
  helpBtn.href = ['http://appimg.qq.com/happyfarm/html/farm_help/farm_help', curModule, '.html'].join('');
  }
   
  app_id = app_id_map[curModule];
  invite_title = invite_title_map[curModule];
   
  var flashvars = {
  "module" : module,
  "app_key" : "qzhf"
  };
</span>

里面的特此声明真让人捧腹啊。

接着看

var others = {"hmv2level":0,"hmv2CloseTime":1261929600,"batchStealHour":"5-10,12-13,19-22","cacheDiy":8,"cacheSeed":27,"buyToolHour":"5-24","buyToolTips":"新春来临,化肥使用量激增导致供应紧张,目前暂不能购买。","healthModeTime":"00:00 - 06:00","reqYellowlevel":2,"ShopToolLink":"","ShopHeadLink":"充话费买东西,送化肥送狗粮!|http://www.paipai.com/promote/2010/03/nongchang/?PTAG=10025.23.1","autoStatus":1,"mode":"qzone","filterLV":0,"reqLevel":"10","api_friend":"http://nc.qzone.qq.com/cgi-bin/cgi_farm_getFriendList?","api_friend_from":0,"api_friend_to":999,"api_listFilter":"","api_listFilter_from":1000,"api_listFilter_to":1000,"api_friendStatus":"","api_friendStatus_from":1000,"api_friendStatus_to":1000,"api_repertory":"","api_repertory_from":1000,"api_repertory_to":1000,"api_item":"","api_item_from":1000,"api_item_to":1000,"api_chat":"","api_chat_from":1000,"api_chat_to":1000,"api_user":"","api_user_from":1000,"api_user_to":1000,"domian":"farm.qzone","api_g1_from":0,"api_userseed":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_getuserseed?","api_reclaim":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_reclaim?","api_allinfo":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_getallinfo?","api_g1_to":999,"api_g2_from":0,"api_clearlog":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_clearfeed?","api_sendchat":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_sendchat?","api_clearchat":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_clearchat?","api_g2_to":999,"api_g3_from":0,"api_useritems":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_getuseritems?","api_notice":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_getnotice?","api_g3_to":999,"api_g4_from":0,"api_seedinfo":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_getseedinfo?","api_buyseed":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_buyseed?","api_g4_to":999,"api_getpackage":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_getpackage?","api_getpackage_from":0,"api_getpackage_to":999,"api_getpackagelist":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_getpackagelist?","api_getpackagelist_from":0,"api_getpackagelist_to":999,"api_g5_from":0,"api_activeitem":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_activeitem?","api_deactiveitem":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_deactiveitem?","api_g5_to":999,"api_g6_from":0,"api_item_buy":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_item_buy?","api_levelup":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_levelup?","api_item_shop":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_shop?","api_g6_to":999,"api_g7_from":0,"api_reclaimpay":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_reclaimpay?","api_welcome":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_welcome?","api_g7_to":999,"api_health_from":0,"api_health":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_sethealth?","api_health_to":999,"api_g8_from":0,"api_task_update":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_task_update?","api_task_run":"","api_task_accept":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_task_accept?","api_g8_to":999,"api_g9_from":0,"api_gettools":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_gettools?","api_buytool":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_buydog?","api_g9_to":999,"api_g10_from":0,"api_feedmoney":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_feedmoney?","api_g10_to":999,"filterUrl":"http://qbar.qq.com/application/r/?839782","noFoodTips":"新春来临,狗粮原材料供应紧张,目前暂不能购买。","missionTitle":"农场植树活动","missionPrepareTime":"2010-2-24 02:00:12","missionBeginTime":"2010-3-8 15:00:00","missionEndTime":"2010-3-10 15:05:00","missionPrepareHtml":"%e6%a4%8d%e6%a0%91%e8%8a%82%ef%bc%883%e6%9c%8812%e6%97%a5%ef%bc%89%e5%8d%b3%e5%b0%86%e5%88%b0%e6%9d%a5%ef%bc%8c%e6%98%a5%e5%a6%ae%e6%9d%a5%e5%86%9c%e5%9c%ba%e8%b7%9f%e5%a4%a7%e5%ae%b6%e4%b8%80%e8%b5%b7%e7%a7%8d%e9%93%b6%e6%9d%8f%e6%a0%91%e8%8b%97%e5%95%a6%ef%bc%81%e9%93%b6%e6%9d%8f%e6%a0%91%e6%98%af%e6%9c%80%e5%8f%a4%e8%80%81%e3%80%81%e6%9c%80%e7%8e%af%e4%bf%9d%e7%9a%84%e6%a0%91%e7%a7%8d%ef%bc%8c%e8%a6%81%e4%bb%8e%e6%88%91%e8%bf%99%e8%8e%b7%e5%be%97%e9%93%b6%e6%9d%8f%e6%a0%91%e7%a7%8d%e5%ad%90%e6%98%af%e7%9b%b8%e5%bd%93%e9%9a%be%e7%9a%84%e5%93%a6%ef%bc%81%3cbr+%2f%3e1%e3%80%81%e5%9c%a8%e7%99%bd%e8%90%9d%e5%8d%9c%e3%80%81%e7%8e%89%e7%b1%b3%e3%80%81%e7%95%aa%e8%8c%84%e3%80%81%e5%8d%97%e7%93%9c%e3%80%81%e8%a5%bf%e7%93%9c%e3%80%81%e4%b8%9d%e7%93%9c%e3%80%81%e8%8f%a0%e8%90%9d%e3%80%81%e6%9e%87%e6%9d%b7%e3%80%81%e6%9c%a8%e7%93%9c%e3%80%81%e7%95%aa%e7%9f%b3%e6%a6%b4%e8%bf%9910%e7%a7%8d%e4%bd%9c%e7%89%a9%e4%b8%ad%ef%bc%8c%e6%88%91%e5%b0%86%e9%80%89%e6%8b%a9%3cfont+color%3d%22%23ff0000%22%3e5%e7%a7%8d%e4%bd%9c%e4%b8%ba%e7%a7%98%e5%af%86%e4%bd%9c%e7%89%a9%3c%2ffont%3e%e3%80%82%3cbr+%2f%3e2%e3%80%81%e5%88%b0%e9%a2%86%e5%8f%96%e6%a0%91%e7%a7%8d%e5%ad%90%e6%97%b6%ef%bc%8c%e5%8f%aa%e8%a6%81%e4%bb%bb%e6%84%8f%e4%b8%80%e7%a7%8d%e7%a7%98%e5%af%86%e4%bd%9c%e7%89%a9%e5%9c%a8%e4%bb%93%e5%ba%93%e4%b8%ad%e7%9a%84%e6%95%b0%e9%87%8f%3cfont+color%3d%22%23ff0000%22%3e%e8%b6%85%e8%bf%87200%e4%b8%aa%3c%2ffont%3e%ef%bc%8c%e6%88%91%e5%b0%b1%e9%80%81%e4%bd%a0%3cfont+color%3d%22%23ff0000%22%3e%e9%93%b6%e6%9d%8f%e6%a0%91%e7%a7%8d%e5%ad%9010%e9%a2%97%3c%2ffont%3e%e3%80%82%3cbr+%2f%3e3%e3%80%81%e5%a6%82%e6%9e%9c%e4%bd%a0%e5%85%a8%e9%83%a8%e7%8c%9c%e4%b8%ad%ef%bc%8c%e5%b9%b6%e9%9b%86%e9%bd%90%e4%ba%865%e7%a7%8d%e7%a7%98%e5%af%86%e4%bd%9c%e7%89%a9%ef%bc%8c%e9%99%a4%e4%ba%8650%e9%a2%97%e9%93%b6%e6%9d%8f%e6%a0%91%e7%a7%8d%e5%ad%90%ef%bc%8c%e6%88%91%e8%bf%98%e5%8f%af%e4%bb%a5%e9%a2%9d%e5%a4%96%e9%80%81%e4%bd%a0%3cfont+color%3d%22%23ff0000%22%3e%e5%86%9c%e5%9c%ba%e7%bb%bf%e8%89%b2%e8%a3%85%e6%89%ae%e4%b8%80%e5%a5%97%3c%2ffont%3e%e5%93%a6%ef%bc%81%3cbr+%2f%3e%e5%88%b0%e5%ba%95%e5%93%aa%e4%ba%9b%e6%98%af%e6%98%a5%e5%a6%ae%e6%8c%87%e5%ae%9a%e7%9a%845%e7%a7%8d%e4%bd%9c%e7%89%a9%e5%91%a2%ef%bc%9f%e6%88%91%e5%b0%86%e5%9c%a83%e6%9c%888%e6%97%a515%e7%82%b9%e5%85%ac%e5%b8%83%e7%ad%94%e6%a1%88%ef%bc%81%3cbr+%2f%3e%e5%9c%b0%e7%90%83%e5%a6%82%e6%ad%a4%e7%be%8e%e4%b8%bd%ef%bc%8c%e7%bb%bf%e8%89%b2%e8%87%aa%e7%84%b6%e6%98%af%e6%9c%aa%e6%9d%a5%e5%b9%b8%e7%a6%8f%e7%9a%84%e4%bf%9d%e9%9a%9c%ef%bc%8c%e6%88%91%e4%bb%ac%e4%b8%80%e8%b5%b7%e5%8a%aa%e5%8a%9b%e5%90%a7%ef%bc%81%3cbr+%2f%3e%3ca+href%3d%22http%3a%2f%2fqbar.qq.com%2fappevent%2fr%2f%3f31%22+target%3d%22_blank%22%3e%3cfont+color%3d%22%23ff0000%22%3e%e6%9b%b4%e5%a4%9a%e6%b4%bb%e5%8a%a8%e8%af%a6%e6%83%85%26gt%3b%26gt%3b%3c%2ffont%3e%3c%2fa%3e%3cbr+%2f%3e%3cbr+%2f%3e%3cfont+color%3d%22%23ff0000%22%3e%e9%a2%86%e5%a5%96%e6%97%b6%e9%97%b4%ef%bc%9a3%e6%9c%888%e6%97%a5+15%e7%82%b9++-+3%e6%9c%8810%e6%97%a5+15%e7%82%b9%ef%bc%88%e6%af%8f%e4%ba%ba%e4%b8%80%e6%ac%a1%e9%a2%86%e5%8f%96%e6%9c%ba%e4%bc%9a%ef%bc%89%3c%2ffont%3e","missionBeginHtml":"%e6%98%a5%e5%a6%ae%e7%9a%84%e7%a7%98%e5%af%86%e4%bd%9c%e7%89%a9%e6%98%af%e4%bb%80%e4%b9%88%e5%91%a2%ef%bc%9f%e5%85%ac%e5%bc%80%e7%ad%94%e6%a1%88%ef%bc%8c%e9%a2%86%e5%8f%96%e5%a5%96%e5%8a%b1%e7%9a%84%e6%97%b6%e5%88%bb%e6%9d%a5%e4%b8%b4%e4%ba%86%ef%bc%81%3cbr+%2f%3e%e6%88%91%e6%8c%87%e5%ae%9a%e7%9a%84%e4%bd%9c%e7%89%a9%e5%88%86%e5%88%ab%e6%98%af%ef%bc%9b%3cb%3e%3cfont+color%3d%22%23ff0000%22%3e%e7%99%bd%e8%90%9d%e5%8d%9c%e3%80%81%e7%95%aa%e8%8c%84%e3%80%81%e8%a5%bf%e7%93%9c%e3%80%81%e8%8f%a0%e8%90%9d%e3%80%81%e6%9c%a8%e7%93%9c%3c%2ffont%3e%3c%2fb%3e%e5%93%a6%ef%bc%81%e6%80%8e%e4%b9%88%e6%a0%b7%ef%bc%9f%e4%bd%a0%e7%8c%9c%e4%b8%ad%e4%ba%86%e5%90%97%ef%bc%9f%3cbr+%2f%3e%e5%8f%aa%e8%a6%81%e4%bb%a5%e4%b8%8a%e4%bd%9c%e7%89%a9%e4%bb%bb%e6%84%8f%e4%b8%80%e4%b8%aa%e5%9c%a8%e4%bb%93%e5%ba%93%e4%b8%ad%e7%9a%84%e6%95%b0%e9%87%8f%3cfont+color%3d%22%23ff0000%22%3e%e8%b6%85%e8%bf%87200%3c%2ffont%3e%e4%b8%aa%ef%bc%8c%e9%83%bd%e5%8f%af%e4%bb%a5%e8%8e%b7%e8%b5%a0%3cfont+color%3d%22%23ff0000%22%3e10%e9%a2%97%e9%93%b6%e6%9d%8f%e6%a0%91%e7%a7%8d%e5%ad%90%3c%2ffont%3e%ef%bc%81%e9%9b%86%e9%bd%90%e4%ba%865%e7%a7%8d%e7%a7%98%e5%af%86%e4%bd%9c%e7%89%a9%ef%bc%8c%e9%99%a4%e4%ba%8650%e9%a2%97%e9%93%b6%e6%9d%8f%e6%a0%91%e7%a7%8d%e5%ad%90%ef%bc%8c%e8%bf%98%e5%b0%86%e8%8e%b7%e5%be%97%3cfont+color%3d%22%23ff0000%22%3e%e5%86%9c%e5%9c%ba%e7%bb%bf%e8%89%b2%e8%a3%85%e6%89%ae%e4%b8%80%e5%a5%97%3c%2ffont%3e%ef%bc%81%3cbr+%2f%3e%3cbr+%2f%3e%e5%87%86%e5%a4%87%e5%a5%bd%e4%ba%86%e5%90%97%ef%bc%9f%e9%a2%86%e5%8f%96%e5%a5%96%e5%8a%b1%ef%bc%8c%e4%bd%9c%e4%b8%ba%e5%9c%b0%e7%90%83%e7%8e%af%e4%bf%9d%e5%8d%ab%e5%a3%ab%ef%bc%8c%e5%9f%b9%e8%82%b2%e9%93%b6%e6%9d%8f%e6%a0%91%e8%8b%97%e5%90%a7%ef%bc%81%3cbr+%2f%3e%3c%2fbr+%2f%3e%3ca+href%3d%22http%3a%2f%2fqbar.qq.com%2fappevent%2fr%2f%3f31%22+target%3d%22_blank%22%3e%3cfont+color%3d%22%23ff0000%22%3e%e6%9b%b4%e5%a4%9a%e6%b4%bb%e5%8a%a8%e8%af%a6%e6%83%85%26gt%3b%26gt%3b%3c%2ffont%3e%3c%2fa%3e%3cbr+%2f%3e%3cbr+%2f%3e%3cfont+color%3d%22%23ff0000%22%3e%e9%a2%86%e5%a5%96%e6%97%b6%e9%97%b4%ef%bc%9a3%e6%9c%888%e6%97%a5+15%e7%82%b9++-+3%e6%9c%8810%e6%97%a5+15%e7%82%b9-%ef%bc%88%e6%af%8f%e4%ba%ba%e4%b8%80%e6%ac%a1%e9%a2%86%e5%8f%96%e6%9c%ba%e4%bc%9a%ef%bc%89%3c%2ffont%3e%0a","phpini":"http://farm.qzone.qq.com/cgi-bin/cgi_farm_ini_run?v=23","miniFactory":"2","miniFactoryText":"神秘的魔法师又来了,这次他又会用什么神奇的魔法把作物变成化肥呢?&lt;font color='#F47600'&gt;红枣 20个 %2B 丝瓜 10个 %2B 杨桃 5个 %2B 金币 500 %3D 1袋普通化肥&lt;/font&gt;&lt;br/&gt;每天一次机会,赶紧试试吧!他会在农场逗留到3月31日!","snowslide":3,"uinMode":1,"flowerDayTips":"%e5%86%85%e6%b5%8b%e6%9c%9f%e9%97%b4%e5%bc%80%e6%94%be%e7%bb%99%e9%bb%84%e9%92%bb%e7%94%a8%e6%88%b7%ef%bc%8c%e6%af%8f%e5%a4%a9%e6%af%8f%e4%ba%ba%e5%8f%af%e8%b5%a0%e9%80%81%e4%b8%80%e6%9d%9f%e9%b2%9c%e8%8a%b1%e5%93%a6%ef%bc%81","flowerYDLevel":1,"friend_list_mod":1000,"friend_list":"","friend_list_tips":"系统繁忙,请稍后再试!","steal_mod":1000,"steal":"","steal_tips":"为保证更加稳定的服务,系统正在对部分号码进行数据维护。在此时间段系统将暂停您的 “摘取”操作以保护您的数据安全。期间好友也不能摘取您的作物,其他操作正常!谢谢您的支持!","steal_tips_other":"为保证更加稳定的服务,系统正在对部分号码进行数据维护。在此号段的农场在维护期间将停止摘取以保护数据安全。期间好友也不能摘取您的作物,其他操作正常!谢谢您的支持!","enter_into_mod":1000,"enter_into":"","redirect_url":"http://imgcache.qq.com/qzone/v5/app/errorback/error_canvas.html#appid=353","recover":"http://nc.qzone.qq.com/cgi-bin/cgi_recover","user_mode":1000,"user":"1001-1002","phpini2":"http://mc.qzone.qq.com/cgi-bin/cgi_pasture_ini_run?v=21","pasture_friend_list_mod":1000,"pasture_friend_list":"1001-1002","pasture_friend_list_tips":"系统繁忙,请稍后再试!","pasture_steal_mod":1000,"pasture_steal":"1001-1002","pasture_steal_tips":"为保证更加稳定的服务,系统正在进行分号段数据维护。在此时间段系统将暂停 “收取”操作以保护您的数据安全。感谢您的理解与支持!","pasture_enter_mod":1000,"pasture_enter":"1001-1002","pasture_enter_tips":"为保证更加稳定的服务,系统正在进行分号段数据维护。在此时间段系统将暂时关闭牧场以保护您的数据安全。感谢您的理解与支持!","pasture_recover":"http://mc.qzone.qq.com/cgi-bin/cgi_recover","pasture_user_mode":1000,"pasture_user":"1001-1002","pasture_animal_mode":1000,"pasture_animal":"1001-1002","pasture_item_mode":1000,"pasture_item":"1001-1002","loading":"http://appimg.qq.com/happyfarm/module/loading_v_8.swf"};
  for( var k in others )
  {
  flashvars[k] = others[k];
  }
   
  var flashDir = "http://appimg.qq.com/happyfarm/";
  var mainSwfUrl = "http://appimg.qq.com/happyfarm/happyfarm_v_1.swf?v=1016";
   
  function domainReplace(url,prefix){ //域名前添加edu前缀
  return url.replace(/\/\/([\w+\.]+[\w])\//g,function($0,$1){
  return '//'+prefix+'.'+$1+'/';
  })
  }
  if(QZONE.FP._t.imgcacheDomain.indexOf('edu')==0){
  if(curModule=='nc'){
  flashDir = domainReplace(flashDir,'edu');
  mainSwfUrl = domainReplace(mainSwfUrl,'edu');
  }
  }
  var attributes = {
  "MredirectURL" : "http://rc.qzone.qq.com/app?url=http%3A%2F%2Ffarm.qzone.qq.com/cgi-bin/cgi_farm_canvasindex_run"
  };
   
  var wmodeValue,_alpha;
  _alpha = QZONE.FP._t.QZONE.alpha;
  if(_alpha &amp;&amp; _alpha.getAlphaStatus){
  wmodeValue = _alpha.getAlphaStatus() ? 'window' : 'opaque';
  }else{
  wmodeValue = 'opaque';
  }
  var params = {
  base : flashDir,
  allowScriptAccess : "always",
  wmode : wmodeValue
  };
  if($(["myContent", module].join("")).tagName.toLowerCase() == 'div'){
  swfobject.embedSWF(
  mainSwfUrl,
  ["myContent", module].join(""),
  "100%",
  "560",
  "9.0.124",
  [flashDir, "/images/expressInstall.swf"].join(""),
  flashvars,
  params,
  attributes,
  function(e)
  {
  if (!e.success)
  {
  $("myContentnc").innerHTML = '&lt;div style="padding:20px"&gt;&lt;h1&gt;请下载最新的Flash插件&lt;/h1&gt;&lt;p&gt;&lt;a href="http://www.adobe.com/go/getflashplayer" target="_blank"&gt;&lt;img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="下载最新的Flash插件" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;'
  }
  }
  );
  }
   
  //if(mainContainer){
  var moduleNc = $("myContentnc"),
  moduleMc = $("myContentmc");
   
  if(module == 'nc'){
  moduleNc.style.height = "560px";
  moduleMc.style.height = "0px";
  if(!ua.ie){
  moduleMc.style.marginTop = "-14px";
  }
  } else {
  moduleNc.style.height = "0px";
  moduleMc.style.height = "560px";
  if(!ua.ie){
  moduleMc.style.marginTop = "-14px";
  }
  }
  //}
  }

可以看到,javascript为flash提供了可观的外部数据储备,在这些数据中,能够看到一些非常有用的API地址可以用来直接拉取游戏信息。

Flash地址暴露出来:http://appimg.qq.com/happyfarm/happyfarm_v_1.swf?v=1016

同时,可以预先大胆猜测下面的这些API方法

获取好友列表:http://nc.qzone.qq.com/cgi-bin/cgi_farm_getFriendList

获取用户包裹:http://farm.qzone.qq.com/cgi-bin/cgi_farm_getpackage

扩建(开垦)新的土地:http://farm.qzone.qq.com/cgi-bin/cgi_farm_reclaim

剩下的“资源”以后再利用吧。

值得注意的是,所有以上API的形式都是类似于Python中的字典类型的,包括这些API调用返回的结果也是基于字典的(算是我个人的倾向理解,其实它被称为JSON格式,后面我也发现了其实单一使用python的字典无法完全解析这种格式,至少那是不方便的。但python有关于json的模块)。这给了我们使用Python的充分理由,为什么不呢。

首先,试着获取好友列表:http://nc.qzone.qq.com/cgi-bin/cgi_farm_getFriendList

import urllib2,codecs
flist=urllib2.urlopen(‘http://nc.qzone.qq.com/cgi-bin/cgi_farm_getFriendList’)
print flist.read()

我们得到的结果是:

{"errorContent":"请重新登录","errorType":"session"}

因此我们需要首先登录获取一个cookie,并在之后的操作中都包含这个cookie。我们使用i.qq.com这个页面包含的登录页面来尝试。
http://i.qq.com中包含一个iframe,内嵌框架的地址是:http://ui.ptlogin2.qq.com/cgi-bin/login?link_target=blank&appid=15000101&hide_title_bar=0&no_verifyimg=0&s_url=http://imgcache.qq.com/qzone/v5/loginsucc.html%3fpara%3dizone&f_url=loginerroralert&target=top&qlogin_jumpname=jump&qlogin_param=u1%3Dhttp://qzone.qq.com/new.html&ptcss=0

其中no_verifyimg的控制其实没有起到很大的用处。

我已经将上面一长串的地址缩成短地址http://2url.org?grabqq

于是,提取登陆表单内容的代码如下:

import urllib2
url=’http://2url.org/?grabqq’
result=urllib2.urlopen(url,None,5)
content=result.read()
print content[content.find('<form'):content.find('</form>')+7]

得到的结果是

<form id=”loginform” autocomplete=”off” name=”loginform” action=”http://ptlogin2.qq.com/login” method=”post” onsubmit=”if(!isAbleSubmit){return false;};return ptui_onLoginEx(loginform, ‘qq.com’)” onreset=”return onFormReset(loginform)” target=”_self” style=”margin:0px;”>
  <ul>
    <li><span><u id=”label_uin”></u></span>
    <input type=”text” id=”u” name=”u” value=”" style=”ime-mode:disabled” tabindex=”1″ onfocus=”ptui_onUserFocus(‘u’, ‘#000000′)” onblur=”ptui_onUserBlue(‘u’, ‘#CCCCCC’);check();” />
        <label><a target=”_blank” href=”http://id.qq.com?from=pt” tabindex=”7″ id=”label_newreg”></a></label></li>
    <li><span><u id=”label_pwd”></u></span>
      <input type=”password”  id=”p” name=”p” value=”" maxlength=”16″ tabindex=”2″ onfocus=”check();” />
      <label><a target=”_blank” tabindex=”8″ href=”http://ptlogin2.qq.com/ptui_forgetpwd” onclick=”onClickForgetPwd()” id=”label_forget_pwd”></a></label></li>
    <li id=”verifyinput” style=”display:none;”><span for=”code”><u id=”label_vcode”></u></span>
    <input name=”verifycode” type=”text” style=”ime-mode:disabled” id=”verifycode” value=”" maxlength=”4″ tabindex=”3″/></li>
    <li id=”verifytip” style=”display:none;”><span>&nbsp;</span>
        <u id=”label_vcode_tip”></u></li>
    <li id=”verifyshow” style=”display:none;”><span for=”pic”>&nbsp;</span>

        <img id=imgVerify width=’130′ height=’53′ >
     <label><a id=”changeimg_link” tabindex=”6″ ></a></label>
    </li>

  </ul>
  <div>
 <input type=”submit” tabindex=”5″  disabled=”disabled” value=”"  id=”login_button” /></span>

</div>
<div id=”label_unable_tips”><a href=”javascript:onClickQLogin()” id=”label_switch_qlogin” style=”display:none;”></a><span id=”label_qlogin_tips” ><img src=”http://imgcache.qq.com/ptlogin/v3/style/0/images/load.gif” align=”absmiddle”> 正在检测能否快速登录.. </span></div>
<input type=”hidden” name=”aid” value=”15000101″ />
<input type=”hidden” name=”u1″ value=”http://imgcache.qq.com/qzone/v5/loginsucc.html?para=izone” />
<input type=”hidden” name=”fp” value=”loginerroralert” />
<input type=”hidden” name=”h” value=”1″ />
<input type=”hidden” name=”ptredirect” value=”1″ />
<input type=”hidden” name=”ptlang” value=”2052″ />

<input type=”hidden” name=”from_ui” value=”1″ />
<input type=”hidden” name=”dumy” value=”" />
</form>

然后我们需要按照顺序提取表单的提交地址和方法、表单内所有input area的id以及它们的name,这里是否需要验证码是个关键问题。因为id为verifyinput, verifytip和verifyshow的提示区和显示区域默认是不显示的,它们的style默认是display:none。

本文写到这里已经非常冗长了。作为启蒙阶段,就告一段落了。总结一下

  1. 需要进行网络验证,使用cookie来进行后续操作。python 2.6使用urllib2,python 3使用urllib.request来调用网页。
  2. 为了保证程序的通用和易维护,除了目前用来提取数据和登录的网页地址固定,其他的关键字均尽量从腾讯网页中提取。
  3. 在可能存在验证码的输入环境下,想尽量实现免人工干预的自动识别验证码输入。这可能会带来非常大的工作量。
  4. 参考了一下别人对农场数据的分析,除了目前腾讯网页上有的这些API出口,还有一些其他有用的接口。不排除这些接口地址获取自Flash内部。

下面的数据结构来自于数据地址:http://nc.qzone.qq.com/cgi-bin/cgi_farm_getFriendList (这个来自于网页数据)
http://nc.qzone.qq.com/cgi-bin/cgi_farm_getFriendList?mod=friend(这个来自于这里)其实两个没有实质性差异

exp: 用户经验值
headPic: 用户头像地址
money: 用户金钱
pf: 用户是否开启了保护模式
uId: 用户id
uin: 用户实例号码(即QQ号)
userName: 用户名(昵称)
yellowlevel: 黄色级别(黄钻等级)
yellowstatus: 黄色状态(是否开通了黄钻)

如果用户没有登录,那么会得到未登录的错误信息。

你也许会喜欢的日志

2人发表了评论  ↓发表评论↓
  • NB

    [回复]

    lx 回复:

    @星星, MNNB

    [回复]

    星星 @ 2010年05月11日

    回复

[ Ctrl+Enter提交 ]

3437471453591321281023251740504243322112038418334931126263041298715442436271424616193932548

Freelance PHP Developer