竹磬网-邵珠庆の日记 生命只有一次,你可以用它来做些更多伟大的事情–Make the world a little better and easier


236月/150

数据论水浒:解析108名梁山好汉

发布在 邵珠庆

梁山一百单八将都是如何落草为寇的?他们都是什么”学历”?除了大碗喝酒大块吃肉,他们真的是替天行道吗?

落草的成了”好汉”,入仕的成了”奸佞”,这之间有一个什么样的衡量标准?

他们,为什么上梁山?

纵观梁山一百单八将,他们上山的原因,大致可以分为以下五种。

第一种:被自己人陷害–以卢俊义为代表。

这里的”自己人”是指一百单八将里的人,如杨志被晁盖、吴用等劫了生辰纲。虽然那时杨志还没走上革命道路,但是日后却在一起了,所以也算是被自己人陷害的。

这种人里,有卢俊义、秦明、李应、朱仝、杨志、徐宁、燕青、萧让、安道全、金大坚、杜兴、李云,共十二人,其中天罡有七人,地煞有五人。

需要说明的是燕青。燕青是跟随主人一起的,若主人不被陷害,他还会在卢俊义府上做他的高级白领。

第二种:被官府(或者与官府有勾结的人)陷害,被迫上山–以林冲为代表。

这些人里,有宋江、林冲、花荣、柴进、鲁智深、武松、戴宗、解珍、解宝、朱武、裴宣、欧鹏、陈达、杨春、宋清、施恩,共十六人,其中天罡九人,地煞七人。可以从一定层次上直接代表着官逼民反的人数。

说明一下,朱武、陈达、杨春是否有这么悲惨,不得而知,原著只交代了他们三人”累被官司逼迫,不得已上山落草”。那么我们就姑且认为他们是被官府逼的吧。宋清是宋江的弟弟,自然跟他哥一样。鲁智深倒不是因为杀了人而上山,他是因为救了林冲被官府通缉才落草的。

第三种:被俘上山,由于个人意志、信仰不坚定,甘愿为梁山效力–以关胜为代表。

这些人里,有关胜、呼延灼、董平、张清、索超、宣赞、郝思文、韩滔、彭玘、单廷珪、魏定国、凌振、扈三娘、龚旺、丁得孙、蔡福、蔡庆、郁保四,共十八人,其中天罡五人,地煞十三人。

有些人可能会对蔡福、蔡庆有异议。实际上在攻打大名府的时候,他俩已经被软禁了,和被俘又有何区别?值得注意的是,梁山军此时正在大名府烧杀抢掠,还是蔡福说了句”大官人可救一城百姓,休教残害”。等传下令时,”城中将及伤损一半”。从这话可以看出梁山军的一贯作风。可惜兄弟俩只有蔡庆活到了”解放后”(平了方腊)。

郁保四是作为人质和曾生一起上梁山谈判的,实际上也是俘虏的一种。

第四种:因杀人越货触犯了法律,为逃避法律制裁不得已而上山–以晁盖、吴用等人为代表。

晁盖、吴用、公孙胜等人在劫了生辰纲之后,是因为东窗事发,不得已才上山的。若不是白胜拿着分到的银子去赌博不小心露了馅儿,他们一时半会还是不会上山的。

这批人里,有吴用、公孙胜、刘唐、李逵、史进、穆弘、雷横、李俊、阮小二、张横、阮小五、张顺、阮小七、杨雄、石秀、黄信、孙立、燕顺、吕方、郭盛、王英、孔明、孔亮、童威、童猛、孟康、侯健、乐和、穆春、杜迁、薛永、朱富、李立、石勇、孙新、顾大嫂、白胜,共三十七人。其中,天罡十五人,地煞二十二人。

有一些革命同志,如李逵等,也不是主动要上山的。虽然说上山可以大碗喝酒大块吃肉大肆砍人,不过他那时还是一个小小的国家干部,还当着小牢子,虽然无赖,但还不至于把脑袋别在裤腰带上干造反工作。只有劫法场救了宋江、戴宗之后,他才真正犯下不赦之罪,只好上山了。

第五种:无明显上山理由。

比如向往梁山大碗喝酒痛快–这和当年很多青年参加红军的道理是一样的;还有一些人,原著中没有交代,一出场即是土匪。我以为,这一批人天生革命觉悟极高,为造反而生,以造反为乐。

这批人里,有邓飞、杨林、蒋敬、皇甫端、鲍旭、樊瑞、项充、李衮、马麟、郑天寿、陶宗旺、曹正、宋万、李忠、周通、汤隆、邹渊、邹润、朱贵、焦挺、张青、孙二娘、王定六、时迁、段景住,共二十五人。没有一个天罡,全是地煞。

梁山革命根据地的两个创始人杜迁、宋万为何不在一起?因为杜迁和王伦是受了”鸟气”来到梁山落草的,而宋万后来才到。所以杜迁是个人原因,而宋万没有交代,只好”革命觉悟高”了。

上述五种原因如果列成表的话,将会更直观:

一、各种革命类型的数量、百分比分布

数据论水浒

数据论水浒

二、各种革命类型,在天罡、地煞中的分布

水浒论水浒

根据上图,我们可以得出什么结论?

一、在总人数中,由于自身触犯法律,为了逃避大宋法律制裁而投奔梁山的人数最多。这些人,在天罡中占据主导地位,在地煞中也高据第二。

那么我们基本上可以认定,这些人,大部分都是无事生非、九处响锣十处有他的那种人。他们的活跃度很高,唯恐天下不乱,而个人能力又很强。这些人,占据了天罡数的42%。

这批人为何在天罡中有如此之多的票数?主要是劫生辰纲,产生了六个天罡,劫法场救宋江,又产生了五个天罡,所以,票数很多。

二、天罡星中,革命觉悟都很低,没有一个是主动上山的。在天罡星中,人群从高到低依次是:由于自身原因上山的、被官府陷害被迫上山的、被自己人陷害上山的,最后是被俘上山的。

由于革命意志不是很坚定,所以,梁山集团最后的被招安,也是不可避免的了。

三、地煞星的革命觉悟最高,很多人在梁山还没有发展壮大的情况下,已经有了自己的一片革命根据地。但也正是由于大伙的文化程度不高,光有热情没有能力是不够的,所以避免不了最后被梁山吞并的结局。同时大伙能力普遍不是很高,只好排到地煞星去了。低天罡星一等啊!

四、 被自己人陷害的一类中,天罡星的比例明显比地煞星要高。这是由于天罡星中的多是能厮杀的人,他们对正处于成长阶段的梁山集团来说是多多益善。

五、总体来看,真正”官逼民反”的,只占总数的15%。这在一定程度上证明了大家一直认为的”官逼民反”是成立的,但我们还应该看到,其中的绝大多数人,要么是无事生非之辈,要么是杀人越货之徒,再就是被俘的原大宋公务员,他们并非都是官逼民反。像王英之流,”原是车家出身。为因半路里见财起意,就势劫了客人。事发到官,越狱走了”,这是死活都和革命沾不上边的。

总结了这么多,实际上结论只有一条,在《水浒传》里,只有造反才是那些人最好的选择。如果不造反,大部分的革命同志只能死于非命,而造反是一项投入产出比小、风险大收益小的特殊工种,除了头几年有把脑袋别在裤腰带上的危险之外,之后还有两条路可以走:

A. 招安;

B. 自己打出一片天地,当了开国元勋。

施老爷子没把他们的造反写成功,估计也是知道哪怕就算是成功,最后也免不了来一个”杯酒释兵权”吧。这还算是文明的,要是学朱元璋同学最后大肆屠杀功臣,那就更完蛋了。

数据论水浒

附梁山一百单八将落草原因

1. 宋 江:利用职权,私放晁盖;与梁山勾结,被二奶阎婆惜发觉;不甘被敲诈,杀了二奶;事发后被捉拿归案,刺配江州;题反诗被黄文炳识破,判处死刑;后被梁山好汉救出,上山落草。

2. 卢俊义:因名头太大,被宋江看中欲赚之上山;遂被吴用诬造反,并怂恿其家人出首告发;获罪被判刺配沙门岛,李固和贾氏贿赂董超、薛霸欲在路上将其杀害,被燕青救出;奔赴梁山途中再次落入官兵之手,梁山好汉打破大名府将其救出,上山落草。

3. 吴 用:劫生辰纲事发,上山落草。

4. 公孙胜:劫生辰纲事发,上山落草。

5. 关 胜:被呼延灼设计引入埋伏圈,被俘,上山落草。

6. 林 冲:被高俅害得家破人亡,无家可归,经柴进介绍,上山落草。

7. 秦 明:被花荣用计生俘,灌醉后宋江派小卒假扮他攻打青州,害其一家老小被慕容知府杀害;最后无处可去,上山落草。

8. 呼延灼:攻打梁山泊被徐宁破了连环马,不得已去青州借兵,又被三山聚义好汉戏弄;后被宋江生俘,上山落草。

9. 花 荣:原为清风寨武知寨(副职),本与刘高文知寨(正职)有隙,为解救宋江,与刘高彻底决裂,又被黄信生俘;解送途中被清风山燕顺、王英、郑天寿救出;后生俘秦明,又通过秦明说服黄信,三人一同上山落草。

10. 柴 进:未上山之前,已与梁山有私交;后因殷天锡(高俅叔伯兄弟、高唐州知府高廉老婆的兄弟)强占其叔父柴皇城花园,与李逵一起前与高唐州看望;殷天锡作威作福,李逵怒从胆边生,杀了殷天锡并逃回梁山;柴进被控指使李逵打死殷天锡,被打入死囚牢,柴皇城家产被抄;李逵从梁山搬救兵救出柴进,柴进上山落草。

11. 李 应:三打祝家庄时被萧让、戴宗等假扮官人捉拿,押解途中被林冲等人”解救”上山;吴用派人将李家庄烧成白地,并取其家眷;后路被断,只得上山落草。

12. 朱 仝:未上山之前,与梁山已有往来;后因私放雷横,刺配沧州,每日陪小衙内玩耍,被吴用、雷横、李逵等用计杀了小衙内,不得已只好上山。

13. 鲁智深:因救林冲恶了高俅,被迫远走江湖;被张青、孙二娘麻翻,介绍投奔二龙山;原二龙山头领邓龙不接纳,与杨志、曹正设计占了二龙山宝珠寺,上山落草。

14. 武 松:因杀死潘金莲等被刺配孟州;替施恩做打手得罪了蒋门神,蒋门神买通张都监诬陷武松做贼,将其刺配恩州;路上张都监、蒋门神派人欲结果武松性命,反被武松大闹飞云浦,血溅鸳鸯楼;事发后,经孙二娘、张青介绍上二龙山落草。

