2018steam特賣星小遊戲的介面分析及掛機腳本

2018steam特賣星小遊戲的介面分析及掛機腳本

來自專欄 Python爬蟲實戰10 人贊了文章

steam夏季特賣活動進行了一半了,現在分享一些東西。

很簡單的介面分析,首先打開遊戲頁面(需翻牆),然後打開瀏覽器的開發者工具,刷新頁面,由於是單頁應用(SPA),所以只需要分析XMLHttpRequest和Fetch的連接就行

  1. gettoken 獲取令牌

首先是獲取令牌的介面,這個令牌在後面的其他介面中都要用,如果是已經登錄的用戶,直接在瀏覽器輸入這個url也可以直接獲得

url: steamcommunity.com/sali

method: GET

然後點擊開始進入遊戲,繼續分析

2. GetPlayerInfo 獲取用戶信息

url: community.steam-api.com

method: POST

data: access_token={token}

返回的信息包括等級和分數,

如果已經加入戰鬥的話,還會包括星球和戰區的信息

其中active_planet是星球的ID,而active_zone_games是遊戲ID,active_zone_position是戰區ID。如果存在這個些信息,說明正在交戰中,再次加入戰場會失敗,需要先退出戰場。

3. LeaveGame 離開遊戲

url: community.steam-api.com

method: POST

data: access_token={token}&gameid={gameid}

離開遊戲這個介面有兩個功能,一個是離開戰區,這個時候gameid就是用戶信息中的active_zone_games;如果是退出星球,gameid填active_planet

4. GetPlanets 獲取星球列表

url: community.steam-api.com

method: GET

這個介面返回的星球列表,其中searchQuery裡面active_only改成1的話,就只會返回當前已經激活的星球。

5.JoinPlanet 加入星球

url: community.steam-api.com

method: POST

data: id={id}&access_token={token}

在加入戰場之前必須選擇對應的星球,需要向伺服器提交的數據是令牌和星球的ID

6. GetPlanet 獲取星球信息

url: https://community.steam-api.com/ITerritoryControlMinigameService/GetPlanet/v0001/?id={id}&language=schinese

method: GET

這個介面用來獲取指定星球的詳細信息,主要是戰區的列表,請求的searchQuery關鍵字裡面id是星球的ID,在獲取星球列表的返回結果裡面可以得到。

7. JoinZone 加入戰區

url: community.steam-api.com

method: POST

data: zone_position={zone_position}&access_token={token}

需要向伺服器提交令牌和戰區的ID,如果加入戰場成功一定會返回戰區的信息。如果不成功可能是不提交的ID和之前加入的星球不匹配,這時候需要通過leaveGame這個介面退出當前星球,然後進入正確的星球,再重新加入戰區。也可能是已經加入過戰區,但還未到結束時間(120s一盤),這時候可以通過leaveGame這個介面退出戰區,然後重新進入。如果選擇的戰區已經被征服,也會導致失敗。

8. ReportScore 提交得分

url: community.steam-api.com

method: POST

data: access_token={score}&score={score}&language=schinese

遊戲過程中和伺服器沒有交互,只有在最後才會提交一下分數,也就是說完全可以看做一個單機的遊戲。所以這兒的得分是完全可以偽造的,不需要真的去玩。經過作者分析遊戲腳本發現,遊戲得分的公式如下:

最終得分=有效遊戲時間 * 單位時間得分 * 難度倍率

其中單位時間得分是5分/s

有效時間是總時間(120s)-基地修復時間,這個數據可以偽造,但是上限就是120s

難度倍率在腳本裡面沒有,是通過ajax動態載入過來的,先說結論:低難度是倍率為1,中等難度為2,高難度為4。

行了,到了這一步我們就可以通過寫一個掛機腳本來自動刷分了。

這些介面沒有被牆。

只需要模擬:選擇星球——加入星球——選擇戰區——加入戰區——等待120s——提交得分這個過程就OK了。

熟悉python的可以很快實現一個掛機腳本。

