利用Python制作王者战力查询以及皮肤查看软件

Posted python可乐编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用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_())

 

以上是关于利用Python制作王者战力查询以及皮肤查看软件的主要内容,如果未能解决你的问题,请参考以下文章

王者荣耀最低战力查询-王者战区修改

王者荣耀英雄战力 最低战区查询

Python爬取王者荣耀官网,实现一对一下载软件!

利用Python制作王者荣耀出装小助手,引来了老板的注意!

Python爬虫实战,requests模块,Python实现抓取王者荣耀全套皮肤

20行Python代码爬取王者荣耀全英雄皮肤