To be honest, the individual has little interest in the game, but the Diablo series of Blizzard is very emotional, starting early last year to play Diablo3, intermittent, feeling the most troublesome is the choice of skills, each version update may have a better build, which is not a good thing for amateur players like me, Fortunately, the grand secret after the ladder, using the ranking of senior players in the top of the build is always right, so spent a little time to write this script.
The script only statistics the active skill, the passive skill and the legendary gem use situation, the theory statistics other like equipment and so on information is also as simple and feasible, but the Diablo equipment's generation mechanism makes the statistic this not much significance, the same equipment attribute may have the superiority and disadvantage, difficult to compare, And some equipment pit Dad's drop rate is not what you want to have.
On the digression, I have to say that Python is too good for writing such a relatively simple script, a word: quick.
#-*-Coding:utf-8-*-"" "Diablo3 ranked top 1000 player heroes using skills statistics python diablo.py help Python diablo.py [barbarian|crusader|demon-h Unter|monk ' |witch-doctor|wizard] uses the data of the Asian service by default, if needs the American service or the European service, changes ' _rank_page ' and ' _api ' variable address can be Copyright (c) 2015 Jinnlynn <
Eatfishlin@gmail.com> released under the terms of the MIT license. "" "from __future__ import unicode_literals, print_function, absolute_import import OS import sys import URLLIB2 import JS On import Re __version__ = ' 1.0.0 ' __author__ = ' Jinnlynn <eatfishlin@gmail.com> ' __license__ = ' The MIT license ' _ _copyright__ = ' Copyright 2015 Jinnlynn ' # ranking page _rank_page = ' http://tw.battle.net/d3/zh/rankings/' # API _api = ' http:// tw.battle.net/api/d3/' _api_profile = Os.path.join (_api, ' profile ') _api_data = Os.path.join (_api, ' data ') _hero_ Classes = {' barbarian ': ' Wild man ', ' Crusader ': ' Holy Army ', ' demon-hunter ': ' Hunter ', ' Monk ': ' Monk ', ' witch-doctor ': ' The Witch ', ' Wizard ': ' The Secret artist '} _retry = 5 _hero_class = ' _active_skills = {} _passive_skills = {} _unique_Gems = {} def _clear_output (msg= '): Sys.stdout.write (' \r{:30} '. Format (')) Sys.stdout.write (' \r{} '. Format (msg)) Sys.stdout.flush () def _process (stated, total): msg = ' Hero data analysis ... {}/{} '. Format (stated, total) _clear_output (msg) def _get (URLs, is_json=true): # print (' Get: ', url) retry = 5 if _r Etry < 1 else _retry while retry > 0:try:req = Urllib2.urlopen (Url.encode (' UTF8 '), timeout=10) r
Eturn Json.load (req) if Is_json else Req.read () except Keyboardinterrupt, e:raise e except Exception, E: Retry-= 1 # print (' Retry ', Retry, E) # Raise E def _api_url (*args, **kwargs): Slash = Kwargs.get (' SLA Sh ', False) args = [Unicode (ARG) for arg in args] url = os.path.join (*args). Rstrip ('/") return URL + '/' if slash El Se url def get_era (): req = Urllib2.urlopen (_rank_page) return Req.geturl (). Split ('/') [-2] def get_rank_page_url (E RA): Url_part = ' rift-' if _hero_class = ' demon-hunter ': Url_part += ' dh ' elif _hero_class = = ' Witch-doctor ': Url_part + ' WD ' Else:url_part + + _hero_class return Os.path.joi N (_rank_page, ' era ', ERA, Url_part) def fetch_rank_list (): tags = [] try: _clear_output (' Get current game era ... ') ERA =
Get_era () _clear_output (' Get current top 1000 players ... ') URL = get_rank_page_url (ERA) HTML = _get (URL, is_json=false) # re Parse LST = Re.findall (r "a Href=\" (. *) \ title=.*class=\ icon-profile link-first\ ">", Html.decod E (' UTF8 '), re. UNICODE) # BeautifulSoup Parse # import BS4 # soup = bs4. BeautifulSoup (HTML) # LST = Soup.select (' #ladders-table tbody tr. Battletag a ') [' href '] for item in Lst:try : Tags.append (Item.split ('/') [-2]) Except:pass except Exception, E:print (' Fetch rank list FA Il. {} '. Format (_rank_page)) Raise e return tags def get_hero (player_tag): url = _api_url (_api_profile, Player_ta
G, slash=true) data = _get (URL) hero_selected = None For hero in Data.get (' Heroes ', []): If hero[' class ']!= _hero_class:continue = last_updated [' Last-updated '] # Recently used heroes if hero_selected is None or last_updated < hero[' last-updated ']: hero_selected = Hero If not hero_selected:raise Exception (' {} hero missing. ')
Format (player_tag)) URL = _api_url (_api_profile, Player_tag, ' hero ', hero_selected[' id ')] return _get (URL) # active skill Rune
def stat_active_skill_rune (Skill_slug, Rune): Global _active_skills if not rune:return slug = rune.get (' slug ') If slug in _active_skills[skill_slug][' rune ']: _active_skills[skill_slug][' rune '][slug][' count '] + = 1 Else: _a ctive_skills[skill_slug][' Rune '][slug] = {' Count ': 1, ' name ': Rune.get (' name ')} # active Skill def stat_active _skill (Active): global _active_skills slug = active.get (' skill ', {}). Get (' Slug ') # d3 The data returned by the API may have empty data if not SL Ug:return if slug in _active_skills: _active_skills[slug][' Count'] + = 1 Else: _active_skills[slug] = {' Count ': 1, ' name ': Active.get (' skill '). Get (' name '), ' Rune ' : {}} stat_active_skill_rune (slug, Active.get (' Rune ')) # passive Skill def stat_passive_skill (passive): Global _passive_ Skills slug = passive.get (' skill ', {}). Get (' Slug ') # d3 The data returned by the API may have an empty data if not slug:return if slug in _pas Sive_skills: _passive_skills[slug][' count '] + + 1 else: _passive_skills[slug] = {' Count ': 1, ' name ': Passive.get (' skill '). Get (' name ')} def stat_unique_gem (items): Global _unique_gems def get_gem (tooltip): I F not tooltip:return none, none url = _api_url (_api_data, tooltip) data = _get (URL) gems = data.get (' ge
Ms ') if not gems:return none, none gem = Gems[0].get (' item ', {}] return Gem.get (' id '), gem.get (' name ') If not items:return lst = [Items.get (s, {}) for s in [' Leftfinger ', ' rightfinger ', ' neck ']] for ToolTip in [D . Get (' Tooltipparams ', NoNE) for D in LST]: id_, name = Get_gem (tooltip) If not id_: Continue if id_ in _unique_gems: _uniq ue_gems[id_][' count '] + + 1 else: _unique_gems[id_] = {' Count ': 1, ' name ': name} def St At (Hero): Global _active_skills, _passive_skills map (Stat_active_skill, hero.get (' skills ', {}). Get (' active ', [])) m AP (Stat_passive_skill, Hero.get (' skills ', {}). Get (' passive ', []) items = hero.get (' Items ', {}) Stat_unique_gem (items def output (hero_stated, hero_stat_failed): def sort (data, count=10): D = sorted (Data.items (), Key=lambda d:d[1] [' Count '], Reverse=true return D if Count <= 0 else D[0:count] _clear_output () # print (' = = ') # print (H Ero_stated, hero_stat_failed) # print (' = = ') # pprint (_active_skills) # print (' = = ') # Pprint (_passive_skill s) # print (' = = ') # pprint (_unique_gems) # Pprint (_active_skills.items ()) # print (' = = ') print (' \n=== RES ULT ===\n ') print (' Statistic English\ n ') print (' success: {} ' failed: {}\n '. Format (hero_stated, hero_stat_failed)) print (' rank of active skill use: ') for _, D in sort (_active _skills): runes = [] for _, R in Sort (D.get (' Rune ', {})): Runes.append (' {name}[{count}] '. Format (**r)) d. Update ({' Rune_rank ': ', '. Join (Runes)}) print (' {Name}[{count}]: {Rune_rank} '. Format (**d)) print () print (' Passive skill usage row Name: ') for _, D in sort (_passive_skills): Print (' {name}[{count}] '. Format (**d)) print () print (' Legendary gem use rank: ') fo
R _, D in sort (_unique_gems): Print (' {name}[{count}] '. Format (**d)) print () def prepare (): Global _hero_class
Def PRINT_HC (): Print (' supports only the following heroic types, default demon-hunter:\n ') for C, N in _hero_classes.items (): Print (C, ': ', N) If Len (sys.argv) = = 1: _hero_class = ' Demon-hunter ' elif len (sys.argv) > 2:sys.exit (' parameter error ') else:a
RG = sys.argv[1] if arg = = ' help ': PRINT_HC () print (' \ntips: Runtime can be terminated at any time by CTRL + C to get the results of the statistical data ') Sys.exit () Elif Arg not in _herO_CLASSES:PRINT_HC () Sys.exit () Else: _hero_class = arg def main (): Prepare () print (' Hero type to be parsed : ', _hero_classes[_hero_class]) hero_stated = 0 hero_stat_failed = 0 try:tags = fetch_rank_list () if not t
Ags:raise Exception (' Parse battle.net rank page fail. ') Except Exception, E:print (' Error, ', e) sys.exit () total = len (tags) for tag in Tags:try:hero = Get_hero (tag) if not hero:raise Exception (' No Hero Data ') stat (Hero) hero_stated + = 1 _PR Ocess (hero_stated, total) except keyboardinterrupt:break except Exception, E: # print (' Fail: ', tag,
E, Hero) hero_stat_failed + 1 output (hero_stated, hero_stat_failed) If __name__ = ' __main__ ': Main ()