#!/usr/bin/env python# -*- coding: utf-8 -*- import requests,time,os,re,json,sysdef parse_response(res): return json.loads(res.text)["response"]class Robot(object): u===========================================================Steam 特賣星人小遊戲掛機程序使用說明:1. 登陸steam網站2. 進入頁面:https://steamcommunity.com/saliengame/gettoken3. 複製token=========================================================== def __init__(self): self.read_token() self.play() def read_token(self): if os.path.exists(token): self.token = open(token).read() else: print(self.__doc__) self.input_token() self.cache_token() def input_token(self): self.token = raw_input(unicode(請輸入令牌:,utf-8).encode(gbk)) if re.match(r^[0-9a-f]{32}$,self.token) == None: print(u不是合法的令牌,請重新輸入) self.input_token() def cache_token(self): open(token,w+).write(self.token) def play(self): try: self.get_user_info() self.get_planets() self.select_planet() self.get_zones() self.select_zone() self.combat() self.report_score() except Exception, e: print(e) finally: self.play() def get_user_info(self): print(u獲取玩家信息...) params = {"access_token":self.token} res = requests.post(https://community.steam-api.com/ITerritoryControlMinigameService/GetPlayerInfo/v0001/,data=params) self.userinfo = parse_response(res) def get_planets(self): print(u獲取星球列表...) res = requests.get(https://community.steam-api.com/ITerritoryControlMinigameService/GetPlanets/v0001/?active_only=0&language=schinese) self.planets = parse_response(res)["planets"] def select_planet(self): new_planet = filter(lambda planet:planet["state"]["active"],self.planets)[-1] if not "active_planet" in self.userinfo: self.join_planet(new_planet) return old_planet = filter(lambda planet:planet["id"] == self.userinfo["active_planet"],self.planets)[0] print(u當前位於%s % old_planet["state"]["name"]) if old_planet["id"] != new_planet["id"]: self.leave_planet(old_planet) self.join_planet(new_planet) return self.planet = new_planet def leave_planet(self,planet): print(u離開%s % planet["state"]["name"]) params = { "access_token":self.token, "gameid":planet["id"] } res = requests.post(https://community.steam-api.com/IMiniGameService/LeaveGame/v0001/,data=params) def join_planet(self,planet): print(u進入%s % planet["state"]["name"]) params = { "access_token":self.token, "id":planet["id"] } res = requests.post(https://community.steam-api.com/ITerritoryControlMinigameService/JoinPlanet/v0001/,data=params) self.planet = planet def get_zones(self): print(u獲取戰區列表...) params = { "id" : self.planet["id"], "language" : "schinese" } res = requests.get(https://community.steam-api.com/ITerritoryControlMinigameService/GetPlanet/v0001/,params=params) self.zones = parse_response(res)["planets"][0]["zones"] def select_zone(self): self.zones.sort(key=lambda zone:zone["difficulty"]) zone = filter(lambda zone:zone["capture_progress"]<0.9,self.zones)[-1] if "active_zone_game" in self.userinfo: gameid = self.userinfo["active_zone_game"] print(u當前位於%s戰區 % gameid) self.leave_zone(gameid) self.join_zone(zone) def join_zone(self,zone): print(u加入%s戰區 % zone["gameid"]) params = { "zone_position":zone["zone_position"], "access_token":self.token } res = requests.post(https://community.steam-api.com/ITerritoryControlMinigameService/JoinZone/v0001/,data=params) self.zone_info = parse_response(res)["zone_info"] def leave_zone(self,gameid): print(u離開%s戰區 % gameid) params = { "access_token":self.token, "gameid":gameid } requests.post(https://community.steam-api.com/IMiniGameService/LeaveGame/v0001/,data=params) def combat(self): for i in range(120,0,-1): sys.stdout.write(u正在交戰,剩餘%s秒.. % i) sys.stdout.flush() time.sleep(1) sys.stdout.write(
) def report_score(self): print(u戰鬥結束,提交遊戲得分...) score = 2**(self.zone_info["difficulty"]-1) * 600 params = { "access_token":self.token, "score": score, "language":"schinese" } res = requests.post(https://community.steam-api.com/ITerritoryControlMinigameService/ReportScore/v0001/,data=params) result = parse_response(res) if "new_score" in result: print(u本場得分:%s % score) print(u當前總分:%s % result["new_score"]) print(u當前等級:%s % result["new_level"]) print(u----------------------------)if __name__ == __main__: Robot()

這兒分享一個用nodeJS寫的掛機腳本

https://github.com/LZ0211/steam_saliengame_robot?

github.com


推薦閱讀:

卡達遊戲開發商承認在遊戲中輕鬆捏合增加銷量!|中東遊戲島群
誰需要《艾希》?
全國最大遊戲外掛團伙犯罪案告破 涉案金額5000餘萬
小狼成長記|建造家園day2
「中國的 3A 遊戲需要中國玩家的鼓勵和支持」—— E3 2018 獨家專訪系列之 添田武人

TAG:腳本 | 遊戲 | Steam |