├── 1.code-workspace ├── 1.ico ├── lib ├── IEDriverServer_x32.exe ├── chromedriver.exe └── geckodriver.exe ├── main.py ├── pip_list.txt ├── readme.md └── utils ├── ini.py ├── location_helper.py ├── my_print.py ├── nexus_cookies.py └── util.py /1.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RecluseXU/CheckStrackerLoader/41ec15263b348af7d73c70debdaec314d366c24f/1.ico -------------------------------------------------------------------------------- /lib/IEDriverServer_x32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RecluseXU/CheckStrackerLoader/41ec15263b348af7d73c70debdaec314d366c24f/lib/IEDriverServer_x32.exe -------------------------------------------------------------------------------- /lib/chromedriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RecluseXU/CheckStrackerLoader/41ec15263b348af7d73c70debdaec314d366c24f/lib/chromedriver.exe -------------------------------------------------------------------------------- /lib/geckodriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RecluseXU/CheckStrackerLoader/41ec15263b348af7d73c70debdaec314d366c24f/lib/geckodriver.exe -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | ''' 4 | @File : spider_Nexus_file 5 | @Time : 2020/02/23 18:14:01 6 | @Author : Recluse Xu 7 | @Version : 1.0 8 | @Contact : 444640050@qq.com 9 | @License : (C)Copyright 2017-2022, Recluse 10 | @Desc : None 11 | ''' 12 | 13 | # here put the import lib 14 | import requests 15 | from fake_useragent import UserAgent 16 | import datetime 17 | import time 18 | from lxml import etree 19 | import re 20 | from utils.util import Util 21 | from utils.ini import Conf_ini 22 | from utils.nexus_cookies import get_cookies_by_selenium_login, get_cookies_from_file, get_cookies_by_input, set_cookies_json_location, set_lib_location_location 23 | from utils.nexus_cookies import set_info_print_func as set_coo_my_print_func 24 | from utils.location_helper import Location 25 | from utils.location_helper import set_info_print_func as set_loc_my_print_func 26 | from utils.my_print import info_print 27 | import json 28 | 29 | 30 | my_session = requests.session() 31 | ua = UserAgent() 32 | headers = { 33 | "Connection": "keep-alive", 34 | "DNT": "1", 35 | "Host": "www.nexusmods.com", 36 | "Referer": "https://www.nexusmods.com", 37 | "TE": "Trailers", 38 | "Upgrade-Insecure-Requests": "1", 39 | 'User-Agent': ua.firefox, 40 | } 41 | locate = None 42 | 43 | 44 | def is_login(my_cookies): 45 | ''' 46 | @summary: 通过检验cookies,得知是否已经成功登录N网 47 | ''' 48 | global headers 49 | response = my_session.get( 50 | url="https://www.nexusmods.com/monsterhunterworld/mods/1982?tab=images", 51 | headers=headers, 52 | cookies=my_cookies 53 | ) 54 | file_page_html = response.content.decode() 55 | 56 | location = locate.get_resources_folder()+ 'is_login.html' 57 | with open(location, 'w', encoding='utf-8')as f: 58 | f.write(file_page_html) 59 | xpath_data = etree.HTML(file_page_html) 60 | a = xpath_data.xpath('//*[@id="login"]') 61 | if len(a) == 0: 62 | return True 63 | return False 64 | 65 | 66 | def get_cookies_info(user_name: str, user_pwd: str): 67 | ''' 68 | @summary: 获取cookies信息 69 | @return: cookies:dict 70 | ''' 71 | 72 | nexus_cookies_location = locate.get_cookies_txt_file() 73 | if Util.is_file_exists(nexus_cookies_location): 74 | info_print("110") 75 | info_print("111") 76 | my_cookies = get_cookies_from_file() 77 | # print(my_cookies) 78 | if is_login(my_cookies): 79 | info_print("112") 80 | return 81 | else: 82 | info_print("113") 83 | 84 | info_print("114") 85 | my_cookies = get_cookies_by_selenium_login(user_name, user_pwd) 86 | if my_cookies is not None: 87 | return my_cookies 88 | 89 | info_print("115") 90 | my_cookies = get_cookies_by_input() 91 | if is_login(my_cookies): 92 | info_print("116") 93 | else: 94 | info_print("117") 95 | Util.warning_and_exit(1) 96 | return my_cookies 97 | 98 | 99 | def spider_mod_file_page(): 100 | ''' 101 | @summary: 爬虫得到 MOD 的文件页 102 | @return: session 103 | ''' 104 | try: 105 | response = my_session.get( 106 | url="https://www.nexusmods.com/monsterhunterworld/mods/1982?tab=files", 107 | headers=headers) 108 | file_page_html = response.content.decode() 109 | # print(file_page_html) 110 | location = locate.get_resources_folder() + 'mod_file_page.html' 111 | with open(location, 'w', encoding='utf-8')as f: 112 | f.write(file_page_html) 113 | headers['Referer'] = "https://www.nexusmods.com/monsterhunterworld/mods/1982?tab=files" 114 | return file_page_html 115 | except Exception as e: 116 | print("失败", e) 117 | Util.warning_and_exit(1) 118 | 119 | 120 | def get_mod_file_page(is_safe_to_spide: bool): 121 | ''' 122 | @summary: 获取 Stracker\'s Loader 的文件页 123 | @return: 网页:str, 使用了爬虫:bool 124 | ''' 125 | if is_safe_to_spide: 126 | info_print('202') 127 | page_html = spider_mod_file_page() 128 | is_spider = True 129 | else: 130 | info_print('203') 131 | location = locate.get_resources_folder() + 'mod_file_page.html' 132 | with open(location, 'r')as f: 133 | page_html = f.read() 134 | is_spider = False 135 | info_print('204') 136 | return page_html, is_spider 137 | 138 | 139 | def analyze_mod_file_page(html: str): 140 | ''' 141 | @summary: 解析得到 MOD 的文件页,得到一些数据保存到配置中,并返回下载页数据 142 | @return: 最新版发布的时间, 最新版下载的URL 143 | ''' 144 | try: 145 | xpath_data = etree.HTML(html) 146 | a = xpath_data.xpath('//*[@id="file-container-main-files"]//div[@class="stat"]/text()') 147 | a = a[0].strip() 148 | last_publish_date = datetime.datetime.strptime(a, r"%d %b %Y, %I:%M%p") 149 | 150 | a = xpath_data.xpath('//*[@id="file-container-main-files"]')[0] 151 | last_download_url = a.xpath('..//a[@class="btn inline-flex"]/@href')[1] 152 | 153 | return last_publish_date, last_download_url 154 | except Exception as e: 155 | print("失败", e) 156 | Util.warning_and_exit(1) 157 | 158 | 159 | def spider_download_file_page(download_page_url): 160 | ''' 161 | @summary: 爬虫得到 MOD 的文件页 162 | @return: 下载页html:str 163 | ''' 164 | try: 165 | response = my_session.get(url=download_page_url, headers=headers) 166 | download_page_html = response.content.decode() 167 | 168 | location = locate.get_resources_folder() + "mod_download_page.html" 169 | with open(location, 'w', encoding='utf-8')as f: 170 | f.write(download_page_html) 171 | headers['Referer'] = download_page_url 172 | return download_page_html 173 | except Exception as e: 174 | print("失败", e) 175 | Util.warning_and_exit(1) 176 | 177 | 178 | def analyze_download_file_page(html: str): 179 | ''' 180 | @summary: 解析 MOD 的下载页 181 | @return: file_id, game_id 182 | ''' 183 | try: 184 | file_id = re.search(r"const file_id = \d+", html).group()[16:] 185 | game_id = re.search(r"const game_id = \d+", html).group()[16:] 186 | return file_id, game_id 187 | 188 | except Exception as e: 189 | print("失败", e) 190 | Util.warning_and_exit(1) 191 | 192 | 193 | def spider_download_file(file_id, game_id): 194 | ''' 195 | @summary: 根据留在页面上的ajax信息,向N网服务器提交请求得到下载链接 196 | @return: 下载用的url:str , 文件类型:str 197 | ''' 198 | data = { 199 | "fid": file_id, 200 | "game_id": game_id, 201 | } 202 | ajax_head = headers.copy() 203 | ajax_head['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8' 204 | ajax_head['Origin'] = 'https://www.nexusmods.com' 205 | try: 206 | url = "https://www.nexusmods.com/Core/Libs/Common/Managers/Downloads?GenerateDownloadUrl" 207 | response = my_session.post(url=url, headers=ajax_head, data=data, cookies=get_cookies_from_file()) 208 | download_url_str = response.content.decode("utf-8") 209 | download_url = json.loads(download_url_str)['url'] 210 | file_type = re.search(r'\.[a-z]+\?', download_url).group()[1:-1] 211 | 212 | location = locate.get_resources_folder() + "download_file_url.json" 213 | with open(location, 'w', encoding='utf-8')as f: 214 | f.write(file_type+"="+download_url) 215 | 216 | return download_url, file_type 217 | except Exception as e: 218 | print("失败", e) 219 | 220 | 221 | def downloadFile(url, location, dl_host): 222 | ''' 223 | @summary: 下载MOD文件 224 | ''' 225 | def formatFloat(num): 226 | return '{:.2f}'.format(num) 227 | 228 | download_head = headers.copy() 229 | download_head['Host'] = dl_host 230 | 231 | with open(location, 'wb')as f: 232 | count = 0 233 | count_tmp = 0 234 | time_1 = time.time() 235 | try: 236 | response = my_session.get(url, stream=True, headers=download_head, cookies=get_cookies_from_file()) 237 | content_length = float(response.headers['content-length']) 238 | for chunk in response.iter_content(chunk_size=1): 239 | if chunk: 240 | f.write(chunk) 241 | count += len(chunk) 242 | if time.time() - time_1 > 2: 243 | p = count / content_length * 100 244 | speed = (count - count_tmp) / 1024 /2 245 | count_tmp = count 246 | print("\t\t" + formatFloat(p) + '%' + ' Speed: ' + formatFloat(speed) + 'KB/S') 247 | time_1 = time.time() 248 | except Exception as e: 249 | print('失败', e) 250 | 251 | info_print('214') 252 | print("\t\t\t" + location) 253 | time.sleep(1) 254 | 255 | 256 | def first_time_run(): 257 | ''' 258 | @summary: 第一次运行的工作 259 | ''' 260 | info_print('100') 261 | info_print('101') 262 | location = locate.get_resources_folder()[:-1] 263 | Util.creat_a_folder(location) 264 | 265 | info_print('102') 266 | location = locate.get_lib_folder()[:-1] 267 | Util.creat_a_folder(location) 268 | 269 | info_print('103') 270 | info_print('104') 271 | info_print('105') 272 | N_name = input() 273 | info_print('106') 274 | N_pwd = input() 275 | Conf_ini.creat_new_conf_ini(locate.get_conf_file(), N_name, N_pwd) 276 | 277 | 278 | def is_first_time_run(): 279 | ''' 280 | @summary: 根据conf.ini文件是否存在,判断是否是第一次运行 281 | @return: bool 282 | ''' 283 | return not Util.is_file_exists(locate.get_run_folder()+'conf.ini') 284 | 285 | 286 | def to_install_VC(): 287 | ''' 288 | @summary: 询问安装VC 289 | ''' 290 | info_print('vc_0') 291 | info_print('vc_1') 292 | info_print('vc_2') 293 | info_print('vc_3') 294 | a = input('->') 295 | if a == "y": 296 | vc_x64_url = "https://download.visualstudio.microsoft.com/download/pr/3b070396-b7fb-4eee-aa8b-102a23c3e4f4/40EA2955391C9EAE3E35619C4C24B5AAF3D17AEAA6D09424EE9672AA9372AEED/VC_redist.x64.exe" 297 | vc_location = locate.get_resources_folder() + 'VCx64.exe' 298 | downloadFile(vc_x64_url, vc_location, "download.visualstudio.microsoft.com") 299 | Util.run_a_exe(vc_location) 300 | 301 | 302 | def init_locate(): 303 | ''' 304 | @summary: 初始化路径信息 305 | ''' 306 | global locate 307 | locate = Location() 308 | set_cookies_json_location(locate.get_resources_folder()+'Nexus_Cookies.txt') 309 | set_lib_location_location(locate.get_lib_folder()) 310 | 311 | 312 | def init_inject_func(): 313 | ''' 314 | @summary: 将一些函数分发到需要的地方 315 | ''' 316 | set_loc_my_print_func(info_print) 317 | set_coo_my_print_func(info_print) 318 | 319 | 320 | def run(): 321 | info_print('000') 322 | info_print('001') 323 | info_print('002') 324 | info_print('003') 325 | info_print('004') 326 | info_print('005') 327 | info_print('006') 328 | info_print('007') 329 | input('->') 330 | 331 | init_inject_func() 332 | init_locate() 333 | 334 | # 信息获取 335 | is_first_time = is_first_time_run() 336 | if is_first_time: 337 | first_time_run() 338 | 339 | info_print('107') 340 | info_print('108') 341 | conf_ini = Conf_ini(locate.get_run_folder()) 342 | 343 | info_print('109') 344 | username, userpwd = conf_ini.get_nexus_account_info() 345 | get_cookies_info(username, userpwd) 346 | 347 | info_print('200') 348 | info_print('201') 349 | file_page_html, is_spider = get_mod_file_page(conf_ini.is_safe_to_spide()) 350 | if is_spider: # 更新最后一次爬虫的时间信息 351 | conf_ini.set_new_last_spide_time() 352 | 353 | info_print('204_1') 354 | last_publish_date, last_download_url = analyze_mod_file_page(file_page_html) 355 | info_print('205') 356 | print("\t\t\t" + str(last_publish_date)) 357 | info_print('206') 358 | print("\t\t\t" + last_download_url) 359 | last_publish_timeStamp = Util.transform_datetime_to_timeStamp(last_publish_date) 360 | installed_version_timeStamp = conf_ini.get_installed_SL_upload_date() 361 | if last_publish_timeStamp == installed_version_timeStamp: 362 | info_print('207') 363 | Util.warning_and_exit() 364 | 365 | info_print('208') 366 | download_page_html = spider_download_file_page(last_download_url) 367 | info_print('209') 368 | file_id, game_id = analyze_download_file_page(download_page_html) 369 | print('\t\tgame_id\t'+game_id, 2) 370 | print('\t\tfile id\t'+file_id, 2) 371 | 372 | info_print('210') 373 | download_url, file_type = spider_download_file(file_id, game_id) 374 | info_print('211') 375 | print("\t\t\t" + download_url) 376 | info_print('212') 377 | print("\t\t\t" + file_type) 378 | 379 | info_print('213') 380 | dl_loader_location = locate.get_resources_folder() + 'StrackerLoader.' + file_type 381 | downloadFile(download_url, dl_loader_location, 'cf-files.nexusmods.com') 382 | # 英文化!!!!!!!! 383 | # 384 | info_print('215') 385 | if file_type == 'zip': 386 | Util.unzip_all(dl_loader_location, locate.get_dl_loader_folder(), '') 387 | else: 388 | info_print('216') 389 | print('\t\t' + file_type) 390 | info_print('217') 391 | Util.warning_and_exit(1) 392 | 393 | info_print('218') 394 | old_mod_file_list = conf_ini.get_mod_file_list() 395 | if len(old_mod_file_list) > 0: 396 | info_print('219') 397 | for _file in old_mod_file_list: 398 | print('\t\t\t'+_file) 399 | if Util.is_file_exists(locate.get_mhw_folder()+_file): 400 | Util.delete_file(locate.get_mhw_folder()+_file) 401 | else: 402 | info_print('220') 403 | 404 | info_print('221') 405 | sl_file_list = Util.get_file_list_in_folder(locate.get_dl_loader_folder()) 406 | info_print('222') 407 | print('\t\t\t' + str(sl_file_list)) 408 | 409 | info_print('223') 410 | for _file in sl_file_list: 411 | print('\t\t' + _file) 412 | Util.copy_file(locate.get_dl_loader_folder()+_file, locate.get_mhw_folder()+_file) 413 | 414 | info_print('224') 415 | info_print('225') 416 | conf_ini.set_installed_SL_upload_date(last_publish_date) 417 | info_print('226') 418 | conf_ini.set_mod_file_list(sl_file_list) 419 | 420 | locate.save_to_conf_ini_file() 421 | info_print('227') 422 | 423 | if is_first_time: 424 | to_install_VC() 425 | 426 | print('3DM biss') 427 | Util.warning_and_exit(0) 428 | 429 | 430 | # def init_webbrowser_driver(): 431 | # # chrome 尝试 432 | # import requests 433 | # from lxml import etree 434 | # url_base = "http://npm.taobao.org" 435 | 436 | # r = requests.get("http://npm.taobao.org/mirrors/chromedriver/") 437 | # html = r.content.decode() 438 | # xpath_data = etree.HTML(html) 439 | # a = xpath_data.xpath('///html/body/div[1]/pre/a')[2:] 440 | 441 | # download_page_url_list = list() 442 | # for i in a: 443 | # if i.xpath('./text()')[0].find("icon") != -1: 444 | # break 445 | # download_page_url_list.append(url_base + i.xpath('./@href')[0] + "chromedriver_win32.zip") 446 | 447 | # for i in download_page_url_list: 448 | # print(i) 449 | 450 | # Util.creat_a_folder(Util.get_lib_folder()+'chromedriver') 451 | # i = 0 452 | # Util.creat_a_folder(Util.get_lib_folder()+'chromedriver\\buffer') 453 | # for url in download_page_url_list: 454 | # location = Util.get_lib_folder()+'chromedriver\\buffer\\' + str(i) + '.zip' 455 | # t_headers = {g 456 | # 'Host': "cdn.npm.taobao.org", 457 | # 'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"} 458 | # response = requests.get(url, stream=True, headers=t_headers) 459 | # with open(location, 'wb')as f: 460 | # f.write(response.content) 461 | # i = i+1 462 | 463 | # unzip_location = Util.get_lib_folder()+'chromedriver\\' + str(i) + '.zip' 464 | # Util.unzip_all(location, unzip_location, '') 465 | 466 | 467 | if __name__ == "__main__": 468 | run() 469 | 470 | # init_locate() 471 | 472 | # conf_ini = Conf_ini(locate.get_run_folder()) 473 | # l = conf_ini.get_mod_file_list() 474 | # print(l) 475 | # conf_ini.set_mod_file_list(['123.json',"678.json"]) 476 | # l = conf_ini.get_mod_file_list() 477 | 478 | 479 | # print(l) 480 | # is_login(get_cookies_from_file()) 481 | # print() 482 | # init_webbrowser_driver() 483 | # spider_download_file(9908, 2531) 484 | 485 | # run_folder_location = Util.get_run_folder() 486 | # downloaded_mod_location = run_folder_location+'\\resources\\StrackerLoader.' + "zip" 487 | # downloaded_mod_unpack_location = run_folder_location+'\\resources\\StrackerLoade\\' 488 | # Util.unzip_all(downloaded_mod_location, downloaded_mod_unpack_location, '') 489 | # a = is_first_time_run() 490 | # print(a) 491 | # print('3DM Biss') 492 | # Util.get_file_list_in_folder("F:\\Workspace\\CheckStrackerLoader") 493 | 494 | 495 | 496 | # with open(r'F:\Workspace\CheckStrackerLoader\dist\resources\mod_file_page.html')as f: 497 | # html = f.read() 498 | # analyze_mod_file_page(html) -------------------------------------------------------------------------------- /pip_list.txt: -------------------------------------------------------------------------------- 1 | altgraph==0.17 2 | asn1crypto==1.3.0 3 | astroid==2.3.3 4 | autopep8==1.5 5 | browsercookie==0.7.6 6 | certifi==2019.11.28 7 | cffi==1.14.0 8 | chardet==3.0.4 9 | colorama==0.4.3 10 | configparser==3.7.4 11 | cryptography==2.8 12 | entrypoints==0.3 13 | fake-useragent==0.1.11 14 | flake8==3.7.9 15 | future==0.18.2 16 | idna==2.8 17 | isort==4.3.21 18 | keyring==21.1.0 19 | lazy-object-proxy==1.4.3 20 | lxml==4.5.0 21 | lz4==3.0.2 22 | macholib==1.11 23 | mccabe==0.6.1 24 | pefile==2019.4.18 25 | pycodestyle==2.5.0 26 | pycparser==2.19 27 | pycryptodome==3.8.2 28 | pyflakes==2.1.1 29 | PyInstaller==3.6 30 | pylint==2.4.4 31 | pyOpenSSL==19.1.0 32 | PySocks==1.7.1 33 | pywin32==227 34 | pywin32-ctypes==0.2.0 35 | rarfile==3.1 36 | requests==2.22.0 37 | selenium==3.141.0 38 | six==1.14.0 39 | urllib3==1.25.8 40 | win-inet-pton==1.1.0 41 | wincertstore==0.2 42 | wrapt==1.11.2 43 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 由于MHW已经停止更新,StrackerLoader也无需更新,所以此程序已经变得并没有什么意义 2 | 3 | ## 基本信息 4 | 由于卡表收紧了对MOD的接口,导致很多文件不再支持。 5 | 为了应对这种情况,国外有大佬利用逆向技术,制造了一个名为 StrackerLoader 的插件来重新开放这些接口。 6 | StrackerLoader:https://www.nexusmods.com/monsterhunterworld/mods/1982 7 | StrackerLoader这个插件在MHW更新的时候也需要跟着更新。 8 | 9 | 为了方便更新这个插件,我打算制作一个一键更新插件的程序,来优化这个过程。(尽管这个过程也不复杂) 10 | github地址:https://github.com/RecluseXU/CheckStrackerLoader 11 | 12 | 本程序不会用于盗号, 偷取信息 等非法操作 13 | 但由于源码是公开的, 可能存在被魔改成非法程序的可能 14 | 故建议从github或者N网获取本程序 15 | 16 | 17 | ## 这个程序做了什么 18 | 1. 检查你电脑的注册表,获知你MHW目录路径 19 | 2. 然后检查你是否装了 StrackerLoader ,记录一些有用的信息 20 | 3. 程序会通过 selenium ,使用账户和密码登录Nexus,获取cookies信息 21 | 4. 爬虫访问 Nexus 的 StrackerLoader 的 MOD 页,检查配对 StrackerLoader 这个MOD是否已经更新 22 | 如果更新了,程序会自动地下载最新版本的 StrackerLoader 并安装到MHW目录 23 | 没有更新,则给出提示后结束 24 | 25 | 程序对爬虫的间隔做了限制,仅仅允许用户以30s一次或更慢的频率来查询N网StrackerLoader这个MOD的信息。 26 | 对于少于这个间隔的运行,程序并不会执行爬虫,而是在上一次爬虫的结果中获取信息。 27 | 28 | 这个登录的过程大多数时候会在第一次使用本程序的时候发生,因为程序还没有获悉cookies。 29 | 当你成功登录后,获取的cookies信息会保存在本地 30 | 在你下一次使用这个程序的时候,程序并不会立刻通过网页登录,而是先检查本地信息是否有效,若是有效则使用旧信息访问,以此减少不必要的访问 31 | 32 | 33 | ## 版本信息 34 | v1.1 35 | 紧急修复了输入密码后会崩溃的BUG 36 | v1.2 37 | 添加IE webdriver作为兜底,从而修复没Chrome就会崩溃的情况 38 | 修改一些参数 39 | v1.3 40 | 添加了手动输入cookies项 41 | 添加了手动输入MHW路径项 42 | 添加了firefox webdriver 43 | 更改部分代码结构 44 | v1.4 45 | 修正了使用手动输入MHW路径安装的时候出现安装错误的情况 46 | 添加了下载进度显示 47 | v1.5 48 | 去除调整 utils.ini.py 结构 49 | 增加 utils.location_helper.py 用来处理路径 50 | 添加 MHW 路径记录功能 51 | 添加 VC 下载功能 52 | 修复了lib地址传递错误的问题 53 | v1.6 54 | 适配新的“StrackerLoader” 55 | 调整获取cookies的逻辑,使得多个浏览器都能尝试 56 | 添加MOD文件记录,在安装新版本的时候会删除旧版本的文件 57 | 删除了dll的MD5校验比对功能,因为“StrackerLoader”以后可能会经常变 58 | 更改安装逻辑 59 | v1.7 60 | 单独抽取出输出内容做为一个模块 my_print.py 61 | 调整部分描述 62 | 修复了VC安装功能由于Cookies导致的错误 63 | 增加了英文输出,但是并没有测试(Add English log, But there was no test) 64 | 65 | 66 | 67 | ## 其他 68 | 自己家里打包代码:F:\Environment\Python\envs\CheckStrackerLoader\Scripts\pyinstaller --workpath F:\Workspace\CheckStrackerLoader\pyinstaller_rubbish -y -F -i F:\Workspace\CheckStrackerLoader\1.ico main.py 69 | 70 | 71 | 2020年3月10日18:04:01 72 | -------------------------------------------------------------------------------- /utils/ini.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | ''' 4 | @File : ini.py 5 | @Time : 2020/02/24 09:40:57 6 | @Author : Recluse Xu 7 | @Version : 1.0 8 | @Contact : 444640050@qq.com 9 | @License : (C)Copyright 2017-2022, Recluse 10 | @Desc : None 11 | ''' 12 | 13 | # here put the import lib 14 | import configparser 15 | import time 16 | import datetime 17 | 18 | 19 | class Conf_ini(object): 20 | config = configparser.ConfigParser() 21 | 22 | def __init__(self, run_location): 23 | 24 | self.ini_location = run_location + '/conf.ini' 25 | self.config.read(self.ini_location, encoding='utf-8') 26 | 27 | def get_installed_SL_upload_date(self): 28 | ''' 29 | @return: 获取已经被安装上了的MOD的上传时间(时间戳):int 30 | ''' 31 | return int(self.config.get('StrackerLoader', 'installed_mod_upload_date')) 32 | 33 | def set_installed_SL_upload_date(self, the_time: datetime): 34 | ''' 35 | @summary: 设置已经被安装上了的MOD的上传时间 36 | ''' 37 | the_time = int(time.mktime(the_time.timetuple())) 38 | self.config.set("StrackerLoader", "installed_mod_upload_date", str(the_time)) 39 | self.write_conf() 40 | 41 | def get_last_spide_time(self): 42 | ''' 43 | @return: 上一次爬虫的时间戳:int 44 | ''' 45 | return int(self.config.get('StrackerLoader', 'last_spide_time')) 46 | 47 | def set_new_last_spide_time(self): 48 | ''' 49 | @summary: 设置新的爬虫时间戳 50 | ''' 51 | now = datetime.datetime.now() 52 | now = int(time.mktime(now.timetuple())) 53 | self.config.set("StrackerLoader", "last_spide_time", str(now)) 54 | self.write_conf() 55 | 56 | def is_safe_to_spide(self): 57 | ''' 58 | @summary: 根据爬虫间隔,返回是否应爬虫 59 | ''' 60 | now = datetime.datetime.now() 61 | now = int(time.mktime(now.timetuple())) 62 | wating_time = now - self.get_last_spide_time() 63 | if wating_time > 30: 64 | return True 65 | return False 66 | 67 | def get_nexus_account_info(self): 68 | ''' 69 | @summary: 从设置中查询 N 网账户信息 70 | @return: user_name:str, user_password:str 71 | ''' 72 | user_name = self.config.get('NexusAccount', 'user_name') 73 | user_password = self.config.get('NexusAccount', 'user_password') 74 | return user_name, user_password 75 | 76 | def set_nexus_account_info(self, user_name, user_password): 77 | ''' 78 | @summary: 设置 N 网账户信息 79 | ''' 80 | self.config.set('NexusAccount', 'user_name', user_name) 81 | self.config.set('NexusAccount', 'user_password', user_password) 82 | self.write_conf() 83 | 84 | def get_mod_file_list(self): 85 | ''' 86 | @summary: 得到已经安装了的前置MOD的 文件列表 87 | @return: list 88 | ''' 89 | file_list = self.config.get('StrackerLoader', 'mod_files') 90 | if len(file_list) == 0: 91 | return [] 92 | if isinstance(file_list, str): 93 | file_list = file_list.replace(' ', '') 94 | if len(file_list) == 0: 95 | return [] 96 | file_list = file_list.replace('\'', '').replace('\"', '').split(',') 97 | return file_list 98 | 99 | def set_mod_file_list(self, file_list: list): 100 | ''' 101 | @summary: 设置已经安装了的前置MOD的 文件的信息 102 | ''' 103 | self.config.set('StrackerLoader', 'mod_files', str(file_list)[1:-1]) 104 | self.write_conf() 105 | 106 | def write_conf(self): 107 | ''' 108 | @summary: 配置持久化 109 | ''' 110 | with open(self.ini_location, "w", encoding="utf-8")as f: 111 | self.config.write(f) 112 | 113 | @staticmethod 114 | def creat_new_conf_ini(loaction, N_name, N_pwd): 115 | ''' 116 | @summary: 初始化,创建 conf.ini 117 | ''' 118 | config = configparser.ConfigParser() 119 | 120 | config.add_section("StrackerLoader") 121 | config.set("StrackerLoader", "installed_mod_upload_date", "0") 122 | config.set("StrackerLoader", 'last_spide_time', "0") 123 | config.set("StrackerLoader", 'mod_files', "") 124 | 125 | config.add_section("NexusAccount") 126 | config.set("NexusAccount", "user_name", N_name) 127 | config.set("NexusAccount", "user_password", N_pwd) 128 | 129 | with open(loaction, "w") as f: 130 | config.write(f) 131 | -------------------------------------------------------------------------------- /utils/location_helper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | ''' 4 | @File : location_helper.py 5 | @Time : 2020/03/10 13:42:51 6 | @Author : Recluse Xu 7 | @Version : 1.0 8 | @Contact : 444640050@qq.com 9 | @License : (C)Copyright 2017-2022, Recluse 10 | @Desc : None 11 | ''' 12 | 13 | # here put the import lib 14 | import os 15 | import winreg 16 | import time 17 | import configparser 18 | from tkinter.filedialog import askdirectory 19 | 20 | _info_print_func = None 21 | 22 | 23 | class Location(object): 24 | def __init__(self): 25 | self.run_folder = os.path.abspath(os.curdir)+"\\" 26 | 27 | self.conf_ini_file = self.run_folder+'conf.ini' 28 | self.resources_folder = self.run_folder + 'resources\\' 29 | self.lib_folder = self.run_folder + 'lib\\' 30 | self.cookies_txt_file = self.resources_folder + "Nexus_Cookies.txt" 31 | self.dl_loader_folder = self.resources_folder + 'StrackerLoade\\' 32 | 33 | self.mhw_folder = _get_MHW_Install_Address(self.conf_ini_file) 34 | 35 | def get_run_folder(self): 36 | ''' 37 | @return: 返回程序运行的目录的路径:str 38 | ''' 39 | return self.run_folder 40 | 41 | def get_resources_folder(self): 42 | ''' 43 | @return: 返回程序运行目录下的resources目录的路径:str 44 | ''' 45 | return self.resources_folder 46 | 47 | def get_lib_folder(self): 48 | ''' 49 | @return: 返回程序运行目录下的lib目录的路径:str 50 | ''' 51 | return self.lib_folder 52 | 53 | def get_conf_file(self): 54 | ''' 55 | @return: 返回程序运行目录下conf.ini的路径:str 56 | ''' 57 | return self.conf_ini_file 58 | 59 | def get_mhw_folder(self): 60 | ''' 61 | @return: 返回程序运行目录下的lib目录的路径:str 62 | ''' 63 | return self.mhw_folder 64 | 65 | def get_cookies_txt_file(self): 66 | ''' 67 | @return: 返回记录cookies的文件的路径 68 | ''' 69 | return self.cookies_txt_file 70 | 71 | def get_dl_loader_folder(self): 72 | ''' 73 | @return: 返回资源文件夹下的strackloader目录 74 | ''' 75 | return self.dl_loader_folder 76 | 77 | def save_to_conf_ini_file(self): 78 | ''' 79 | @summary: 将路径记录保存到文件中 80 | ''' 81 | config = configparser.ConfigParser() 82 | config.read(self.conf_ini_file, encoding='utf-8') 83 | if "Locations" not in config.sections(): 84 | config.add_section("Locations") 85 | config.set("Locations", "mhw_folder", self.mhw_folder) 86 | with open(self.conf_ini_file, "w") as f: 87 | config.write(f) 88 | 89 | 90 | def _is_file_exists(file_path: str): 91 | ''' 92 | @summary: 检测路径下的文件是否都已经存在 93 | @return: :bool 94 | ''' 95 | return os.path.exists(file_path) 96 | 97 | 98 | def _is_effective_MHW_location(location): 99 | ''' 100 | @summary: 检测路径是否为MHW目录,通过其下是否有mhw启动程序判断。 101 | @return: :bool 102 | ''' 103 | return _is_file_exists(location+"MonsterHunterWorld.exe") 104 | 105 | 106 | def _warning_and_exit(statue_code=0): 107 | ''' 108 | @summary: 警告用户这个程序将在10s后退出 109 | ''' 110 | print('将在 10 秒后自动退出') 111 | time.sleep(10) 112 | exit(statue_code) 113 | 114 | 115 | def _get_MHW_Install_Address(conf_ini_file): 116 | ''' 117 | @return: MHW目录:str 118 | ''' 119 | _info_print('loc_0') 120 | _info_print('loc_1') 121 | if _is_file_exists(conf_ini_file): 122 | try: 123 | config = configparser.ConfigParser() 124 | config.read(conf_ini_file, encoding='utf-8') 125 | mhw_folder = config.get('Locations', 'mhw_folder') 126 | if _is_effective_MHW_location(mhw_folder): 127 | return mhw_folder 128 | except Exception as e: 129 | print("失败", e) 130 | 131 | _info_print('loc_2') 132 | try: 133 | aReg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) 134 | aKey = winreg.OpenKey( 135 | aReg, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 582010") 136 | data = winreg.QueryValueEx(aKey, "InstallLocation")[0] 137 | location = data + '\\' 138 | # 验证是否真的是存在的 139 | if _is_effective_MHW_location(location): 140 | return location 141 | except Exception as e: 142 | print("失败", e) 143 | 144 | _info_print('loc_3') 145 | try: 146 | location = askdirectory() + "/" 147 | if _is_effective_MHW_location(location): 148 | return location 149 | except Exception as e: 150 | print("失败", e) 151 | 152 | _info_print('loc_4') 153 | _warning_and_exit(1) 154 | 155 | 156 | ''' 157 | for print 158 | ''' 159 | 160 | 161 | def _info_print(info_num): 162 | ''' 163 | @summary: 根据信息号码 和 是否为中文输出内容 164 | ''' 165 | global _info_print_func 166 | _info_print_func(info_num) 167 | 168 | 169 | def set_info_print_func(func): 170 | ''' 171 | @return: 设置输出函数 172 | ''' 173 | global _info_print_func 174 | _info_print_func = func 175 | 176 | 177 | if __name__ == "__main__": 178 | l = Location() 179 | l.save_to_conf_ini_file() 180 | a = l.get_mhw_folder() 181 | print(a) 182 | a = _is_effective_MHW_location(a) 183 | print(a) -------------------------------------------------------------------------------- /utils/my_print.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | ''' 4 | @File : my_print.py 5 | @Time : 2020/03/18 23:14:54 6 | @Author : Recluse Xu 7 | @Version : 1.0 8 | @Contact : 444640050@qq.com 9 | @License : (C)Copyright 2017-2022, Recluse 10 | @Desc : None 11 | ''' 12 | 13 | # here put the import lib 14 | import locale 15 | 16 | _is_chinese = None 17 | 18 | chinese_info_print_dict = { 19 | '000': '本程序由Recluse制作', 20 | '001': '本程序用于一键更新前置MOD Stracker\'s Loader', 21 | '002': '本程序不会用于盗号, 偷取信息 等非法操作', 22 | '003': '但由于源码是公开的, 可能存在被魔改成盗号程序的可能。故建议从github获取本程序。', 23 | '004': 'github地址:https://github.com/RecluseXU/CheckStrackerLoader', 24 | '005': 'B站联系地址:https://www.bilibili.com/video/av91993651', 25 | '006': 'https://www.nexusmods.com/monsterhunterworld/mods/2639', 26 | '007': '输入回车键开始', 27 | '100': '初始化', 28 | '101': '\t创建resources目录', 29 | '102': '\t创建lib目录', 30 | '103': '\t创建conf.ini', 31 | '104': '这次输入的信息会记录在conf.ini中,如果需要更改,用记事本修改conf.ini的内容即可', 32 | '105': '请输入N网账号或邮箱:', 33 | '106': '请输N网密码:', 34 | '107': '\t尝试获取 conf.ini信息', 35 | '108': '\t\t读取conf.ini', 36 | '109': '\t尝试获取 Cookies 信息', 37 | '110': '\t\tNexus_Cookies.json存在', 38 | '111': '\t\t\t尝试通过Nexus_Cookies.json获取Cookies信息', 39 | '112': '\t\t\t\tCookies信息验证成功,', 40 | '113': '\t\t\t\tCookies信息验证失败', 41 | '114': '\t\t尝试通过登录N网记录Cookies信息', 42 | '115': '\t\t尝试通过手动输入, 获知Cookies信息', 43 | '116': '\t\t\t\t手工输入的Cookies信息验证成功', 44 | '117': '\t\t\t\t手工输入的Cookies信息验证失败', 45 | '': '', 46 | '200': '获取MOD信息', 47 | '201': '\t尝试获取N网 "Stracker\'s Loader" 文件信息页', 48 | '202': '\t\t尝试通过爬虫得到 "Stracker\'s Loader" 文件页', 49 | '203': '\t\t由于爬虫等待时间未过,从本地记录中获取', 50 | '204': '\t\t\t获取成功', 51 | '204_1': '\t尝试分析文件页,得到 "Stracker\'s Loader" 最新版信息', 52 | '205': '\t\t最新版本上传日期(存在时区误差)', 53 | '206': '\t\t最新版本下载地址', 54 | '207': '已安装的版本与最新版发布时间一致,无需更新', 55 | '208': '\t尝试获取N网 "Stracker\'s Loader" 最新版文件下载页', 56 | '209': '\t尝试分析N网 "Stracker\'s Loader" 最新版文件下载页', 57 | '210': '\t尝试获取N网 "Stracker\'s Loader" 最新版文件下载url', 58 | '211': '\t\t最新版文件下载url', 59 | '212': '\t\t最新版文件类型', 60 | '213': '\t尝试下载"Stracker\'s Loader" 最新版文件', 61 | '214': '\t\t文件已保存为', 62 | '215': '\t尝试解压"Stracker\'s Loader" 文件', 63 | '216': '\t尚未编写该压缩文件类型解压方法', 64 | '217': '\t请自行尝试在已经下载好的文件中手动安装', 65 | '218': '\t检查是否要删除旧文件', 66 | '219': '\t\t尝试删除旧版\"Stracker\'s Loader\"文件', 67 | '220': '\t\t\t\t文件不存在', 68 | '221': '\t尝试获取\"Stracker\'s Loader\"文件信息', 69 | '222': '\t\t新下载的\"Stracker\'s Loader\"所包含的文件: ', 70 | '223': '\t尝试安装\"Stracker\'s Loader\"文件', 71 | '224': '\t更新安装信息', 72 | '225': '\t\t更新 已安装版本N网作者上传时间信息', 73 | '226': '\t\t更新 已安装版本文件 信息', 74 | '227': '\t\t程序运行完毕', 75 | '': '', 76 | 'vc_0': '\t需要安装VC吗?', 77 | 'vc_1': '\t\t这个是Stracker\'s Loader的运行库。没有安装这个,但安装了Stracker\'s Loader,会进不了游戏。', 78 | 'vc_2': '\t\t要是你不确定是否已经安装,那么建议安装.', 79 | 'vc_3': '\t\t输入y开始下载安装,输入其他跳过', 80 | '': '', 81 | 'loc_0': '尝试获取MHW目录', 82 | 'loc_1': '\t尝试从conf.ini中获取 MHW 目录', 83 | 'loc_2': '\t尝试从注册表获取 MHW 目录', 84 | 'loc_3': '请手动选择 MHW 目录', 85 | 'loc_4': '尝试获取MHW路径失败', 86 | '': '', 87 | 'Coo_0': '\t\t\t尝试初始化浏览器', 88 | 'Coo_1': '\t\t\t\t尝试初始化 Chrome 浏览器', 89 | 'Coo_2': '\t\t\t\t尝试初始化 Firefox 浏览器', 90 | 'Coo_3': '\t\t\t\t尝试初始化 IE 浏览器', 91 | 'Coo_4': '\t\t\t尝试初始化浏览器失败', 92 | 'Coo_5': '\t\t\t登录界面', 93 | 'Coo_6': '\t\t\t请在页面中登录N网账户', 94 | 'Coo_7': '\t\t\t如果设置在conf.ini的账户密码正确,这个过程会自动完成。', 95 | 'Coo_8': '\t\t\t如果不正确,请手动输入账户密码', 96 | 'Coo_9': '\t\t\t每一步操作都设置了一定的的可行时间,超过时间程序就会退出', 97 | 'Coo_10': '\t\t\t等待进入首页Cookies,请勿操作', 98 | 'Coo_11': '\t\t\t尝试手动获取Cookies信息?(输入y代表尝试,输入其他东西代表不尝试并退出)', 99 | 'Coo_12': '\t\t\t请输入手动获取的cookies:', 100 | '': '', 101 | } 102 | english_info_print_dict = { 103 | '000': 'This program was written by Recluse', 104 | '001': 'This program is used to update Stracker\'s Loader', 105 | '002': 'This program will not be used to steal Numbers, steal information and other illegal operations', 106 | '003': 'Because everyone can get the source code. There may be more to be changed to the possibility of theft program. Therefore, it is recommended to obtain this program from Github or Nexus', 107 | '004': 'Github Location:https://github.com/RecluseXU/CheckStrackerLoader', 108 | '005': 'Bilibili Location:https://www.bilibili.com/video/av91993651', 109 | '006': 'Nexus Location: https://www.nexusmods.com/monsterhunterworld/mods/2639', 110 | '007': 'Press the enter key to continue', 111 | '100': 'Initialize', 112 | '101': '\tCreate resources folder', 113 | '102': '\tCreate lib folder', 114 | '103': '\ttCreate conf.ini file', 115 | '104': 'The information you entered this time will be recorded in conf.ini. If changes are needed, just modify the contents of conf.ini', 116 | '105': 'Please input Nexus Account or Email:', 117 | '106': 'Please input Nexus Account password:', 118 | '107': '\tTry to get the information from conf.ini', 119 | '108': '\t\tloading conf.ini', 120 | '109': '\tTry to get the information of Cookies ', 121 | '110': '\t\tfile Nexus_Cookies.json do not exist', 122 | '111': '\t\t\tTry to get the information of Cookies in Nexus_Cookies.json', 123 | '112': '\t\t\t\tCookies Information authentication succeeded', 124 | '113': '\t\t\t\tCookies Information authentication failed', 125 | '114': '\t\tTry to get the information of Cookies by logging in Nexus', 126 | '115': '\t\tTry to get the information of Cookies by manually entering it', 127 | '116': '\t\t\t\tEntering Cookies Information authentication success', 128 | '117': '\t\t\t\tEntering Cookies Information authentication failed', 129 | '': '', 130 | '200': 'Get MOD information', 131 | '201': '\tTry to get Stracker\'s Loader information from Nexus file page', 132 | '202': '\t\tTry to get Stracker\'s Loader information by crawler', 133 | '203': '\t\tSince the crawler has not passed the time limit, it is obtained from the local record', 134 | '204': '\t\t\tsuccess', 135 | '204_1': '\tTry to analyze the file page for the latest version of Stracker\'s Loader', 136 | '205': '\t\tLatest version upload date(There are time zone errors in different countries)', 137 | '206': '\t\tLatest version download address', 138 | '207': 'The installed version is released at the same time as the latest version, and no updates are required', 139 | '208': '\tTry to get the latest version of the Stracker\'s Loader file download page', 140 | '209': '\tTry to analyze the latest version of "Stracker\'s Loader" file download page', 141 | '210': '\tTry to get the latest version of the Stracker\'s Loader download url', 142 | '211': '\t\tlatest version of the Stracker\'s Loader download url', 143 | '212': '\t\tlatest version of the Stracker\'s Loader file type', 144 | '213': '\tTry to download the latest version of Stracker\'s Loader', 145 | '214': '\t\tThe file has been saved as', 146 | '215': '\tTry to unzip Stracker\'s Loader file', 147 | '216': '\tThe file type unzip method has not been written', 148 | '217': '\tPlease try to install it manually in the downloaded files', 149 | '218': '\tCheck to see if you want to delete the old file', 150 | '219': '\t\tTry to delete the old version Stracker\'s Loader files', 151 | '220': '\t\t\t\tfile do not exist', 152 | '221': '\tTry to get the Newly downloaded Stracker\'s Loader file information', 153 | '222': '\t\tNewly downloaded Stracker\'s Loader contained files: ', 154 | '223': '\tTry to install Stracker\'s Loader files', 155 | '224': '\tUpdate installation information', 156 | '225': '\t\tUpdate the information of installed version upload time', 157 | '226': '\t\tUpdate the information of installed version file', 158 | '227': '\t\tProgram finished', 159 | '': '', 160 | 'vc_0': '\tDo you need to install VC?', 161 | 'vc_1': '\t\tStracker\'s Loader base on it. without it, Stracker\'s Loader will not run', 162 | 'vc_2': '\t\tIf you are not sure if it is already installed, it is recommended.', 163 | 'vc_3': '\t\tInput y to start the download and install VC, and input others to skip', 164 | '': '', 165 | 'loc_0': 'Try to get the MHW Location', 166 | 'loc_1': '\tTry to get the MHW Location frome conf.ini', 167 | 'loc_2': '\tTry to get the MHW Location frome the registry', 168 | 'loc_3': 'Please manually select the MHW directory', 169 | 'loc_4': 'An attempt to obtain the MHW path failed', 170 | '': '', 171 | 'Coo_0': '\t\t\tTry to initialize the browser', 172 | 'Coo_1': '\t\t\t\tTry to initialize Chrome', 173 | 'Coo_2': '\t\t\t\tTry to initialize Firefox', 174 | 'Coo_3': '\t\t\t\tTry to initialize IE', 175 | 'Coo_4': '\t\t\tAn attempt to initialize the browser failed', 176 | 'Coo_5': '\t\t\tLogin page', 177 | 'Coo_6': '\t\t\tPlease Login', 178 | 'Coo_7': '\t\t\tIf the password for the account set at conf.ini is correct, this process is done automatically.', 179 | 'Coo_8': '\t\t\tIf not, please enter the account password manually', 180 | 'Coo_9': '\t\t\tEach step of the operation is set a certain feasible time, beyond the time program will exit', 181 | 'Coo_10': '\t\t\tWait to enter the home page, do not operate', 182 | 'Coo_11': '\t\t\tTrying to retrieve Cookies manually?(Enter y for try, enter something else for not try and exit)', 183 | 'Coo_12': '\t\t\tPlease enter cookies obtained manually:', 184 | '': '', 185 | } 186 | 187 | 188 | def info_print(info_num): 189 | ''' 190 | @summary: 根据信息号码 和 是否为中文输出内容 191 | ''' 192 | if _is_system_using_chinese(): 193 | print(chinese_info_print_dict[info_num]) 194 | else: 195 | print(english_info_print_dict[info_num]) 196 | 197 | 198 | def _is_system_using_chinese(): 199 | ''' 200 | @summary: 判断系统是否在使用中文 201 | ''' 202 | global _is_chinese 203 | if _is_chinese is None: 204 | if locale.getdefaultlocale()[0] == "zh_CN": 205 | _is_chinese = True 206 | else: 207 | _is_chinese = False 208 | return _is_chinese 209 | 210 | -------------------------------------------------------------------------------- /utils/nexus_cookies.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | ''' 4 | @File : Nexus_cookies.py 5 | @Time : 2020/02/24 15:52:31 6 | @Author : Recluse Xu 7 | @Version : 1.0 8 | @Contact : 444640050@qq.com 9 | @License : (C)Copyright 2017-2022, Recluse 10 | @Desc : None 11 | ''' 12 | 13 | # here put the import lib 14 | 15 | 16 | from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 17 | from selenium.webdriver.common.by import By 18 | from selenium.webdriver.support.ui import WebDriverWait 19 | from selenium.webdriver.support import expected_conditions as EC 20 | from selenium.webdriver.support.expected_conditions import presence_of_element_located 21 | from selenium import webdriver 22 | import json 23 | import os 24 | from utils.util import Util 25 | # from util import Util 26 | 27 | 28 | cookies_json_location = None 29 | lib_location = None 30 | _info_print_func = None 31 | 32 | 33 | def set_cookies_json_location(location: str): 34 | ''' 35 | @summary: 设置Cookies.json的路径 36 | ''' 37 | global cookies_json_location 38 | cookies_json_location = location 39 | 40 | 41 | def set_lib_location_location(location: str): 42 | ''' 43 | @summary: 设置lib目录的路径 44 | ''' 45 | 46 | global lib_location 47 | lib_location = location 48 | 49 | 50 | def _init_selenium_chrome_driver(): 51 | ''' 52 | @summary: 配置selenium.webdriver chrome 53 | @return: selenium.webdriver chrome 54 | ''' 55 | _info_print('Coo_1') 56 | chromedriver = lib_location + "chromedriver.exe" 57 | drivePath = os.path.join(os.path.dirname(__file__), chromedriver) 58 | options = webdriver.ChromeOptions() 59 | # 禁止图片加载 60 | # prefs = {"profile.managed_default_content_settings.images": 2} 61 | # options.add_experimental_option("prefs", prefs) 62 | # 不显示图片 63 | # options.add_argument('--blink-settings=imagesEnabled=false') 64 | # 非沙盒模式 65 | options.add_argument('no-sandbox') 66 | driver = webdriver.Chrome(executable_path=drivePath, 67 | chrome_options=options) 68 | return driver 69 | 70 | 71 | def _init_selenium_firefox_driver(): 72 | ''' 73 | @summary: 配置selenium.webdriver firefoxdriver 74 | @return: selenium.webdriver firefoxdriver 75 | ''' 76 | _info_print('Coo_2') 77 | firefoxdriver = lib_location + "geckodriver.exe" 78 | drivePath = os.path.join(os.path.dirname(__file__), firefoxdriver) 79 | driver = webdriver.Firefox(executable_path=drivePath) 80 | return driver 81 | 82 | 83 | def _init_selenium_ie_driver(): 84 | ''' 85 | @summary: 配置selenium.webdriver IE 86 | @return: selenium.webdriver IE 87 | ''' 88 | _info_print('Coo_3') 89 | iedriver = lib_location + "IEDriverServer_x32.exe" 90 | drivePath = os.path.join(os.path.dirname(__file__), iedriver) 91 | 92 | capabilities = DesiredCapabilities.INTERNETEXPLORER 93 | capabilities["ignoreProtectedModeSettings"] = True # 无视保护模式 94 | capabilities["ignoreZoomSetting"] = True # 不检查界面缩放 95 | driver = webdriver.Ie(executable_path=drivePath, capabilities=capabilities) 96 | return driver 97 | 98 | 99 | def _selenium_operations(driver: webdriver, user_name: str, user_password: str): 100 | # 登录界面 101 | _info_print('Coo_5') 102 | driver.get('https://users.nexusmods.com/auth/sign_in') 103 | _info_print('Coo_6') 104 | _info_print('Coo_7') 105 | _info_print('Coo_8') 106 | _info_print('Coo_9') 107 | 108 | wait = WebDriverWait(driver, 300) 109 | username_inputer = wait.until(presence_of_element_located((By.ID, "user_login"))) 110 | userpassword_inputer = wait.until(presence_of_element_located((By.ID, "password"))) 111 | commit_button = wait.until(presence_of_element_located((By.XPATH, '//input[@type="submit"]'))) 112 | 113 | username_inputer.send_keys(user_name) 114 | userpassword_inputer.send_keys(user_password) 115 | commit_button.click() 116 | 117 | wait.until(EC.url_changes) 118 | # 欢迎界面 119 | 120 | index_a = wait.until(EC.presence_of_element_located((By.XPATH, '//div[@class="links"]/div[@class="left-link"]/a[1]'))) 121 | index_a.click() 122 | _info_print('Coo_10') 123 | 124 | # 返回首页后 125 | # Util.info_print('等待从首页中获取cookies', 3) 126 | wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".intro > h1:nth-child(1)"))) 127 | nexus_cookies_list = driver.get_cookies() 128 | driver.quit() 129 | 130 | nexus_cookies = dict() 131 | for cookie in nexus_cookies_list: 132 | nexus_cookies[cookie['name']] = cookie['value'] 133 | 134 | return nexus_cookies 135 | 136 | 137 | def save_cookies_to_file(nexus_cookies: dict): 138 | ''' 139 | @summary: 将cookies信息保存到resources/Nexus_Cookies.txt 140 | ''' 141 | with open(cookies_json_location, 'w', encoding="utf-8")as f: 142 | json.dump(nexus_cookies, f) 143 | 144 | 145 | def get_cookies_by_selenium_login(user_name: str, user_password: str): 146 | ''' 147 | @summary: 通过selenium获取cookies信息,并记录下来,返回 148 | @return: cookies:dict 149 | ''' 150 | _info_print('Coo_0') 151 | 152 | nexus_cookies = None 153 | for _init_selenium_func in [_init_selenium_chrome_driver, _init_selenium_firefox_driver, _init_selenium_ie_driver]: 154 | try: 155 | driver = _init_selenium_func() 156 | nexus_cookies = _selenium_operations(driver, user_name, user_password) 157 | save_cookies_to_file(nexus_cookies) 158 | return nexus_cookies 159 | except Exception as e: 160 | print("失败", e) 161 | if not nexus_cookies: 162 | _info_print('Coo_4') 163 | return 164 | 165 | 166 | def get_cookies_from_file(): 167 | ''' 168 | @summary: 从文件中读取cookies信息 169 | @return: cookies:dict 170 | ''' 171 | 172 | with open(cookies_json_location, "r", encoding="utf-8")as f: 173 | nexus_cookies = json.load(f) 174 | return nexus_cookies 175 | 176 | 177 | def get_cookies_by_input(): 178 | ''' 179 | @summary: 让用户手工输入cookies信息 180 | @return: cookies:dict 181 | ''' 182 | _info_print('Coo_11') 183 | a = input() 184 | if a == "y": 185 | cookes_dict = dict() 186 | try: 187 | _info_print('Coo_12') 188 | cookies_str = input() 189 | for cookie in cookies_str.split(';'): 190 | cookie_one_list = cookie.split('=') 191 | cookes_dict[cookie_one_list[0]] = cookie_one_list[1] 192 | save_cookies_to_file(cookes_dict) 193 | return cookes_dict 194 | except Exception as e: 195 | print("失败", e) 196 | Util.warning_and_exit(1) 197 | 198 | 199 | ''' 200 | for print 201 | ''' 202 | 203 | 204 | def _info_print(info_num): 205 | ''' 206 | @summary: 根据信息号码 和 是否为中文输出内容 207 | ''' 208 | info_print_func(info_num) 209 | 210 | 211 | def set_info_print_func(func): 212 | ''' 213 | @return: 设置输出函数 214 | ''' 215 | global info_print_func 216 | info_print_func = func 217 | 218 | 219 | if __name__ == "__main__": 220 | # host = ".baidu.com" 221 | # init_selenium_driver() 222 | # a = get_cookie_from_chrome(host) 223 | # b = get_cookies_by_selenium_login("", "") 224 | 225 | set_lib_location_location("F:\\Workspace\\CheckStrackerLoader\\lib\\") 226 | set_cookies_json_location("F:\\Workspace\\CheckStrackerLoader\\dist\\resources\\Nexus_Cookies.txt") 227 | 228 | b = get_cookies_by_selenium_login("444640050@qq.com", "XuGuoHao444640050") 229 | # print(b) 230 | pass 231 | -------------------------------------------------------------------------------- /utils/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | ''' 4 | @File : util.py 5 | @Time : 2020/02/24 10:13:15 6 | @Author : Recluse Xu 7 | @Version : 1.0 8 | @Contact : 444640050@qq.com 9 | @License : (C)Copyright 2017-2022, Recluse 10 | @Desc : None 11 | ''' 12 | 13 | # here put the import lib 14 | import winreg 15 | import hashlib 16 | import os 17 | import time 18 | import zipfile 19 | import shutil 20 | import datetime 21 | from tkinter.filedialog import askdirectory 22 | 23 | 24 | is_chinese = None 25 | 26 | 27 | class Util(object): 28 | 29 | @staticmethod 30 | def run_a_exe(location: str): 31 | ''' 32 | @summary: 运行一个exe文件 33 | ''' 34 | os.system(location) 35 | 36 | @staticmethod 37 | def creat_a_folder(location: str): 38 | ''' 39 | @summary: 在程序目录下创建resources文件夹 40 | ''' 41 | if os.path.exists(location) is False: 42 | os.mkdir(location) 43 | 44 | 45 | @staticmethod 46 | def get_Firefox_Install_Address(): 47 | ''' 48 | @return: FireFox目录:str 49 | ''' 50 | try: 51 | aReg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) 52 | aKey = winreg.OpenKey( 53 | aReg, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall") 54 | i = 0 55 | while 1: 56 | i = i+1 57 | keyname = winreg.EnumKey(aKey, i) 58 | # 因为firefox在注册表里的键带着一个版本号,所以不能写死,这里通过关键词找到键名 59 | if(keyname.find('Firefox') != -1): 60 | print(keyname) 61 | break 62 | 63 | aKey = winreg.OpenKey( 64 | aReg, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\\" + keyname) 65 | data = winreg.QueryValueEx(aKey, "InstallLocation")[0] 66 | return data + '\\' 67 | except Exception as e: 68 | print("->Fail\t可能此电脑未安装Firefox", e) 69 | aKey.close() 70 | 71 | @staticmethod 72 | def is_file_exists(file_path: str): 73 | ''' 74 | @summary: 检测路径下的文件是否都已经存在 75 | @return: :bool 76 | ''' 77 | return os.path.exists(file_path) 78 | 79 | @staticmethod 80 | def get_file_MD5(file_location): 81 | ''' 82 | @staticmethod 83 | @return: 返回目标文件的MD5:str 84 | ''' 85 | try: 86 | with open(file_location, 'rb')as f: 87 | file_bytes = f.read() 88 | md5_str = hashlib.md5(file_bytes).hexdigest() 89 | return md5_str 90 | except Exception as e: 91 | print("->失败", e) 92 | Util.warning_and_exit(1) 93 | 94 | @staticmethod 95 | def info_print(info, space=0): 96 | ''' 97 | @staticmethod 98 | @summary: 简单输出 99 | ''' 100 | for i in range(space): 101 | print('\t', end="") 102 | print(info) 103 | 104 | @staticmethod 105 | def warning_and_exit(statue_code=0): 106 | ''' 107 | @staticmethod 108 | @summary: 警告用户这个程序将在10s后退出 109 | ''' 110 | print('将在 15 秒后自动退出') 111 | time.sleep(15) 112 | exit(statue_code) 113 | 114 | @staticmethod 115 | def unzip_single(src_file, dest_dir, password): 116 | ''' 117 | @staticmethod 118 | @summary: 从zip压缩包中解压单个文件到目标文件夹。 119 | ''' 120 | if password: 121 | password = password.encode() 122 | zf = zipfile.ZipFile(src_file) 123 | try: 124 | zf.extractall(path=dest_dir, pwd=password) 125 | except RuntimeError as e: 126 | print(e) 127 | zf.close() 128 | 129 | @staticmethod 130 | def unzip_all(source_dir: str, dest_dir: str, password: str): 131 | ''' 132 | @staticmethod 133 | @summary: 从zip压缩包中解压多个文件 134 | ''' 135 | if not os.path.isdir(source_dir): # 如果是单一文件 136 | Util.unzip_single(source_dir, dest_dir, password) 137 | else: 138 | it = os.scandir(source_dir) 139 | for entry in it: 140 | if entry.is_file() and os.path.splitext(entry.name)[1] == '.zip': 141 | Util.unzip_single(entry.path, dest_dir, password) 142 | 143 | @staticmethod 144 | def copy_file(origin_file_location, copy_file_location): 145 | ''' 146 | @staticmethod 147 | @summary: 复制一个文件到目标路径, 若已经存在,则覆盖 148 | ''' 149 | try: 150 | shutil.copyfile(origin_file_location, copy_file_location) 151 | except Exception as e: 152 | print(e) 153 | Util.warning_and_exit(1) 154 | 155 | @staticmethod 156 | def delete_file(del_file_location): 157 | ''' 158 | @staticmethod 159 | @summary: 复制一个文件到目标路径, 若已经存在,则覆盖 160 | ''' 161 | try: 162 | os.remove(del_file_location) 163 | except Exception as e: 164 | print(e) 165 | Util.warning_and_exit(1) 166 | 167 | @staticmethod 168 | def get_file_list_in_folder(folder_location: str): 169 | ''' 170 | @staticmethod 171 | @summary: 返回目录下所有文件的文件名 172 | @return: filenames:list 173 | ''' 174 | files = os.listdir(folder_location) 175 | return files 176 | 177 | @staticmethod 178 | def transform_datetime_to_timeStamp(d_time: datetime): 179 | ''' 180 | @staticmethod 181 | @summary: 将datetime对象转换为时间戳,返回 182 | @return: timeStamp:int 183 | ''' 184 | timeStamp = int(time.mktime(d_time.timetuple())) 185 | return timeStamp 186 | 187 | @staticmethod 188 | def is_win_x64(): 189 | ''' 190 | @staticmethod 191 | @summary: 返回操作系统是否是64位 192 | @return: bool 193 | ''' 194 | return 'PROGRAMFILES(X86)' in os.environ 195 | 196 | 197 | if __name__ == "__main__": 198 | # lacate = Util.get_run_folder() 199 | # print(lacate) 200 | a = Util.is_win_x64() 201 | print(a) 202 | --------------------------------------------------------------------------------