PamGram/model/wiki/weapons.py

211 lines
8.8 KiB
Python
Raw Normal View History

2022-07-26 10:07:31 +00:00
import os
from enum import Enum
from typing import Optional
import httpx
import ujson
from bs4 import BeautifulSoup
from .helpers import get_headers, get_id_form_url
class WeaponType(Enum):
Sword = "sword" # 单手剑
Claymore = "claymore" # 双手剑
PoleArm = "polearm" # 长柄武器
Bow = "bow" # 弓
Catalyst = "catalyst" # 法器
class Weapons:
IGNORE_WEAPONS_ID = [
"1001", "1101", "1406",
"2001", "2101", "2204", "2406", "2407",
"3001", "3101", "3204", "3404",
"4001", "4101", "4201", "4403", "4405", "4406",
"5001", "5101", "5201", "5404", "5404", "5405",
] # 忽略的武器包括一星、二星武器beta表格内无名武器未上架到正服的武器
# 根地址
ROOT_URL = "https://genshin.honeyhunterworld.com"
TEXT_MAPPING = {
"Type": "类型",
"Rarity": "Rarity",
"Base Attack": "基础攻击力"
}
WEAPON_TYPE_MAPPING = {
"Sword": "https://genshin.honeyhunterworld.com/img/skills/s_33101.png", # 单手剑
"Claymore": "https://genshin.honeyhunterworld.com/img/skills/s_163101.png", # 双手剑
"Polearm": "https://genshin.honeyhunterworld.com/img/skills/s_233101.png", # 长枪
"Bow": "https://genshin.honeyhunterworld.com/img/skills/s_213101.png", # 弓箭
"Catalyst": "https://genshin.honeyhunterworld.com/img/skills/s_43101.png", # 法器
}
def __init__(self):
self.client = httpx.AsyncClient(headers=get_headers())
project_path = os.path.dirname(__file__)
characters_file = os.path.join(project_path, "metadata", "ascension.json")
monster_file = os.path.join(project_path, "metadata", "monster.json")
elite_file = os.path.join(project_path, "metadata", "elite.json")
with open(characters_file, "r", encoding="utf-8") as f:
self._ascension_json: dict = ujson.load(f)
with open(monster_file, "r", encoding="utf-8") as f:
self._monster_json: dict = ujson.load(f)
with open(elite_file, "r", encoding="utf-8") as f:
self._elite_json: dict = ujson.load(f)
async def _get_soup(self, url: str) -> Optional[BeautifulSoup]:
request = await self.client.get(url)
return BeautifulSoup(request.text, "lxml")
async def get_weapon_url_list(self, weapon_type: WeaponType):
weapon_url_list = []
url = self.ROOT_URL + f"/db/weapon/{weapon_type.value}/?lang=CHS"
soup = await self._get_soup(url)
weapon_table = soup.find("span", {"class": "item_secondary_title"},
string="Released (Codex) Weapons").find_next_sibling()
weapon_table_rows = weapon_table.find_all("tr")
for weapon_table_row in weapon_table_rows:
content = weapon_table_row.find_all("td")[2]
if content.find("a") is not None:
weapon_url = self.ROOT_URL + content.find("a")["href"]
weapon_id = str(get_id_form_url(weapon_url))
if weapon_id not in self.IGNORE_WEAPONS_ID:
weapon_url_list.append(weapon_url)
return weapon_url_list
async def get_all_weapon_url(self):
all_weapon_url = []
temp_data = await self.get_weapon_url_list(WeaponType.Bow)
all_weapon_url.extend(temp_data)
temp_data = await self.get_weapon_url_list(WeaponType.Sword)
all_weapon_url.extend(temp_data)
temp_data = await self.get_weapon_url_list(WeaponType.PoleArm)
all_weapon_url.extend(temp_data)
temp_data = await self.get_weapon_url_list(WeaponType.Catalyst)
all_weapon_url.extend(temp_data)
temp_data = await self.get_weapon_url_list(WeaponType.Claymore)
all_weapon_url.extend(temp_data)
return all_weapon_url
@staticmethod
def get_weapon_info_template():
weapon_info_dict = {
"name": "",
"description": "",
"source_img": "",
"atk":
{
"min": 0,
"max": 999999,
"name": "基础攻击力"
},
"secondary":
{
"min": 0.1,
"max": 999999.9,
"name": ""
},
"star":
{
"value": -1,
"icon": ""
},
"type":
{
"name": "",
"icon": ""
},
"passive_ability":
{
"name": "",
"description": ""
}
}
materials_dict = {
"name": "",
"star": {
"value": 0,
"icon": ""
},
"city": "",
"icon": ""
}
weapon_info_dict["materials"] = {
"ascension": materials_dict,
"elite": materials_dict,
"monster": materials_dict,
}
return weapon_info_dict
async def get_weapon_info(self, url: str):
weapon_info_dict = self.get_weapon_info_template()
soup = await self._get_soup(url)
weapon_content = soup.find("div", {"class": "wrappercont"})
data = weapon_content.find("div", {"class": "data_cont_wrapper", "style": "display: block"})
weapon_info = data.find("table", {"class": "item_main_table"})
weapon_name = weapon_content.find("div", {"class": "custom_title"}).text.replace("-", "").replace(" ", "")
weapon_info_dict["name"] = weapon_name
weapon_info_row = weapon_info.find_all("tr")
for weapon_info_ in weapon_info_row:
content = weapon_info_.find_all("td")
if len(content) == 3: # 第一行会有三个td其中一个td是武器图片
weapon_info_dict["source_img"] = self.ROOT_URL + content[0].find("img",
{"class": "itempic lazy"})["data-src"]
weapon_info_dict["type"]["name"] = content[2].text
weapon_info_dict["type"]["icon"] = self.get_weapon_type(content[2].text)
elif len(content) == 2:
if content[0].text == "Rarity":
weapon_info_dict["star"]["value"] = len(
content[1].find_all("div", {"class": "sea_char_stars_wrap"}))
elif content[0].text == "Special (passive) Ability":
weapon_info_dict["passive_ability"]["name"] = content[1].text
elif content[0].text == "Special (passive) Ability Description":
weapon_info_dict["passive_ability"]["description"] = content[1].text
elif content[0].text == "In-game Description":
weapon_info_dict["description"] = content[1].text
elif content[0].text == "Secondary Stat":
weapon_info_dict["secondary"]["name"] = content[1].text
stat_table = data.find("span", {"class": "item_secondary_title"},
string=" Stat Progression ").find_next_sibling()
stat_table_row = stat_table.find_all("tr")
for stat_table_ in stat_table_row:
content = stat_table_.find_all("td")
# 通过等级判断
if content[0].text == "1":
weapon_info_dict["atk"]["min"] = int(content[1].text)
weapon_info_dict["secondary"]["min"] = float(content[2].text)
elif content[0].text == "80+":
item_hrefs = content[3].find_all("a")
for item_href in item_hrefs:
item_id = get_id_form_url(item_href["href"])
ascension = self.get_ascension(str(item_id))
if ascension.get("name") is not None:
weapon_info_dict["materials"]["ascension"] = ascension
monster = self.get_monster(str(item_id))
if monster.get("name") is not None:
weapon_info_dict["materials"]["monster"] = monster
elite = self.get_elite(str(item_id))
if elite.get("name") is not None:
weapon_info_dict["materials"]["elite"] = elite
elif content[0].text == "90":
weapon_info_dict["atk"]["max"] = int(content[1].text)
weapon_info_dict["secondary"]["max"] = float(content[2].text)
return weapon_info_dict
def get_ascension(self, item_id: str):
return self._ascension_json.get(item_id, {})
def get_monster(self, item_id: str):
return self._monster_json.get(item_id, {})
def get_elite(self, item_id: str):
return self._elite_json.get(item_id, {})
def get_weapon_type(self, weapon_type: str):
return self.WEAPON_TYPE_MAPPING.get(weapon_type, "")