15. 董 平:原为东平府兵马都监,因求婚一事与太守程万里不和;后被宋江用计生俘,为梁山所用;以其原有身份,赚开东平府城门,杀程太守抢其女,从此上山落草。

16. 张 清:原为东昌府猛将,打东昌府时被林冲赶下水,被三阮生俘,上山落草。

17. 杨 志:三代将门之后,因丢失花石纲逃往他处避难,后被赦;欲行贿高俅求官复原职,高俅(及下人)收了钱不办事;杨志穷困潦倒,草市卖刀不料误杀牛二,被刺配大名府;因与索超比武被梁中书赏识,做了管军提辖使;替梁中书押送生辰纲被劫,不得已与鲁智深一同用计夺了二龙山宝珠寺落草。

18. 徐 宁:本是随驾金枪班教师,懂得使钩镰枪;不幸被时迁盗了家传宝甲,后被其表弟汤隆等用计赚上山落草。

19. 索 超:宋江攻打大名府时被俘,上山落草。

20. 戴 宗:欲用假信救宋江,被黄文炳识破,同罪判处死刑;后被梁山好汉救出,上山落草。

21. 刘 唐:劫生辰纲事发,上山落草。

22. 李 逵:劫法场救宋江后,上山落草。

23. 史 进:本与少华山勾结,事发后杀死俩都头并李吉,不愿意落草而去投奔王进;寻王进不得结识鲁智深,因鲁智深拳打镇关西而离开渭州;后至延州、北京,盘缠用尽,与鲁智深一起火烧瓦罐寺后分手,投少华山落草。

24. 穆 弘:劫法场救宋江后,上山落草。

25. 雷 横:本与梁山勾结;因打了白玉乔,被知县姘头告了一状,戴枷示众;后因白秀英与其母亲厮打,用枷打死白秀英;被朱仝私放,上山落草。

26. 李 俊:劫法场救宋江后,上山落草。

27. 阮小二:劫生辰纲事发,上山落草。

28. 张 横:劫法场救宋江后,上山落草。

29. 阮小五:劫生辰纲事发,上山落草。

30. 张 顺:劫法场救宋江后,上山落草。

31. 阮小七:劫生辰纲事发,上山落草。

32. 杨 雄:杀了与和尚裴如海私通的老婆潘巧云,投奔梁山落草。

33. 石 秀:杀了与杨雄老婆潘巧云勾搭的头陀和报晓和尚,与杨雄一起杀了潘巧云,无处可去,投奔梁山落草。

34. 解 珍:因官府下令限期捉拿大虫,打死老虎后被毛太公诬陷入狱;毛太公勾结王正、包吉等欲结果其性命,得乐和等救出,杀了毛太公一家老小,投奔梁山落草。

35. 解 宝:同解珍。

36. 燕 青:被李固赶出家门,因救卢俊义杀了董超薛霸;投奔梁山途中,卢俊义被官兵劫走,遂上梁山搬救兵,救出卢俊义后一同上山落草。

37. 朱 武:”累被官司逼迫,不得已上山落草”。

38. 黄 信:为救宋江,打破清风寨,一同上山落草。

39. 孙 立:为劫狱救解氏兄弟,上山落草。

40. 宣 赞:被秦明生擒,上山落草。

41. 郝思文:被扈三娘生擒,上山落草。

42. 韩 滔:被刘唐、杜迁生擒,上山落草。

43. 彭 玘:被扈三娘生擒,上山落草。

44. 单廷珪:被关胜生擒,上山落草。

45. 魏定国:被围,向关胜投降,上山落草。

46. 萧 让:梁山欲救宋江,被戴宗赚上梁山落草。

47. 裴 宣:”为因朝廷除将一员贪滥知府到来,把他寻事,刺配沙门岛。”路过饮马川被救上山落草。

48. 欧 鹏: “因恶了本官,逃走在江湖上。”原著中未交代为何落草,出场即为黄门山头领。

49. 邓 飞:原著并未交代,开场即为饮马川头领。

50. 燕 顺:原是贩羊马客人出身,因为消折了本钱,占据清风山落草。

51. 杨 林:原本也是绿林中人,后遇公孙胜,被举荐上梁山。

52. 凌 振:攻打梁山时落水被生俘,上山落草。

53. 蒋 敬:原著未交代,只说:”原是落科举子出身。科举不弟,弃文就武。颇有谋略,精通书算,积万累千,纤毫不差。亦能刺枪使棒,布阵排兵。”

54. 吕 方:”因贩生药到山东,消折了本钱,不能够还乡”,占对影山落草,后上梁山。

55. 郭 盛:”因贩水银货卖,黄河里遭风翻了船,回乡不得”,占对影山落草,后上梁山。

56. 安道全:被张顺杀死姘头并题”杀人者安道全也”,被迫上山落草。

57. 皇甫端:被张清举荐,上山落草。

58. 王 英:”原是车家出身。为因半路里见财起意,就势劫了客人。事发到官,越狱走了”,上清风山落草。

59. 扈三娘:二打祝家时被林冲生擒上山,被宋太公认为义女,上山落草。

60. 鲍 旭:原著未交代,原为枯树山头领,被李逵说服上梁山落草。

61. 樊 瑞:原著未交代,原为芒砀山头领,后被项充、李衮说服,一同上梁山。

62. 孔 明:因与本村财主争执而杀其全家,逃上白虎山落草。

63. 孔 亮:同孔明。

64. 项 充:原著未交代,原为芒砀头领,后被俘虏,留在梁山。

65. 李 衮:同项充。

66. 金大坚:梁山欲救宋江,被戴宗赚上梁山落草。

67. 马 麟:原著未交代,只说”原是小番子闲汉出身,吹得双铁笛,使得好大滚刀,百十人近他不得”。

68. 童 威:劫法场救宋江后,上山落草。

69. 童 猛:劫法场救宋江后,上山落草。

70. 孟 康:”原因押送花石纲,要造大舡,嗔怪这提调官催并责罚他,把本官一时杀了,弃家逃走在江湖上。”

71. 候 健:提供捉拿黄文炳线索,为宋江出气,后一同上山落草。

72. 陈 达:”累被官司逼迫,不得已上山落草”。

73. 杨 春:也是”累被官司逼迫,不得已上山落草”。

74. 郑天寿:路过清风山时与王英斗五六十回合不分胜负,被燕顺请上山落草。

75. 陶宗旺:原著未交代,只说”庄家田户出身。惯使一把铁锹,有的是气力,亦能使枪轮刀”。

76. 宋 清:与宋太公一起被同取上山落草。

77. 乐 和:为劫狱救解氏兄弟,上山落草。

78. 龚 旺:梁山打东昌府时被林冲、花荣生俘,上山落草。

79. 丁得孙:梁山打东昌府时被燕青打中马蹄,被吕方、郭盛生擒,上山落草。

80. 穆 春:劫法场救宋江后,上山落草。

81. 曹 正:”为因本处一个财主,将五千贯钱教小人来此山东做客,不想折本,回乡不得”,后助鲁智深打破二龙山,一并上山落草。

82. 宋 万:原著未交代,开场即为梁山泊头领。

83. 杜 迁:”因鸟气合着杜迁来这里落草。”

84. 薛 永:劫法场救宋江后,上山落草。

85. 施 恩:”因武松杀了张都监一家人口,官司着落他家追捉凶身,以此连夜拿家逃走在江湖上。”后投二龙山入伙。

86. 李 忠:与鲁智深在渭州分手之后,经过桃花山,被周通劫道;杀退周通,被请上桃花山落草。

87. 周 通:原著未交代,出场即为桃花山原主人,后投梁山。

88. 汤 隆:流落江湖,遇李逵,跟随上山落草。

89. 杜 兴:”因一口气上打死了同伙的客人,吃官司监在蓟州府里。杨雄见他说起拳棒都省得,一力维持,救了他。”后在李应家落草,”每日拨万论千”,后随李应上山落草。

90. 邹 渊:开场即为登云山头领,与邓飞、杨林、石勇为旧识,后救解氏弟兄一起上梁山。

91. 邹 润:开场即为登云山头领。

92. 朱 贵:”因在江湖上做客,消折了本钱,就于梁山泊落草。”

93. 朱 富:与哥哥朱贵一起,为救李逵麻翻师傅李云,后劝说李云与他一起上山落草。

94. 蔡 福:宋江攻破大名府,因照顾卢俊义有功,被硬请上山落草。

95. 蔡 庆:宋江攻破大名府,因照顾卢俊义有功,被硬请上山落草。

96. 李 立:原开黑店,因闹江州救宋江而上山落草。

97. 李 云:因押解李逵,被朱富麻倒,无法交差,只好上山落草。

98. 焦 挺:”平生最无面目(不顾面子,不讲交情),到处投人不着”,被李逵劝上梁山落草。

99. 石 勇:”为因赌博上一拳打死了个人,逃走在柴大官人庄上。”送信给宋江,一同上山。

100. 孙 新:为劫狱救解氏兄弟,上山落草。

101. 顾大嫂:为劫狱救解氏兄弟,上山落草。

102. 张 青:原在孟州道上开黑店,后投奔二龙山落草。

103. 孙二娘:原在孟州道上开黑店,后投奔二龙山落草。

104. 王定六:随张顺在取安道全时一同上山落草。

105. 郁保四:原为曾头市人马,随曾生一同上梁山谈判,被说服落草。

106. 白 胜:劫生辰纲事发被捉拿,后被解救,上山落草。

107. 时 迁:”流落在此,则一地里做些飞檐走壁,跳篱骗马的勾当。曾在苏州府里吃官司,却得杨雄救了他。”听说石秀、杨雄欲上梁山,便一同跟去上山落草。

108. 段景住:以盗马为生,欲盗好马送给宋江作见面礼,因被劫了马而直接投奔梁山。

摘自《盗寇的潜规则:从数据看水浒》一书。

274月/150

社交APP的痛点及九大流派解析

发布在 邵珠庆

“陌生社交是不是没戏了?”

当然有戏。

今天社交APP最好的切点必在“半熟人群”,既不是彻底的熟人没悬念,也不是彻底的陌生人不靠谱,而是这样一群人,有可以迅速熟悉起来的契合点,有持续交往的路径,有暧昧的小心思和羞羞的盼头,有关系升温以致(你懂的)的可能。

而这一方向和今天市场的格局完全契合,一方面熟人社交已经被腾讯的手Q和微信双向锁死,所有试图模仿path、做熟人安全私密社交的APP都遭遇了困境;另一方面纯粹的陌生匿名社交大行其道,各种炒概念、夺眼球,热潮退去之后却始终无法形成有效的用户沉淀。唯独“半熟人群的陌生社交”这个领域,完全可能出现新的巨头。试想,半熟沉淀下来就是熟人,接下来可能颠覆的就是……

陌生社交产品必须着重于解决两大痛点:

1、社交主体差距过大,我和一个舞厅里天昏地暗觉得抽烟男人才帅气的女生,确实没什么好聊。

2、缺乏有价值的场景和话题,不知道该聊什么。

让平凡而善良的广大什么丝人群摆脱枯燥乏味的生活,得到现实中没有的社交体验,只要能稳定持续地解决这两大痛点,你就有可能在大战中脱颖而出。

破冰难的解决思路呢?在此,笔者梳理了今天已有的陌生社交产品,总结出九大流派,与诸君共享。

免责条款:

1、本人是产品菜狗,很多见解未必靠谱,欢迎拍砖,恕不回应。

2、文中会列举一些APP,但不夹私货、不予评论,没有任何广告或攻击恶意。

3、本文不讨论强弱关系问题,以下分类方法互有交叉,也就是说:一个产品可能同时使用几种方法。

4、描述部分只代表一般用户心理,与笔者无关,笔者是正经人。也不要以为笔者是社交高手,其实现实中菜狗很木讷内向,才会特别留心社交领域。

  一、位置流

基于LBS的破冰方案,陌生人通过地理位置彼此连接,实现信息传递,发生社交互动。

1、描述:还记得吗,一次次在陌生的城市、寂寞而空虚的夜晚,颤抖着手打开陌陌、微信附近的人,哇,好多高颜值异性哦,约吗?这是LBS社交最初的形态。

后来这个形态玩出了更多的花样。我在路上和你擦肩而过,APP里会有显示哦。每个地理位置都是广播台留言板,可以向周围扩散信息和照片哦。又或者如笔者策划过的“新大陆”项目一样,地图上的每一个位置都变成了领土,可以占领、攻防、寻宝。

2、举例:陌陌、微信附近的人、克鲁、在场

3、优点:充分运用了solomo的优势,符合“移动”特性;因为都在“附近”,转化为线下关系的“可能性”大大增加;充分满足了人们的窥探欲和好奇心,使人更兴奋、更有期待感和想象空间。

4、劣势:

遭遇一,周围最近的人在7公里,再远一点是152公里,天啊……

遭遇二,周围好多美女呀,勾搭勾搭勾搭……(一晚上过去了,没有人回音)

遭遇三,九宝山公墓,今天好冷啊墓地里空荡荡的,一看附近的人,哇全是美女!!!

基于LBS的方案最坑爹的一点是,对“冷启动”要求超高,必须基于很大的用户基数,或者至少在一定区域内形成较高的用户密度。否则,所有预期中的“神奇点”,随时随地偶遇也罢,随时随地呼叫人帮忙也罢,都将变成“用户期待与实际体验严重脱钩”。反过来说,只要用的人多了,你说什么故事都能形成现象、蔚然成风。

阿里“到位”那样的idea很多人都能想到,但最后只有阿里这种量级才玩得转啊。

这时候怎么办呢?砸钱狠推吗,创业公司烧得起吗?如果用户密度没上来,则产品体验根本不能有效兑现,反过来说,产品体验不高,用户又怎么可能增长——这不是死循环吗?所以这种项目,往往成熟的互联网公司更容易“玩得转”,你想解决这个问题,先找一个足记大片模式那样的引爆点,或者大姨吗这样的高频刚需,打迂回战术。

  二、匹配流

基于匹配逻辑的破冰方案,随机匹配陌生人,或者基于兴趣等数据匹配陌生人。

1、描述:来,让我们随机匹配一个陌生人吧,管他三七二一,聊先!来,一个漂流瓶过来了,有人摇一摇了。

你觉得不靠谱?那就让系统基于大数据分析吧,找一个这样的女生:和我兴趣吻合度90%,同城以内,喜欢的男星和我长相相似(唉,好像没有)。

2、举例:11点11分、比邻、抱抱、猜么

3、优点:社交简单易行,没有负担;漂流瓶类的push会带动活跃和粘性;基于兴趣的匹配如果像一点资讯那样靠谱,会非常赞。

4、劣势:完美的匹配往往建立在理想状态下:异性、高颜值、寂寞空虚冷,和我的兴趣充分切合。但是……现实很骨感。当大家用比邻一次次匹配到同性时,又或者一个宅男在深夜打开手Q的巧遇时,听见对面传来另一个宅男响亮的脏话时,这是怎样一种失落。而匹配要想做到精准,往往需要2个条件,一是你常常用、能沉淀下兴趣数据,二是用户基数还是得很大,不然100个男生15个女生,匹配都匹配不过来。

那么问题来了,对于创业公司来说,能做到这两点,你的产品和商业思路绝对非同一般……

  三、活动流

基于线下活动的破冰方案,通过发布活动、参与活动连接陌生人,并整合线下商户O2O。

1、描述:有美女发起了一次聚会哦,AA制。有妹纸要看电影哦,要求“你请客”。有投资人发起行业聚会哦,讨论一下陌生社交的话题。

2、举例:约你、会会、约饭、微聚

3、优点:符合社交习惯,易于接受;更易形成线下关系;容易与线下商户合作盈利。

4、劣势:坦白讲,这种APP是本人体验最少的,因为真的不大喜欢参加纯私人聚会,所以提出的问题都是想象出来的:对聚会的质量、安全性要求较高,否则极易影响体验;狼多肉少,一个妹纸想看电影50个男的排队报名;容易成为非法交易的温床,背负政策和法律风险。

  四、暧昧流

主打男女配对的破冰方案,呵呵你懂的。

1、描述:哇,好多女神啊。哇,照片好大胆啊,全都是事业线和大长腿。来来来我打赏,给我露多一点。

觉得粗俗,那也可以这样:妹纸都是女王,我是奴仆。妹纸都有愿望,我要英雄救美。妹纸想听一首歌,我来扯嗓子了,啧啧,不是原音!

2、举例:大叔帮帮忙、哎呀、女神来了、陪我

3、优点:需求明显而突出,性和恐惧永远是营销中最不可抵挡的两大力量;相貌平凡的女性体验在生活中少有的被簇拥搭讪感,虚荣心全面满足,部分女性还可以玩玩代购,或者卖卖其他的;宅男们满足皇帝选妃一般猎艳的乐趣,尽管几乎没有人搭理,但每个用了这个APP的异性都可默认为可约对象,使他们充满期待,得到一种YY的刺激。

4、劣势:

遭遇一:“呵呵,我在你手机上发现了一个奇怪的APP哦。”如果你是一个稍微正经的人,敢把这个APP放桌面上吗?

遭遇二:“这是什么软件,不行,让我看看,不准躲,快给我看看!!”如果你有了另一半,你还敢用这种APP吗?

遭遇三:“约不约啊。”“约啊,来1912坐坐。”“那不是酒吧街吗?”“对啊,吃点夜宵喝点酒点个公主嘛。”

毫无疑问,此类APP从产生开始就打上了有色的标签,而且永远都洗不白,这使它们用户增长虽快、天花板来的也非常快——稳定适用的人群极其有限。同时,容易成为酒托、饭托、非法交易的温床,甚至带来政策法律风险被网信办直接KO也有先例。

  五、游戏流

通过互动小游戏完成破冰,匿名用户先一起玩游戏,感觉好再结为好友。

1、描述:先一起玩个非诚勿扰吧?或者玩个真心话大冒险?要么你画我猜。先成为玩伴嘛,玩着玩着,就有了战火之中的“一份情”。

2、举例:碰碰、兜兜友、贝贝

3、优点:游戏确实是一个较为自然的交往途径,也可以在安全距离内展现双方才华,形成合作体验。

4、劣势:

和匹配一样,游戏流的玩法要想生效,必须建立在高密度的用户基础上,否则要么根本匹配不到玩伴,要么陪你玩的其实都不是人。

同时,玩游戏从来都需要承受一定的风险和压力,交互成本较直接聊天更高。这就要求你的游戏必须高体验,简单、有意思、利于交往,要不费了半天劲形不成一个有效社交,脸都丢地上了,妹纸也没搭理我,这样的游戏绝对玩不下去。要设计出一个大家都喜欢的社交小游戏,不容易。

  六、广场派

这是最传统的类型,通过论坛社区、聊天室、秀场、群组等“广场”,让大家展示自身价值,自然而然地社交互动,逐步由弱关系转为强关系。

1、描述:这是最经典的模式了。我不擅长搭话,但是我可以在女神所在的群、论坛、聊天室里,假装和大家一起讨论问题,然后有的没的和她搭一句,一边故作正经。熟了?赶紧加私聊!

2、举例:豆瓣、知乎、QQ群

3、优点:广场派是最经典的做法,其优点已经被长期验证,非常符合人们的社交特性和习惯,更容易找的志趣相投的人,满足虚荣心和归属感,也可以缓解一上来就私聊的紧张和尴尬。

4、劣势:

遭遇一,我是新人,这个群里谁都不认识,算了不说话。

遭遇二,前几天都在说话,自从这几个人讲话之后,我就不怎么想讲话了,我不讲话他们也不讲话了。

遭遇三,这里怎么都是垃圾信息、营销和谩骂也,罢了罢了我退。

遭遇四,我费了一天,想出这么经典的一句,就10个人赞,那个名人就一句屁话10万个赞,那个美女就发了张照。

这是每个人都遭遇的情况,广场玩法对运营的要求极高,稍有不慎就会缓缓滑入信息过载的深渊,出现“蒸发效应”之类的用户集体沉默和逃离;加剧了人们之间话语权的不平等,释放了语言暴力的恐怖;容易出现敏感词,触及政策和法律高压线。

  七、实名派

绝对的经过认证的实名,破冰往往围绕具体事务,利用人们身份和资源属性彼此对接,目的性强、各取所需。

1、描述:哎呀,这几家互联网公司的HR妹纸真漂亮,先加了,啧啧,我们聊工作,对接资源啊。最近要找这个院系交流下,先搜到他们的女神:“能让我们搭起两个学院友好交往的桥梁吗?”

2、举例:Facebook、脉脉

3、优点:基于真实身份,更接近工作学习的常态,交往更正当,目的更明确;可以披着正经的外衣一点点满足小心思;能产生更有利现实工作生活的收益;运营得当,则容易活跃用户的满足虚荣心和归属感。

4、劣势:

广场派的所有问题实名派都可能遭遇,好在都是实名,不负责任的言行相对可控。

认证成本高,容易形成用户门槛。

互动成本也高,氛围太正经,大家都是“有身份的人”,于是投鼠忌器,审慎聊天。

网络虚拟的优势荡然无存,身份利益的界限存在,甚至愈发明显。

  八、匿名派

通过放心大胆地绝对匿名来破冰,更符合互联网的本质特征。

