利用Python制作王者戰力查詢以及皮膚查看軟件


 

根據下面的提供的王者榮耀最低戰力查詢的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_())

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM