
根據下面的提供的王者榮耀最低戰力查詢的Python源碼,使用PYQT5搭建了一個GUI,同時還可以看每個英雄皮膚的高清圖。
""" 當然在學習Python的道路上肯定會困難,沒有好的學習資料,怎么去學習呢? 學習Python中有不明白推薦加入交流Q群號:928946953 群里有志同道合的小伙伴,互幫互助, 群里有不錯的視頻學習教程和PDF! 還有大牛解答! """ import requests as r import random import json def getMidStr(txt, txt_start, txt_end='', seeks=0, seeke=0): """取中間文本函數""" try: if txt_end or seeks or seeke: pass else: raise 1 s_1 = txt.find(txt_start) if s_1 == -1: raise 1 l_1 = len(txt_start) if txt_end: s_2 = txt.find(txt_end, s_1) if s_1 == -1 or s_2 == -1: return False return txt[s_1 + l_1:s_2] if seeks: return txt[s_1 - seeks:s_1] if seeke: return txt[s_1 + l_1:s_1 + l_1 + seeke] except Exception: return '傳參錯誤或未找到傳參文本' while True: hero = input("輸入需要查詢的英雄:") if hero == "": print("您輸入無效") elif hero == "0": exit() else: source = r.get("http://s.wukongfenshen.com:9972/main/api/honour/wzpower/static/js/index.js?v=0." + str( random.randint(1000000, 9999999))).text _json = getMidStr(source, "var dictAll = ", "}}") + "}}" _json = json.loads(_json) try: _json[hero] except KeyError as reason: print("沒有英雄:%s" % reason) continue title = _json[hero]["title"] content = _json[hero]["content"] print("英雄:%s" % title) content = str.replace(content, "<p><p>", "\n") content = str.replace(content, "<p> <p>", "\n") content = str.replace(content, "</p>", "\n") content = str.replace(content, "<p>", "") print(content + "\n")

如果想更換主界面背景,修改第90行的圖片路徑即可。
pixmap.load("./image/199-bigskin-3.jpg")
搜索框輸入想查詢的英雄名稱,帶有自動補全。英雄查詢失敗,或者名字不正確,則會被提示

點擊搜索,搜索時間有時較長有時較短,我也不知道為什么。結果界面如下,背景默認為原皮皮膚,可以移動鼠標位置到縮略圖上,即可將該皮膚設置為背景。

點擊QQ頭像即可切換到微信區

鼠標停留在地區上,則會顯示所屬省份或市級(該功能默認關閉,因為需調用百度地圖api, 使用前要自己去申請相應的 ak, 申請后將functions文件夾下get_detail_location.py 中的 ak 替換為自己的 ak 即可)