1、描述:我靠,这些匿名状态太劲爆了,我的朋友圈里怎么有这样的人?或者,随时随地找人聊天啊,随便什么话题,无关注无压力,想聊就聊,不聊阅后即焚。啧啧,我可不是约炮哦。

2、举例:无秘、几度、yikyark

3、优点:以相对安全的形式充分满足了人们的窥私欲、宣泄欲。

4、劣势:

容易成为语言暴力和色情信息的温床。

零成本投入的社交、归属感往往也是零,人们的连接太偶然,没关注,没名头,社交关系也就飘忽不定,很难形成深度沉淀。结果一开始新鲜时还好,久了必定粘性下降、大幅流失。

  九、交互创新派

采用不同以往的交互设计,使匹配、信息流、即时通信都变得炫酷、极简、具有戏剧色彩。

1、描述:这个交互真的好帅啊,APP一打开就是相机哦,我们用图片和短视频对话哦,我的UI好萌好有品位格调!或者,这是国外最先进的tinder模式哦,你看我可以像古代的皇帝一样翻牌子哦,美女,右滑,又是美女,右滑,怎么还是美女……

2、举例:国内模仿snapchat、tinder的产品

3、优点:有可能更符合95后的审美,成为一种现象和潮流;由于交互格局与微信类迥然不同,腾讯系无法跟进,总不能把微信也做成那样子呀;非常吸引眼球,非常容易讲故事,借着国外已火的东风,通过伟大的“赛道理论”迅速拿到投资人的钱。

4、劣势:除了形式吸引眼球,这种模式并没有解决最根本的破冰问题。更可怕的是,炫酷的交互往往过于超前,或者根本不符合中国人的使用习惯,进而水土不服。在此专门讲一下仿tinder和仿snapchat交互。

最近这段时间,国外的tinder火了,国内很多APP都开始跟着学,一时间翻牌子横行。但是以本人尝试了至少15款有此交互设计的APP、翻牌子翻到手抽筋的结论,这种APP一般面对三大问题:

一是先期匹配率不高,常常翻了半天毫无结果,匹配上了也无回音,就难免让人怀疑是运营账号一堆。

二是适用人群有限。对于急躁贪婪的男性,是喜欢面前一次出现一个女生,掀起盖头,喜欢就留下,不喜欢下一个——还是,刷的一声,面前站了一排女生任君挑?做N次单选,和做一次多选,哪个耗费的精力多?

三是照片造假严重。在美图和营销号流行的时代,你怎么知道这一张张美女谁真谁假了,看久了都审美疲劳爱无能了吧——讲的是看眼缘,可谁都知道是假眼缘。

再来看拍照、短视频交互的应用,优点是非常符合读图时代的特征,视图互动的效率相较以往大幅提升,因为没有美图类的修饰,这种互动也更加真实。但缺点同样明显,在中国此类应用中最长出现的图片就是墙、地面或者天花板。

原因很简单。国人对拍照互动的需求和西方人完全不同,比起互动的真实性和高效率,他们更注重的是分享中的“面子安全”。中国人太要面子了,照片从来都是精心挑选、反复修饰才敢发出去,要是现在一不小心就会拍照发出去,或者一不小心就拍到自己的丑样子,又或者每次对话都得拍照,这实在是太可怕了,带给人们的社交压力实在过大。

这是给新一代的?别搞错了,中国的95后尽管思想更灵活开放,但也更敏感,对隐私和个人空间的关注也更加明显,面对现实冲突的孤独焦虑感也更加强烈了。

说到底,除非两个人已经熟到睡过一张床了,否则一般情况下,拍照都是审慎的行为,更多是为了分享自己的正面、提升逼格、满足虚荣心的,学snapchat的朋友应该想想它致胜的另一面。

当然,以上两种情况是有例外的,那就是你在炫目的模仿之外,更触及了用户的深层需求,以独特的玩法抓到了点,那就大不一样了。还是那句话,设计和情怀不能超过需求本身,否则就是本末倒置,耍流氓。

评估九大流派,关键看你产品的定位——针对的用户群和商业模式,进而分析需求结构、体验成本、线下转化难度、设计风格、运营依赖度等要素。

看到这里,你是否已经有了自己的选择、思路和策略了呢?陌生社交是盘大棋,人心永远是微妙难测的,你要有心理学家一般的耐心沟通、敏感度和同理心。有想法的话,就尽快设计MVP去验证吧,不然十年后你只能和孩子说,想当年我有个牛逼的想法,做出来就能颠覆腾讯。

社交网络永远是互联网产品设计中难度最高也最好玩的领域。创业聚会中,很多人听说你是做O2O、在线教育、金融之类的就两眼放光,一听你是做社交网络的,他们不是像看见外星人、就是像目光越过空气。然而必须指出的是,在可以预见的未来,几乎所有的商业领域都将被社交玩法渗透,很多吹得天花乱坠的商业模式,都必须通过广大用户的社交粘性来维持,所以不懂社交你就只有无底洞一般地烧钱致死一个选择,或许有投资人陪你吧。

创业从来都是九死一生,面对腾讯这样的巨头,社交领域的创业者更要有“向死而生”的心态,做最坏的打算,尽最大的努力。

261月/141

解析12306订票流程

发布在 邵珠庆

前言

每当春节临近时,因为网络的方便,访问12306购买火车票回家过年成了很多人的首选。但由于12306的种种不给力,给那些在官网刷票的人带来了很多的不便。从2011年未12306上线起,连续几年回家我都是靠网上购票,今年也不例外;我记得11年时我使用的是官网直接购票,到了12年则使用了新出的木鱼抢票助手,而今年我用了360与猎豹两款主流抢票浏览器,还发动了几位朋友一起帮忙,才买到了一张差强人意的票,现在感觉买票是越来越困难。而就在前几天媒体还曝出了商业黄牛使用假身份证生成器10分钟钞杀1000多张票的新闻,让人吃惊不已。于是就萌生了自己写一个抢票应用的念头,最开始设想的就是本地桌面应用,而非浏览器插件,个人觉得本地应用始终比浏览器插件敏捷,因为本地应用可以精确稳定的请求有用的链接,过滤图片和CSS等前台无用请求,可以节省网络消耗时间。于是我花了一段时间将12306的整体订票流程解析了一遍,其间还经历了一次12306的改版,幸好主体流程改动不是很大,终算有点收获。

粗略的将12306的流程划分为:登录、查询和订票三大模块,下面就这三大模块逐一说明:

1.登录

登录12306请求的URL是:https://kyfw.12306.cn/otn/login/init,可以使用Firbug抓取一下它的请求头,得到的response响应内容如下:

从中可以看到Set-Cookie信息,也就是说,如果想要登录就必须先请求https://kyfw.12306.cn/otn/login/init这个链接,以获取服务端设置的Cookie信息,而有了该Cookie信息就可以将其保存,以备下步的请求使用。

再来分析一下它的页面HTML与其对应处理登录的Javascript脚本文件(https://kyfw.12306.cn/otn/resources/merged/login_js.js),得到如下流程:

1.用户点击登录提交时先要验证请求一下:https://kyfw.12306.cn/otn/login/loginAysnSuggest链接,用于判断当前网络环境是否可以登录,得到JSON数据(通过Firebug抓包):

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. {  
  2.     "validateMessagesShowId":"_validatorMessage"  
  3.     "status":true  
  4.     "httpstatus":200,  
  5.     "data":{  
  6.         "loginCheck":"Y"  
  7.     },  
  8.     "messages":[],  
  9.     "validateMessages":{}  
  10. }  

 

这里通过判断data.loginCheck是否为字符串Y判断用户是否可以登录,如不能登录,则显示messages中的内容.

2.当用户登录信息检查成功时,则POST请求https://kyfw.12306.cn/otn/login/userLogin,得到登录请求后的HTML,对应请求的参数为:

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. "loginUserDTO.user_name":  // 用户名  
  2. "userDTO.password":        // 密码  
  3. "randCode":                // 验证码  

注:登录图片验证码的获取地址可以从登录页面的HTML中得到为:https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand

 

3.通过解析获取的HTML可以根据id为login-txt的<span>标签来判断是否登录成功,登录成功的对应的HTML内容为:

 

[html] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. <span class="login-txt" style="color: #666666">  
  2.     <span>意见反馈:  
  3.          <a class="cursor colorA" href="mailto:12306yjfk@rails.com.cn">  
  4.              12306yjfk@rails.com.cn  
  5.          </a>您好,  
  6.     </span>  
  7.     <a id="login_user" href="/otn/index/initMy12306"   
  8.        class="colorA" style="margin-left:-0.5px;"><span>登录成功用户名</span></a>|  
  9.     <a id="regist_out" href="/otn/login/loginOut">退出</a>  
  10. </span>  

失败的内容为:

 

[html] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. <span class="login-txt" style="color: #666666">  
  2.     <span>意见反馈:  
  3.          <a class="cursor colorA" href="mailto:12306yjfk@rails.com.cn">  
  4.                12306yjfk@rails.com.cn  
  5.           </a>您好,请  
  6.     </span>  
  7.     <a id="login_user" href="/otn/login/init"  
  8.        class="colorA" style="margin-left:-0.5px;">登录</a> |  
  9.     <a id="regist_out" href="/otn/regist/init">注册</a>  
  10. </span>  

 

如上登录成功即可进行下一步的操作:对于车次的查询。

2,车次查询

新版车次预订的查询(这里单指单程票查询)大大减化了请求参数,只接收出发地编码,到达地编码,出发日期与旅客编码四个参数,所有的过滤操作都扔给了前台Javascript,这也说明了车次查询流程的简单,只需请求一个链接地址:

查询车次是通过GET:https://kyfw.12306.cn/otn/leftTicket/query链接获取的,对应的查询参数为(GET请求注意查询参数的顺序):

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. leftTicketDTO.train_date=2014-01-23  // 出发日期  
  2. leftTicketDTO.from_station=BJP       // 出发站编码  
  3. leftTicketDTO.to_station=SHH         // 到达站编码  
  4. purpose_codes=ADULT                  // 旅客编码:成人为ADULT,学生为:0X00  

 

对应的获取的JSON信息格式如下:

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. {"validateMessagesShowId": "_validatorMessage",  
  2.     "status": true,  
  3.     "httpstatus": 200,  
  4.     "data": [  
  5.         {"queryLeftNewDTO": {  
  6.                 "train_no": "240000G14104",          // 列车编号  
  7.                 "station_train_code": "G141",        // 车次  
  8.                 "start_station_telecode": "VNP",     // 始发站编码  
  9.                 "start_station_name": "北京南",      // 始发站名  
  10.                 "end_station_telecode": "AOH",       // 终到站编码  
  11.                 "end_station_name": "上海虹桥",      // 终到站名  
  12.                 "from_station_telecode": "VNP",      // 查询输入经过站编码  
  13.                 "from_station_name": "北京南",       // 查询输入经过站名  
  14.                 "to_station_telecode": "AOH",        // 查询输入到站编码  
  15.                 "to_station_name": "上海虹桥",       // 查询输入到站名  
  16.                 "start_time": "14:16",               // 出发时间  
  17.                 "arrive_time": "19:47",              // 到站时间  
  18.                 "day_difference": "0",               // 花费天数  
  19.                 "train_class_name": "",  
  20.                 "lishi": "05:31",                    // 历时  
  21.                 "canWebBuy": "Y",                    // 是否可以预定  
  22.                 "lishiValue": "331",  
  23.                 "yp_info": "O055300094M0933000999174800017",  
  24.                 "control_train_day": "20301231",  
  25.                 "start_train_date": "20140123",  
  26.                 "seat_feature": "O3M393",  
  27.                 "yp_ex": "O0M090",  
  28.                 "train_seat_feature": "3",  
  29.                 "seat_types": "OM9",  
  30.                 "location_code": "P3",  
  31.                 "from_station_no": "01",  
  32.                 "to_station_no": "09",  
  33.                 "control_day": 19,  
  34.                 "sale_time": "1400",                // 出票时间点hhmm  
  35.                 "is_support_card": "1",  
  36.                 "gg_num": "--",  
  37.                 "gr_num": "--",          // 高级软卧座剩余数  
  38.                 "qt_num": "--",          // 其他座剩余数  
  39.                 "rw_num": "--",          // 软卧座剩余数  
  40.                 "rz_num": "--",          // 软座座剩余数  
  41.                 "tz_num": "--",          // 特等座剩余数  
  42.                 "wz_num": "--",          // 无座座剩余数  
  43.                 "yb_num": "--",  
  44.                 "yw_num": "--",          // 硬卧座剩余数  
  45.                 "yz_num": "--",          // 硬座座剩余数  
  46.                 "ze_num": "有",          // 二等座剩余数  
  47.                 "zy_num": "有",          // 一等座剩余数  
  48.                 "swz_num": "17"          // 商务座剩余数  
  49.             },  
  50.             "secretStr": "预定请求令牌字符串",  
  51.             "buttonTextInfo": "预订或开售日期"  
  52.         },  
  53.         ..........                       // 省略其它车次,信息同上  
  54.     ],  
  55.     "messages": [],  
  56.     "validateMessages": {}  
  57. }  

注意这里的canWebBuy属性,用于标记该趟列车是否可以预订,还有对应列车的secretStr字符,它用于请求预订确认页面的令牌,

 

对于其中一直提到的列车站点编码,可以通过请求https://kyfw.12306.cn/otn/resources/js/framework/station_name.js链接,通过得到JS脚本中的station_names变量获取,对应的站点以@字符分隔,而每一个站点信息如下,这里以北京北为例:

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. bjb|北京北|VAP|beijingbei|bjb|0  

用于提取其中有用的信息是:北京北与VAP,使用查询北京北的编码就是VAP,其它站点的解析同理。

 

如上即可以查询指定出发地与到达地的车次预定信息,紧接着进行预订流程的分析。

3,车票预订

在12306的解析中,就属车票预订的解析最为费神,也是最核心的一个流程,我现在只掌握了成人单程票的预订流程,其他的比如返程,学生票等都还没有分析出来,如下讲解的就是关于成人单程票的预定基本流程:

3.1,获取预定确认页面

车票预定首先要请求获取车票的预订确认页面,如下流程图所示:


分析:该流程是在用户单击车次的“预订”按钮时触发的,如图所示,获取预订确认页面,先要判断用户是否登录,POST请求的地址是:https://kyfw.12306.cn/otn/login/checkUser,这个请求无参数,然后通过判断得到的JSON信息中的data.flag属性是否为true判断用户是否已登录,接着再根据对应列车查询时所获得的secretStr字符与用户输入的查询信息POST请求https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest,判断用户是否可以访问预定确认画面,通过得到JSON信息的status属性判断是否允许访问,如果为true说明可以访问,最后依据旅行类型为单程(dc)POST跳转获取单程车票的预订确认画面:https://kyfw.12306.cn/otn/confirmPassenger/initDc。如果登录用户不进行上述判断,直接POST请求https://kyfw.12306.cn/otn/confirmPassenger/initDc提示非法请求,只有成功获取预订确认页面后才能进行下一步的操作。

注:该流程可以查看对应JS脚本:https://kyfw.12306.cn/otn/resources/merged/queryLeftTicket_end_js.js,function L(b4, bX)方法获知。

从请求订单的确认画面还可以得到获取当前登录用户常用联系人的链接地址为:https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs

3.2,预订提交

在车票的预定提交之前必先要获取预定确认画面的原因是因为预订确认HTML中声明的orderRequestDTOticketInfoForPassengerForm两个Javascript变量,含有预订提交的时的必需参数信息,下面就预订提交给出粗略的流程分析图,如下:

注:图片可以右击后查看大图,该流程对应的JS文件地址为:https://kyfw.12306.cn/otn/resources/merged/passengerInfo_js.js

分析:如上图显示了车票预定提交的大体流程,可以依据请求的链接数将其分为四大块:

1.检查用户选择的乘客信息的合法性,POST请求:https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo,通过分析得到的JSON中的data.submitStatus属性是否为true判断,同时这一步的JSON信息中还会包含有一个data.isCheckOrderInfo属性将会作为下一步判断当前用户是否可排队请求的参数。对应请求参数有如下5个:

 

[javascript] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. cancel_flag: "2",                                         // 固定值  
  2. bed_level_order_num: "000000000000000000000000000000",    // 固定值  
  3. passengerTicketStr: getpassengerTickets(),                // 旅客信息字符串  
  4. oldPassengerStr: getOldPassengers(),                      // 旅客信息字符串  
  5. tour_flag: ticketInfoForPassengerForm.tour_flag,  // 从ticketInfoForPassengerForm中获取  
  6. randCode: $("#randCode").val()                            // 前台输入验证码  

这五个参数中,有两个参数需要注意passengerTicketStroldPassengersStr

passengerTicketStr是以下划线"_"分隔当每一个乘客信息组成的字符串,对应每个乘客信息字符串组成如下:

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. 座位编号,0,票类型,乘客名,证件类型,证件号,手机号码,保存常用联系人(Y或N)  

同样oldPassengersStr也是以下划线"_"分隔每个乘客信息组成的字符串,对应每个乘客信息字符串组成如下:

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. 乘客名,证件类型,证件号,乘客类型  

在上面的信息中座位编号指的是,一等座、二等座等的编码,从ticketInfoForPassengerForm.limitBuySeatTicketDTO.seat_type_codes属性中选择获取。

 

票类型指的是,成人票,学生票等的编码,可以从ticketInfoForPassengerForm.limitBuySeatTicketDTO.ticket_type_codes属性中选择获取。

证件类型指的是二代身份证,学生证,签证等的编码,可以从ticketInfoForPassengerForm.cardTypes属性中选择获取。

最后oldPassengersStr中的乘客类型主要有如下信息:

 

[javascript] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. adult: "1",  
  2. child: "2",  
  3. student: "3",  
  4. disability: "4"  

取上面对应的数字编码。

 

注意:在组合oldPassengersStr乘客信息字符串时,未尾会多一个下划线,提交请求是一定要补上,从上也可以看出所有的一些参数都是通过ticketInfoForPassengerForm变量获取的,这也是为什么要事先获取预定确认画面HTML的原因。

 

2.检查乘合信息合法后,接下来就会结合返回的data.isCheckOrderInfo属性,POST请求:https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue,判断当前乘客是否可以排队,对应的参数如下:

 

[javascript] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. train_date: new Date(orderRequestDTO.train_date.time).toString(),  // 列车日期  
  2. train_no: orderRequestDTO.train_no,                                // 列车号  
  3. stationTrainCode: orderRequestDTO.station_train_code,  
  4. seatType: limit_tickets[0].seat_type,                            // 座位类型  
  5. fromStationTelecode: orderRequestDTO.from_station_telecode,      // 发站编号  
  6. toStationTelecode: orderRequestDTO.to_station_telecode,          // 到站编号  
  7. leftTicket: ticketInfoForPassengerForm.queryLeftTicketRequestDTO.ypInfoDetail,  
  8. purpose_codes: n,         // 默认取ADULT,表成人,学生表示为:0X00  
  9. isCheckOrderInfo: m       // data.isCheckOrderInfo  

 

这里的参数要注意传递列车日期的方式,及座位类型编码,这里选择的是第一个乘客的座位类型编码。最后还要确保orderRequestDTO变量的准确性。

通过返回的JSON信息的data属性值来判断是否允许当前用户进行排队下单,并提示当前的剩余票数。

其中的data属性会包含有两个重要的参数,countTticket,(ticket的格式为:1*****30314*****00001*****00003*****0000的形式):

countT表示的是排队人数,而ticket指的是当前列车对应座位的剩余票数,可以通过https://kyfw.12306.cn/otn/resources/merged/passengerInfo_js.js文件中的function L(l, m) 函数解析获取:

 

[javascript] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. function L(l, m) {  
  2.             rt = "";  
  3.             seat_1 = -1;  
  4.             seat_2 = -1;  
  5.             i = 0;  
  6.             while (i < l.length) {  
  7.                 s = l.substr(i, 10);  
  8.                 c_seat = s.substr(0, 1);  
  9.                 if (c_seat == m) {  
  10.                     count = s.substr(6, 4);  
  11.                     while (count.length > 1 && count.substr(0, 1) == "0") {  
  12.                         count = count.substr(1, count.length)  
  13.                     }  
  14.                     count = parseInt(count);  
  15.                     if (count < 3000) {  
  16.                         seat_1 = count  
  17.                     } else {  
  18.                         seat_2 = (count - 3000)  
  19.                     }  
  20.                 }  
  21.                 i = i + 10  
  22.             }  
  23.             if (seat_1 > -1) {  
  24.                 rt += seat_1  
  25.             }  
  26.             if (seat_2 > -1) {  
  27.                 rt += "," + seat_2  
  28.             }  
  29.             return rt  
  30.         }  

函数中的l指的就是ticket,而m指的是第一位乘客所选择的座位编号。

 

如果计算的余票信息还有剩余,则会提示用户点击确认按进行订单的提交请求,如果没有充实的票,则会提示用户选择其它车次,处理该请求的方法详情见https://kyfw.12306.cn/otn/resources/merged/passengerInfo_js.js文件中的function M(n, m) 方法。

3.当提示的有充足的余票,且用户点击了确定按钮,则接下来会POST请求:https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue,进行单程票(dc)类型的排队下单操作,通过判断返回的JSON信息data.submitStatus属性判断订单是否以成功提交至服务器,对应的请求参数为:

 

[javascript] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. passengerTicketStr: getpassengerTickets(),  
  2. oldPassengerStr: getOldPassengers(),  
  3. randCode: $("#randCode").val(),  
  4. purpose_codes: ticketInfoForPassengerForm.purpose_codes,  
  5. key_check_isChange: ticketInfoForPassengerForm.key_check_isChange,  
  6. leftTicketStr: ticketInfoForPassengerForm.leftTicketStr,  
  7. train_location: ticketInfoForPassengerForm.train_location  

这里的参数没有新意,主要是注意获取ticketInfoForPassengerForm变量的准确性。

 

 

4.订单提交至服务器后不一定说明订单已经成功了,还需要GET请求:https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime,判断系统是否已根据提交的订单信息为相应的乘客占位成功,并提示预估出票等待时间,这一步只有一个参数,就是旅行类型,由于我们主要考虑的是单程票,故提交时POST dc就行了,如下:

 

[javascript] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. tourFlag: "dc"  

这一步占位的操作在12306的官网中是将其封装在了一个名为OrderQueueWaitTime的对象中,可以解压https://kyfw.12306.cn/otn/resources/merged/passengerInfo_js.js文件获知,对应的如果判断系统占位成功,将会从返的JSON信息中获取data.orderId属性,即为下单成功时的订单号。

 

如上4次请求就可以准确的模拟出12306官网订单提交的整套流程,其中其实还忽略了验证码的获取与判断操作,而这一步仅仅是判断验证码的合法性,与主体流程无关。对应订单确定页面的验证码获取链接为:https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp,从中与登录页面的验证码链接对比,可知新版12306的验证码管理统一为了一个方法,登录与订单确认的验证码链接只是传递的module和rand参数不一样而已。

4,结束语:

根据上面的操作,基本可以全程模拟官网的订单操作,编写出一个属于自己的抢票助手。在写这篇文章时,我一直在想这样做是否有意义,因为12306随时都有可能变更,由于23:00点~07:00点的维护时间段的设置,也许今天写出来的东西明天马上就会失效过期。但仔细考虑后还是打算将他分享出来,就当是一种学习吧。同时在这里公布GitHub上使用Python3编写的一个订票项目源码:https://github.com/lzqwebsoft/trainticket,对应window下独立运行exe文件下载地址为:https://code.google.com/p/lzqwebsoft-projects/source/browse/#svn%2Ftrunk,软件运行效果如下:

239月/130

PHP CodeIgniter框架源码解析

发布在 邵珠庆

1.index.php :入口文件
|-->define('ENVIRONMENT')  |主要用于设置errors日志输出级别
|-->$system_path |设置系统路径
|-->设置BASEPATH、FCPATH、SYSDIR、APPPATH等    |设置路径信息变量,为加载相应文件信息准备
|-->require_once BASEPATH.core/CodeIgniter.php | 最后加载CodeIgniter.php作为总控制器

2.CodeIgniter.php加载过程,主要用于加载core核心目录下相应文件

|-->require(BASEPATH.'core/Common.php');  |加载core目录下的Common文件,见2.1解析
|-->require(APPPATH.'config/'.ENVIRONMENT.'/constants.php'); |加载constants目录,与开发环境无关时直接使用config目录下的constants目录
|-->get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));   |设置子文件,扩展类的前缀
|-->$BM =& load_class('Benchmark', 'core');  |加载benchmark类,mark记录当前的时间
|-->$EXT =& load_class('Hooks', 'core');     |加载core目录下的Hooks钩子类
|-->$EXT->_call_hook('pre_system');  |调用_call_hook(pre_system),根据pre_system内部调用_run_hook执行钩子,在系统开始正式工作前作预处理
|-->$CFG =& load_class('Config', 'core');    |继续执行core下的Config配置文件,
|-->$CFG->_assign_to_config($assign_to_config); 
|-->|$this->set_item($key, $val);      |解析指定给config的配置文件,实质为对config[]赋值
|-->$UNI =& load_class('Utf8', 'core');      |加载了UTF-8编码类,CI_Utf8
|-->$URI =& load_class('URI', 'core');       |加载core目录的URI类,CI_URI
|-->$RTR =& load_class('Router', 'core');    |设置route路由及覆盖信息,见2.2解析
|-->_set_routing()
|-->_set_overrides()
|-->$OUT =& load_class('Output', 'core');    |实例化输出类,加载core目录下的output文件
|-->$OUT->_display_cache($CFG, $URI)         |判断是否存在页面缓存,是则输出文件
|-->$SEC =& load_class('Security', 'core');  |加载core目录下的安全处理文件
|-->$IN =& load_class('Input', 'core');      |实例化输入类,加载core目录下的input文件
|-->$LANG =& load_class('Lang', 'core');     |加载语言类
|-->require BASEPATH.'core/Controller.php';  |加载基本控制器类,见2.3解析
|-->require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';  |尝试加载扩展的自定义子类控制器
|-->include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');  |加载自定义控制器下的控制器类
|-->$BM->mark('loading_time:_base_classes_end'); |设定一个benchmark测试点
|-->$class  = $RTR->fetch_class();     |分别获取uri地址的控制器类名和方法名
|-->$method = $RTR->fetch_method();
|-->if ( ! class_exists($class)              |判断方法及类是否合理
OR strncmp($method, '_', 1) == 0
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
)
|-->$EXT->_call_hook('pre_controller');      |处理器执行前进行预处理,并做benchmark设置
|-->$CI = new $class();                      |获取执行的控制器实例,实例化构造器
|-->$EXT->_call_hook('post_controller_constructor');  |实例化控制器类后的钩子处理
|-->if (method_exists($CI, '_remap'))
|-->$CI->_remap($method, array_slice($URI->rsegments, 2))  |如果控制器存在_remap()方法,则执行, 判断条件$CI为控制器类 
|-->else |判断方法在类当中的存在似,如果不存在,则设置
|-->call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); |最终传递参数供调用控制类方法
|-->$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); |benchmark标记时间结束点
|-->$EXT->_call_hook('post_controller');     |控制器生存周期,在控制器执行完成后执行后续操作
|-->$OUT->_display();  |输出页面进行展示
|-->$EXT->_call_hook('post_system');         |请求生存周期完成后的终结操作
|-->$CI->db->close();                        |自动关闭数据库资源