def get_detail_location(place_name): ak = 'ckXXxxxxxxxxxxxxxxxxcO9' # 替換為自己申請的ak url = "http://api.map.baidu.com/place/v2/suggestion" + \ f"?query={place_name}®ion={place_name}&city_limit=false&output=json&ak={ak}" res = requests.get(url).json() return res['result'][0]['province'] + res['result'][0]['city']
核心Python代碼:
from multiprocessing import Pool import sys import time from bs4 import BeautifulSoup from PyQt5.QtGui import QBrush, QIcon, QMouseEvent, QPalette, QPixmap from PyQt5.QtCore import pyqtSignal, Qt, QRect, QSize, QThread from PyQt5.QtWidgets import QApplication, QCompleter, QGraphicsOpacityEffect, QGroupBox,\ QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, QWidget import requests import sip # 引入自定義組件 from custom_widgets.CustomQLabel import CustomQLabel from custom_widgets.PowerDisplayArea import PowerDisplayArea from custom_widgets.SkinBox import SkinBox from custom_widgets.WarnMessagebox import WarnMessagebox # 引入自定義函數 from functions.get_detail_location import get_detail_location from functions.get_heroSkin_url import heroSkin, download_image_data from functions.get_power_information import get_power_info # 讀取qss文件並設置stylesheet class QssTool: @staticmethod def set_qss(obj, filepath): with open(filepath, 'r', encoding='utf-8') as f: style = f.read() obj.setStyleSheet(style) class RunThread(QThread): """ 該線程用於下載圖片數據以及獲取地名詳情信息 """ _signal = pyqtSignal(object) def __init__(self, hero, qq_info, wx_info): super(RunThread, self).__init__() self.hero = hero self.qq_info = qq_info self.wx_info = wx_info def __del__(self): self.wait() def run(self): print('線程開始') self.load_data(self.hero, self.qq_info, self.wx_info) def load_data(self, hero, qq_info, wx_info): """ 1. 調用 heroSkin 獲取英雄皮膚以及縮略圖網址,然后在線程池中下載圖片數據 2. 調用 get_detail_location 補全定位所在省份或者市級 :param hero: :param qq_info: :param wx_info: :return: """ small_skin, big_skin, num = heroSkin(hero) # 爬取高清皮膚、縮略圖網址,以及皮膚數量 pool = Pool(2 * (num-1)) # 利用線程池下載皮膚高清圖以及縮放圖數據 rl = pool.map(download_image_data, big_skin + small_skin) pool.close() # 關閉進程池,不再接受新的進程 pool.join() # 主進程阻塞等待子進程的退出 img_data = rl # 補全地區信息 qq_detail_place = [get_detail_location(qq_item['定位']) for qq_item in qq_info] wx_detail_place = [get_detail_location(wx_item['定位']) for wx_item in wx_info] return_data = { 'big_skin': img_data[:num], 'small_skin': img_data[num:], 'qq_detail_place': qq_detail_place, 'wx_detail_place': wx_detail_place, 'qq_info': qq_info, 'wx_info': wx_info, } self._signal.emit(return_data) # 主程序 class App(QWidget): def __init__(self, parent=None): super(App, self).__init__(parent) # 應用布局 美化 QssTool.set_qss(self, 'beautify.qss') self.setWindowTitle("王者戰力查詢") # 設置窗口背景 pixmap = QPixmap() pixmap.load("./image/199-bigskin-3.jpg") pixmap = pixmap.scaled(960, 441, Qt.KeepAspectRatio, Qt.SmoothTransformation) palette = QPalette() palette.setBrush(QPalette.Background, QBrush(pixmap)) self.setPalette(palette) self.mainLayout = QVBoxLayout(self) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.addStretch() # 顯示皮膚頭像的布局 self.thumbnailLayout = QHBoxLayout() self.thumbnailLayout.addStretch() self.smallLayout = QHBoxLayout() self.smallLayout.setContentsMargins(0, 0, 0, 0) self.smallLayout.setSpacing(10) self.thumbnailLayout.addLayout(self.smallLayout) self.thumbnailLayout.addStretch() self.mainLayout.addLayout(self.thumbnailLayout) self.setLayout(self.mainLayout) self.container = QGroupBox(self) self.container.setObjectName('container') self.container.setGeometry(QRect(340, 250, 280, 280)) self.lay = QVBoxLayout() self.search_box_area = QGroupBox(self) self.search_box_area.setObjectName('searchBox') self.search_box_layout = QHBoxLayout() self.search_box_layout.setSpacing(0) self.search_box_layout.setContentsMargins(5, 0, 5, 0) self.channel = CustomQLabel(self) self.channel.button_clicked_signal.connect(self.channel_Changed) self.inputBox = QLineEdit(self) self.inputBox.setObjectName('inputBox') self.inputBox.setPlaceholderText('輸入英雄名稱') self.inputBox.setAlignment(Qt.AlignCenter) self.btn = QPushButton('', self) self.btn.setIcon(QIcon('./image/scope1.png')) self.btn.setObjectName('searchButton') self.btn.setIconSize(QSize(30, 30)) self.btn.setFixedSize(QSize(36, 36)) self.btn.clicked.connect(self.search) self.search_box_layout.addWidget(self.channel) self.search_box_layout.addWidget(self.inputBox) self.search_box_layout.addWidget(self.btn) self.search_box_area.setLayout(self.search_box_layout) layout = QHBoxLayout() layout.addStretch() layout.addWidget(self.search_box_area) layout.addStretch() self.lay.addLayout(layout) self.container.setLayout(self.lay) self.lay.addSpacing(20) self.wid = PowerDisplayArea() self.wid.setInfo('省標') self.lay.addWidget(self.wid) self.wid2 = PowerDisplayArea() self.wid2.setInfo('市標') self.lay.addWidget(self.wid2) self.wid3 = PowerDisplayArea() self.wid3.setInfo('縣標') self.lay.addWidget(self.wid3) self.wid.hide() self.wid2.hide() self.wid3.hide() self.container.setStyleSheet(''' QGroupBox{ background-color:transparent; }''') self.status = False self.start() def start(self): url = 'https://pvp.qq.com/web201605/herolist.shtml' headers = { 'content-type': 'text/html', 'user-agent': '''Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36''' } total_list = requests.get(url, headers) total_list.encoding = 'GBK' soup = BeautifulSoup(total_list.text, 'html.parser') hero_names = soup.select('div[class="herolist-content"]') soup2 = BeautifulSoup(str(hero_names), 'html.parser') hero_names = soup2.find_all('a') hero_list = [item.get_text() for item in hero_names] # 增加自動補全 completer = QCompleter(hero_list) # 設置匹配模式 completer.setFilterMode(Qt.MatchStartsWith) # 設置補全模式 completer.setCompletionMode(QCompleter.InlineCompletion) # 給LineEdit設置補全器 self.inputBox.setCompleter(completer) def search(self): hero = self.inputBox.text() if hero == "": warnBox = WarnMessagebox() warnBox.set_position(self.pos().x() + 380, self.pos().y() + 145) warnBox.exec_() else: try: self.s1 = time.time() self.setWindowTitle("王者戰力查詢 (查詢中)") qq_info, wx_info = get_power_info(hero) self.thread = RunThread(hero, qq_info, wx_info) self.thread._signal.connect(self.call_backlog) # 開始線程 self.thread.start() except Exception as reason: print("沒有英雄:%s" % reason) warnBox = WarnMessagebox() warnBox.set_position(self.pos().x() + 380, self.pos().y() + 145) warnBox.exec_() def call_backlog(self, data): self.container.setGeometry(QRect(340, 80, 280, 280)) self.container.setStyleSheet('''QGroupBox#container{ background-color:white; border-radius:10px; }''') opacity = QGraphicsOpacityEffect() opacity.setOpacity(0.7) self.container.setGraphicsEffect(opacity) self.inputBox.setStyleSheet('''QLineEdit#inputBox { border:none; border-right:2px solid #7F7F7F; background-color:transparent; font-size:12pt; font-family:"微軟雅黑"; color:gray; }''') self.search_box_area.setStyleSheet(''' QGroupBox#searchBox{ border:2px solid #7F7F7F; } ''') self.btn.setIcon(QIcon('./image/scope2.png')) self.qq_info, self.wx_info = data['qq_info'], data['wx_info'] # 設置窗口背景 self.imgData = data['big_skin'] pixmap = QPixmap() pixmap.loadFromData(self.imgData[0]) pixmap = pixmap.scaled(960, 441, Qt.KeepAspectRatio, Qt.SmoothTransformation) palette = QPalette() palette.setBrush(QPalette.Background, QBrush(pixmap)) self.setPalette(palette) # -----------如果有頭像框,刷新前清除------------ for i in reversed(range(self.smallLayout.count())): w = self.smallLayout.itemAt(i) w.widget().deleteLater() self.smallLayout.removeItem(w) sip.delete(w.widget()) sip.delete(self.smallLayout) self.smallLayout = QHBoxLayout() # ----------重新生成縮略圖區--------------------------------- SkinBox.numInstance = 0 for i, skin in enumerate(data['small_skin']): self.skinBox = SkinBox() self.skinBox.setMouseTracking(True) self.skinBox.setObjectName(str(i)) self.skinBox.setSkin(skin, 'q' + str(i)) self.smallLayout.addWidget(self.skinBox) self.skinBox.num_send_signal.connect(self.get_object_name) self.thumbnailLayout.insertLayout(1, self.smallLayout) # ------獲取地區信息--------- self.qq_detailPlace = data['qq_detail_place'] self.wx_detailPlace = data['wx_detail_place'] # -------設置戰力數據-------- self.status = True self.show_information(self.channel.getStatus()) self.wid.show() self.wid2.show() self.wid3.show() self.setWindowTitle("王者戰力查詢") self.s2 = time.time() print('time', self.s2 - self.s1) del self.thread def channel_Changed(self): if self.status: self.show_information(not self.channel.getStatus()) def show_information(self, IsWx): if IsWx: self.wid.setInfo('省標', self.wx_info[2]['戰力'], self.wx_info[2]['定位'], self.wx_info[2]['更新時間'], self.wx_detailPlace[2]) self.wid2.setInfo('市標', self.wx_info[1]['戰力'], self.wx_info[1]['定位'], self.wx_info[1]['更新時間'], self.wx_detailPlace[1]) self.wid3.setInfo('縣標', self.wx_info[0]['戰力'], self.wx_info[0]['定位'], self.wx_info[0]['更新時間'], self.wx_detailPlace[0]) else: self.wid.setInfo('省標', self.qq_info[2]['戰力'], self.qq_info[2]['定位'], self.qq_info[2]['更新時間'], self.qq_detailPlace[2]) self.wid2.setInfo('市標', self.qq_info[1]['戰力'], self.qq_info[1]['定位'], self.qq_info[1]['更新時間'], self.qq_detailPlace[1]) self.wid3.setInfo('縣標', self.qq_info[0]['戰力'], self.qq_info[0]['定位'], self.qq_info[0]['更新時間'], self.qq_detailPlace[0]) self.lay.addWidget(self.wid) self.lay.addWidget(self.wid2) self.lay.addWidget(self.wid3) strNum = 0 def get_object_name(self, object_name): """ 1. 根據對象名稱,得到 SkinBox 中對應縮略圖的索引 2. 如果索引發生改變,則將新的索引值所對應的皮膚設置為當前界面背景 :param object_name: :return: """ list_str = list(object_name) list_str.pop(0) object_name = ''.join(list_str) if int(object_name) != self.strNum: self.strNum = int(object_name) pixmap = QPixmap() pixmap.loadFromData(self.imgData[self.strNum]) pixmap = pixmap.scaled(960, 441, Qt.KeepAspectRatio, Qt.SmoothTransformation) palette = QPalette() palette.setBrush(QPalette.Background, QBrush(pixmap)) self.setPalette(palette) else: pass def mouseMoveEvent(self, a0: QMouseEvent): self.setMouseTracking(True) if __name__ == "__main__": import ctypes # 解決任務欄ico無法顯示的問題 ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid") app = QApplication(sys.argv) form = App() form.setFixedSize(960, 441) form.setWindowIcon(QIcon('image/2021.ico')) form.show() sys.exit(app.exec_())