2.1 Core/Common.php加载
|-->function is_php($version)                |用于比较版本号的函数
|-->function is_really_writable($file)       |用于判断是否可以写文件,在不同的系统中可靠程度不同,
      W中通过判断is_readonly,U中如果safe_mode为开则不确定性
|-->function load_class($class, $directory = 'libraries', $prefix = 'CI_')   |用于加载目录下的PHP文件的class类
|-->foreach (array(APPPATH, BASEPATH) as $path)    |分别在application和system目录下轮循
|-->file_exists($path.$directory.'/'.$class.'.php' |找到对应的PHP文件
|-->require($path.$directory.'/'.$class.'.php');   |require加载对应的PHP文件内的类,加了前缀,此处可扩展
|-->break;    |如正确加载则退出,否则继续尝试加载文件
|-->file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php')  |自扩展的class类,如My_Test
|-->if ($name === FALSE)   |如果$name不存在,则exit()退出 ,(在自定义类加载时,此处可作为扩展点,增加边际条件)
|-->is_loaded($class);     |确类已经加载
|-->$_classes[$class] = new $name();  |加载至静态的classes数祖中,用于缓存,调用时首先从classes中获取
|-->function is_loaded($class = '')                      
|-->设置$_is_loaded数祖,参数$class不为空,判断是否存在gf $_is_loaded,否则设置
|-->function &get_config($replace = array())|用于获取Config的实例化文件
|-->static $_config;       |定义config类型
|-->$file_path = APPPATH.'config/config.php';      |确定application目录路径下定义的config.php的路径
|-->require($file_path);   |加载application/config/config.php类
|-->count($replace) > 0    |对于config.php中定义的变量,如果有replace,则逐个替代
|-->foreach ($replace as $key => $val)
|-->$config[$key] = $val;
|-->return $_config[0] =& $config;   |最后返回定义的config的结果集
|-->function config_item($item)    |配置选项,从config的数祖对象中返还特殊的配置项
|-->$config =& get_config();
|-->$_config_item[$item] = $config[$item];
|-->function show_error            |用于错误信息输出
|-->$_error =& load_class('Exceptions', 'core');    |加载Exceptions类
|-->echo $_error->show_error($heading, $message, 'error_general', $status_code);  |直接输出错误
|-->function show_404              |用于输出404页面,输出的错误信息页面可配置
|-->function log_message           |用于写日志信息
|-->$_log =& load_class('Log');
|-->$_log->write_log($level, $message, $php_error);

|-->function set_status_header     |用于输出状态的heade信息
|-->function _exception_handler
|-->function remove_invisible_characters
|-->function html_escape           |过滤HTML变量
|-->return htmlspecialchars($var, ENT_QUOTES, config_item('charset'));

2.2Router路由信息设置
|-->_set_routing() 
|-->$segments = array()    |根据目录,控制器,函数的触发器设定segment[]的uri段值,分别fetch()方法去取对象值
|-->include(APPPATH.'config/routes.php');       |加载config下的routes文件
|-->$this->routes          |设置routes数祖值,从config的route中获取
|-->$this->default_controller       |设置routes的控制器值,从config的route中获取
|-->return $this->_validate_request($segments); |验证uri的segment合法性
|-->$this->uri->_remove_url_suffix();$this->uri->_reindex_segments();  |进一步清理解析uri,使segment从1开始x
|-->_set_overrides()  |根据$routing的值,重新设定directory、controller、function参数
|-->$this->set_directory($routing['directory']);
|-->$this->set_class($routing['controller']);
|-->$this->set_method($routing['function']);

2.3 core/Controller.php加载
|-->__construct()                                         |构造函数
|-->self::$instance =& $this;  
|-->foreach (is_loaded() as $var => $class)       |根据is_loaded()的信息加载相应的类
|-->$this->$var =& load_class($class);   
|-->$this->load =& load_class('Loader', 'core');  |加载core/Loader的php文件
|-->$this->load->initialize();                    |主要用于autoload加载信息,如libraries、database等等
|-->function &get_instance                                |返回当前实例
|-->return self::$instance

扩展点:PHP自动加载机制在CodeIgniter中的应用
1.PHP自动加载机制:PHP5后,提供了类的自动加载机制,即类在加载时才被使用,即Lazy loading,共有二种方式
1.1: __autoload()通过扩展可实现,实质为设定规则加载相应路径的PHP文件(require、include方式)
1.2: 将autoload_func指向php文件,这个一般用c语言扩展实现 
  详见:http://blog.csdn.net/flyingpig4/article/details/7286438

2.在CodeIgniter中的应用
根据上述源码分析可知:CodeIgniter中所有的操作都是以Controller为起始,只需在Cotroller加载的过程中,
使__autoload()函数自动加载即可,目前的加载方式为在application/config/config.php中设置__autoload()
函数

3110月/1130

电子商务网站数据分析指标、名词定义与解析

发布在 邵珠庆

网站分析采用指标可能有各种各样,根据网站目标和网站客户不同,可以有许多不同指标来衡量。常用网站分析指标有内容指标和商业指标,内容指标指是衡量访问者活动指标,商业指标是指衡量访问者活动转化为商业利润指标。

一、网站分析内容指标

转换率 Take Rates (Conversions Rates)

计算公式:转换率=进行了相应动作访问量/总访问量

指标意义:衡量网站内容对访问者吸引程度以及网站宣传效果

指标用法:当你在不同方测试新闻订阅、下载链接或注册会员,你可以使用不同链接名称、订阅方式、广告放置、付费搜索链接、付费广告(PPC)等等,看看那种方式是能够保持转换率在上升?如何增强来访者和网站内容相关性?如果这个值上升,说明相关性增强了,反之,则是减弱。

回访者比率 Repeat Visitor Share

计算公式:回访者比率=回访者数/独立访问者数

指标意义:衡量网站内容对访问者吸引程度和网站实用性(出自 业务员网:www.yewuyuan.com),你网站是否有令人感兴趣内容使访问者再次回到你网站。

指标用法:基于访问时长设定和产生报告时间段,这个指标可能会有很大不同。绝大多数网站都希望访问者回访,因此都希望这个值在不断提高,如果这个值 在下降,说明网站内容或产品质量没有加强。需要注意是,一旦你选定了一个时长和时间段,就要使用相同参数来产生你报告,否则就失去比较意义。

积极访问者比率 Heavy User Share

计算公式:积极用户比率=访问超过11页用户/总访问数

指标意义:衡量有多少访问者是对网站内容高度兴趣

指标用法:如果你网站针对正确目标受众并且网站使用方便,你可以看到这个指标应该是不断上升。如果你网站是内容型,你可以针对不同类别内容来区分不同积极访问者,当然你也可以定义20页以上才算是积极访问者。

忠实访问者比率 Committed Visitor Share

计算公式:访问时间在19分钟以上用户数/总用户数

指标意义:和上一个指标意义相同,只是使用停留时间取代浏览页数,取决于网站目标,你可以使用两个中一个或结合使用。

指标用法:访问者时长这个指标有很大争议,这个指标应结合其它指标一起使用,例如转换率,但总体来说,较长访问时长意味着用户喜欢呆在你网站,高忠实访问率当然是较好。同样,访问时长也可以根据不同需要自行设定。

忠实访问者指数 Committed Visitor Index

计算公式:忠实访问者指数=大于19分钟访问页数/大于19分钟访问者数

指标意义:指是每个长时间访问者平均访问页数,这是一个重要指标,它结合了页数和时间。

指标用法:如果这个指数较低,那意味着有较长访问时间但是较低访问页面(也许访问者正好离开吃饭去了)。通常都希望看到这个指数有较高值,如果你修改了网站,增加了网站功能和资料,吸引更多忠实访问者留在网站并浏览内容,这个指数就会上升。

忠实访问者量 Committed Visitor Volume

计算公式:忠实访问者量=大于19分钟访问页数/总访问页数

指标意义:长时间访问者所访问页面占所有访问页面数量

指标用法:对于一个靠广告驱动网站,这个指标尤其值注意,因为它代表了总体页面访问质量。如果你有10000访问页数却仅有1%忠实访问者率,这意味着你可能吸引了错误访问者,这些访问者没有啥价值,他们仅仅看一眼你网页就离开了。这是你应该考虑是否广告词语产生了误解。

访问者参与指数 Visitor Engagement Index

计算公式:访问者参与指数=总访问数/独立访问者数

指标意义:这个指标是每个访问者平均会话(session),代表着部分访问者多次访问趋势。

指标用法:与回访者比率不同,这个指标代表着回访者强烈度,如果有一个非常正确目标受众不断回访网站,这个指数将大大高于1;如果没有回访者,指数 将趋近于1,意味着每一个访问者都有一个新会话。这个指数高低取决于网站目标,大部分内容型和商业性网站都希望每个访问者在每周/每月有多个会话 (session);客户服务尤其是投诉之类页面或网站则希望这个指数尽可能接近于1。

回弹率(所有页面)Reject Rate/Bounce Rate

计算公式:回弹率(所有页面)=单页面访问数/总访问数

指标意义:代表着访问者看到仅有一页比率

指标意义:这个指标对于最高进入页面有很重要意义,因为流量就是从这些页面产生,当你对网站导航或布局设计进行调整时尤其要注意到这个参数。总而你是希望这个比率不断下降。

回弹率(首页)Reject Rate/Bounce Rate

计算公式:回弹率(首页)=仅仅访问首页访问数/所有从首页开始访问数

指标意义:这个指标代表所有从首页开始访问者中仅仅看了首页访问者比率

指标意义:这个指标是所有内容型指标中最重要一个,通常我们认为首页是最高进入页面(当然,如果你网站有其他更高进入页面,那么也应该把它加入到追 踪目标中)。对任意一个网站,我们可以想象,如果访问者对首页或最常见进入页面都是一掠而过,说明网站在某一方面有问题。如果针对目标市场是正确,说明是 访问者不能找到他想要东西,或者是网页设计上有问题(包括页面布局、网速、链接文字等等);如果网站设计是可行易用,网站内容可以很容易找到,那么问题可 能出在访问者质量上,即市场问题。

浏览用户比率 Scanning Visitor Share

计算公式:浏览用户比率=少于1分钟访问者数/总访问数

指标意义:这个指标一定程度上衡量网页吸引程度。

指标用法:大部分网站都希望访问者停留超过一分钟,如果这个指标值太高,那么就应该考虑一下网页内容是否过于简单,网站导航菜单是否需要改进。

浏览用户指数 Scanning Visitor Index

计算公式:浏览用户指数=少于1分钟访问页面数/少于1分钟访问者数

指标意义:一分钟内访问者平均访问页数

指标用法:这个指数也接近于1,说明访问者对网站越没兴趣,他们仅仅是瞄一眼就离开了。这也许是导航问题,如果你对导航系统进行了显著改进,应该可以看到这个指数在上升;如果指数还是下降,应该是网站目标市场及使用功能有问题,应该着手解决。

将浏览用户比率和浏览用户指数结合起来使用,可以看出用户是在浏览有用信息还是厌烦而离开。

浏览用户量 Scanning Visitor Volume

计算公式:浏览用户量=少于1分钟浏览页数/所有浏览页数

指标意义:在一分钟内完成访问页面数比率

指标用法:根据网站目标不同,这个指标高低有不同要求,大部分网站希望这个指标降低。如果是搞广告驱动网站,这个指标太高对于长期目标是不利,因为这意味着尽管你通过广告吸引了许多访问者,产生很高访问页数,但是访问者质量却是不高,所能带来收益也就会受到影响。

二、网站分析商业指标

平均订货额 Average Order Amount (AOA)

计算公式:平均订货额=总销售额/总订货数

指标意义:用来衡量网站销售状况好坏

指标用法:将网站访问者转化为买家当然是很重要,同样重要是激励买家在每次访问是购买更多产品。跟踪这个指标可以找到更好改进方法。

转化率 Conversion Rate (CR)

计算公式:转化率=总订货数/总访问量

指标意义:这是一个比较重要指标,衡量网站对每个访问者销售情况

指标用法:通过这个指标你可以看到即使一些微小变化都可能给网站收入带来巨大变化。如果你还能够区分出新、旧访问者所产生订单,那么就可以细化这个指标,对新旧客户进行分别统计。

每访问者销售额 Sales Per Visit (SPV)

计算公式:每访问者销售额=总销售额/总访问数

指标意义:这个指标也是用来衡量网站市场效率

指标用法:这个指标和转化率差不多,只是表现形式不同。

单笔订单成本 Cost per Order (CPO)

计算公式:单笔订单成本=总市场营销开支/总订货数

指标意义:衡量平均订货成本

指标用法:每笔订单营销成本对于网站盈利和现金流都是非常关键。营销成本计算各人有不同标准,有些把全年网站营运费用摊入到每月成本中,有些则不这么做,关键要看那种最适合自己情况。如果能够在不增加市场营销成本情况下提高转化率,这个指标就应该会下降。

再订货率 Repeat Order Rate (ROR)

计算公式:再订货率=现有客户订单数/总订单数

指标意义:用来衡量网站对客户吸引力

指标用法:这个指标高低和客户服务有很大关系,只有满意用户产品体验和服务才能提高这个指标。

单个访问者成本 Cost Per Visit (CPV)

计算公式:单个访问者成本=市场营销费用/总访问数

指标意义:用来衡量网站流量成本

指标用法:这个指标衡量是你市场效率,目标是要降低这个指标而提高SPV,为此要将无效市场营销费用削减,增加有效市场投入。

订单获取差额 Order Acquisition Gap (OAG)

计算公式:订单获取差额=单个访问者成本(CPV)-单笔订单成本(CPO)

指标意义:这是一个衡量市场效率指标,代表着网站所带来访问者和转化访问者之间差异

指标用法:指标值应是一个负值,这是一个测量从非访问者中获客户成本。有两种方法来降低这个差额,当你增强了网站销售能力,CPO就会下降,这个差 额就会缩小,说明网站转化现有流量能力到了加强;同样,CPV可能升高而CPO保持不变或降低,这个差额也会缩小,表明网站所吸引流量都具有较高转化率, 这种情形通常发生在启用了PPC(pay per click)计划。

订单获取率 Order Acquisition Ratio (OAR)

计算公式:订单获取率=单笔订单成本(CPO)/单个访问者成本(CPV)

指标意义:用另一种形式来体现市场效率

指标用法:用比率形式往往比较容易为管理阶层所理解,尤其是财务人员。

每笔产出 Contribution per Order (CON)

计算公式:每笔产出=(平均订货数X平均边际收益)-每笔订单成本

指标意义:每笔订单给你带来现金增加净值

指标用法:公司财务总监总是对这个指标感兴趣,代表了你花了多少钱来赚多少钱。

投资回报率 Return on Investment (ROI)

计算公式: 投资回报率=每笔产出(CON) /每笔订单成本 (CPO)

指标意义: 用来衡量你广告投资回报

指标用法:比较你广告回报率,应该把钱分配给有最高回报率广告,但是这个回报率应当要有时间段限制,比如“25% RIO/每周”和“25% RIO/每年”是有很大差别。

2410月/118

【Python】 如何解析json数据结构

发布在 邵珠庆

一、JSON的格式:

1,对象:

{name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"}

属性 :  , 属性 :  , 属性 :  }

 

2,数组是有顺序的值的集合。一个数组开始于"[",结束于"]",值之间用","分隔。

[

{name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"}, {name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"},

{name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"}

]

3, 值可以是字符串、数字、truefalsenull,也可以是对象或数组。这些结构都能嵌套。

 

4,json示例:

import json

# Converting Python to JSON

json_object = json.write( python_object )

# Converting JSON to Python

python_object = json.read( json_object )

 

5,simplejson 示例:

import simplejson

# Converting Python to JSON

json_object = simplejson.dumps( python_object )

# Converting JSON to Python

python_object = simplejson.loads( json_object )

 

二、pythonweb接口上查询信息

1,先看个例子

>>> import urllib

>>> url='http://a.bkeep.com/page/api/saInterface/searchServerInfo.htm?serviceTag=729HH2X'

>>> page=urllib.urlopen(url)

>>> data=page.read()

>>> print data           //这个就是json的数据结构,str类型

{"total":1,"data":[{"outGuaranteeTime":"","assetsNum":"B50070100007003","cabinet":"H05","deviceModel":"PowerEdge 1950","hostname":"hzshterm1.alibaba.com","logicSite":"中文站","memoryInfo":{"amount":4,"size":8192},"ip":"172.16.20.163","isOnline":true,"useState":"使用中","serviceTag":"729HH2X","cpuInfo":{"amount":2,"masterFrequency":1995,"model":"Intel(R) Xeon(R) CPU           E5405  @ 2.00GHz","coreNum":8,"l2CacheSize":6144},"cabinetPositionNum":"","buyTime":"2009-06-29","manageIp":"172.31.58.223","idc":"杭州德胜机房","responsibilityPerson":"张之诚"}],"errorMsg":"","isSuccess":true}

>>> type(data)

<type 'str'>

 

2,有了json数据结构,我却不知道怎么把它解析出来,幸亏有了李建辉的指导。大概思路是:

首先,json基本上是key/value的,python中就叫字典。既然是字典,那就应该安照读字典的方式去读。

将上面的data转为字典类型,这里用json模块的read方法。

 

>>> import json

>>> ddata=json.read(data)

>>> ddata

{'isSuccess': True, 'errorMsg': '', 'total': 1, 'data': [{'isOnline': True, 'idc': '\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf', 'assetsNum': 'B50070100007003', 'responsibilityPerson': '\xe5\xbc\xa0\xe4\xb9\x8b\xe8\xaf\x9a', 'deviceModel': 'PowerEdge 1950', 'serviceTag': '729HH2X', 'ip': '172.16.20.163', 'hostname': 'hzshterm1.alibaba.com', 'manageIp': '172.31.58.223', 'cabinet': 'H05', 'buyTime': '2009-06-29', 'useState': '\xe4\xbd\xbf\xe7\x94\xa8\xe4\xb8\xad', 'memoryInfo': {'amount': 4, 'size': 8192}, 'cpuInfo': {'coreNum': 8, 'l2CacheSize': 6144, 'amount': 2, 'model': 'Intel(R) Xeon(R) CPU           E5405  @ 2.00GHz', 'masterFrequency': 1995}, 'cabinetPositionNum': '', 'outGuaranteeTime': '', 'logicSite': '\xe4\xb8\xad\xe6\x96\x87\xe7\xab\x99'}]}

>>> 

看看ddata已经是dict类型了

>>> type(ddata)

<type 'dict'>

 

其次,我们以读字典中key ”data”对应的键值

>>> ddata['data']    //查看字典的方法!

[{'isOnline': True, 'idc': '\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf', 'assetsNum': 'B50070100007003', 'responsibilityPerson': '\xe5\xbc\xa0\xe4\xb9\x8b\xe8\xaf\x9a', 'deviceModel': 'PowerEdge 1950', 'serviceTag': '729HH2X', 'ip': '172.16.20.163', 'hostname': 'hzshterm1.alibaba.com', 'manageIp': '172.31.58.223', 'cabinet': 'H05', 'buyTime': '2009-06-29', 'useState': '\xe4\xbd\xbf\xe7\x94\xa8\xe4\xb8\xad', 'memoryInfo': {'amount': 4, 'size': 8192}, 'cpuInfo': {'coreNum': 8, 'l2CacheSize': 6144, 'amount': 2, 'model': 'Intel(R) Xeon(R) CPU           E5405  @ 2.00GHz', 'masterFrequency': 1995}, 'cabinetPositionNum': '', 'outGuaranteeTime': '', 'logicSite': '\xe4\xb8\xad\xe6\x96\x87\xe7\xab\x99'}]

 

>>>type(ddata[‘data’])

<type 'list'>

 

发现ddata[‘data’]是一个列表,列表就要用序号来查询

>>> ddata['data'][0]         //查看列表的方法!

{'isOnline': True, 'idc': '\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf', 'assetsNum': 'B50070100007003', 'responsibilityPerson': '\xe5\xbc\xa0\xe4\xb9\x8b\xe8\xaf\x9a', 'deviceModel': 'PowerEdge 1950', 'serviceTag': '729HH2X', 'ip': '172.16.20.163', 'hostname': 'hzshterm1.alibaba.com', 'manageIp': '172.31.58.223', 'cabinet': 'H05', 'buyTime': '2009-06-29', 'useState': '\xe4\xbd\xbf\xe7\x94\xa8\xe4\xb8\xad', 'memoryInfo': {'amount': 4, 'size': 8192}, 'cpuInfo': {'coreNum': 8, 'l2CacheSize': 6144, 'amount': 2, 'model': 'Intel(R) Xeon(R) CPU           E5405  @ 2.00GHz', 'masterFrequency': 1995}, 'cabinetPositionNum': '', 'outGuaranteeTime': '', 'logicSite': '\xe4\xb8\xad\xe6\x96\x87\xe7\xab\x99'}

>>> 

 

呵呵,ddata[‘data’]列表的0号元素是个字典。。

好,那我们查查keyidc的键值是多少

>>> ddata['data'][0]['idc']          //查看字典的方法!

'\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf'

>>> print ddata['data'][0]['idc']   //呵呵,为什么print搞出来的是汉字呢?

杭州德胜机房

 

看到这里终于明白怎么解析json数据结构了。。。

那就是一层一层往下剥

227月/118

网站运营实战经验解析

发布在 邵珠庆

 

 不知不觉自己从事网站运营已有几年了!因为一直都是自己创业,在期间随着自己的见解对网站运营做了不少尝试,形成自己一套独特理论和方法,也积累了不好的或者好的经验。今天趁美好心情记录下来,以便日后在经营管理以及策略运用上的借鉴!以我多年的网站运营经验给大家从网站策划、设计、编辑、优化和推广,营销分六大系列祥细解析,加上一些特殊绝招也献丑一下。

网站策划是整体流程开始之一。网站定位,域名的构思选择,俗话说得好域名选择得好就成功了一半了!不停完善对用户有帮助功能和栏目。制定可行性推广方案和销售方案。这两者可以决定网站的价值,所以要特别重视。一开始我们的网站选择域名和网名很不确实,改来改去至少改了三次域名和网名,导致搜索引擎收录反感。搜索引擎是机器人,可不像人一样灵活性;再有用户习惯突然又换,用户心中对网站大大打折扣。从中可见我们做网站之前策划工作很不到位!

设计在网站运营占位置也是很重要的。衡量一个网站好不好,内行人看综合,外行人只看设计,网站设计是给人第一印象。当时我们的网站是商业性的网站,主色是灰,头部是黄色。知识库做得比较简约,用户看文章舒服,我记得赢得不少用户喜欢和赞赏。

现在都说网站运营中内容为王,编辑对用户有帮助的数据。有数据才是硬道理,有了数据量才有流量。我们网站在统计系统试过,看到一篇文章从搜索引擎主关键词和散关键词进来加起来有1万多个IP,尝到意想不到的效果。虽然编辑工作比较轻松,简单复制和粘帖,这只是简单编辑人员。为了从搜索引擎免费带来IP,一般我们都原创的,自己常写一些用户喜欢的文章。自己写不过来时候,到网上找一些培训老师合作,让他们写的文章都发布到网站去。我们在网站上免费帮他们做个专栏,他们得到宣传,我们得到原创文章,有利于搜索引擎收录、提高排名和流量,这样子一来资源共享,对大家都有好处!

相信懂互联网的人都知道SEO优化。SEO是一种利用搜索引擎的搜索规则来提高网站在有关搜索引擎内的排名的方式,让自己的网站在搜索引擎排名靠前带来更多的自然流量。但做好SEO真的是很让人头疼的事情,其实把网站排名做上来需要的是时间、方法和技巧。技术方面得一定要注意遵守SEO的规则,如果不遵守的话,网站早晚会被搜索引擎给K掉,所以凡事都要招规矩办事。我们做优化一般站内部优化和站外部优化。内部优化主要做URL规划、关键词布局、代码精简、权重传递、内链建设、标题、关键词、描述等等,外部优化主要通过博客、论坛、栏目合作、分类信息等等渠道做锚文字外链。必须花大量的时间去做这些事情,特别是关键词定夺,严格根据用户对这类网站的搜索习惯,围绕网站的营销目的,两者结合的制定核心关键词。前期还做了网络调查,收集些用户对这类网站的需求和搜索方式,来定夺关键词。

网站做得再美若不推广,没有任何人浏览,网站就失去价值得了。网站推广任务重大,网站推广方法方式有很多,有收费和免费的!因为我们还是创业阶段没有太多资金投资,所以只采取常用免费网络推广方法,例如:搜索引擎推广,博客推广,邮件群发推广,QQ群,论坛社区发帖,攒写软文宣传等。

商务平台日IP上了3-5万IP后的赢利模式一般常见:一:收会员费,二:广告费。我们到达了这个数后,进行网络营销策略和网站使用分析。前期提倡战略是:广告投放,竞价排名,大客户合作。我们的商机是各行各业,广告投放可分首页和类别投放。竞价排名利用积分系统控制,积分越多商机信息就越靠前,积分不多又想商机排名靠前只有购买积分。大客户合作就是费用比较高,整站广告形式展示,暴光就越高。盈利模式我们以后将不断挖掘的!。

这几年技术朋友配合我,让我运营网站很轻松。他们技术扎实加上服务器安全性高,放心根据自己制定运营指标一步步完成。运营一个网站需要一个完美团队,都说:“没有完美的个人,只有完美的团队!”总结了不少自己的经验,当然,这些都只是很粗浅的一些观念与导引!相信网络公司也运用得上,其余领域也可一体适用。