mirror of
https://github.com/PaiGramTeam/PaiGram.git
synced 2024-12-01 11:41:59 +00:00
190 lines
8.9 KiB
Python
190 lines
8.9 KiB
Python
|
import re
|
||
|
from typing import Optional
|
||
|
|
||
|
import httpx
|
||
|
from bs4 import BeautifulSoup
|
||
|
|
||
|
from .helpers import get_headers
|
||
|
|
||
|
|
||
|
class Characters:
|
||
|
CHARACTERS_LIST_URL = "https://genshin.honeyhunterworld.com/db/char/characters/?lang=CHS"
|
||
|
ROOT_URL = "https://genshin.honeyhunterworld.com"
|
||
|
|
||
|
def __init__(self):
|
||
|
self.client = httpx.AsyncClient(headers=get_headers())
|
||
|
|
||
|
async def _get_soup(self, url: str) -> Optional[BeautifulSoup]:
|
||
|
request = await self.client.get(url)
|
||
|
return BeautifulSoup(request.text, "lxml")
|
||
|
|
||
|
async def get_all_characters_url(self):
|
||
|
url_list = []
|
||
|
soup = await self._get_soup(self.CHARACTERS_LIST_URL)
|
||
|
character_list = soup.find_all('div', {'class': 'char_sea_cont'})
|
||
|
for character in character_list:
|
||
|
name = character.find("span", {"class": "sea_charname"}).text
|
||
|
if "旅行者" in name:
|
||
|
continue
|
||
|
character_link = self.ROOT_URL + character.a['href']
|
||
|
url_list.append(character_link)
|
||
|
return url_list
|
||
|
|
||
|
def get_characters_info_template(self):
|
||
|
characters_info_dict = {
|
||
|
"name": "",
|
||
|
"title": "",
|
||
|
"rarity": 0,
|
||
|
"element": {"name": "", "icon": ""},
|
||
|
"description": "",
|
||
|
"constellations": {},
|
||
|
"skills": {
|
||
|
"normal_attack": self.get_skills_info_template(),
|
||
|
"skill_e": self.get_skills_info_template(),
|
||
|
"skill_q": self.get_skills_info_template(),
|
||
|
"skill_replace": self.get_skills_info_template(),
|
||
|
},
|
||
|
"gacha_splash": ""
|
||
|
}
|
||
|
return characters_info_dict
|
||
|
|
||
|
@staticmethod
|
||
|
def get_skills_info_template():
|
||
|
skills_info_dict = {
|
||
|
"icon": "",
|
||
|
"name": "",
|
||
|
"description": ""
|
||
|
}
|
||
|
return skills_info_dict
|
||
|
|
||
|
async def get_characters(self, url: str):
|
||
|
characters_info_dict = self.get_characters_info_template()
|
||
|
soup = await self._get_soup(url)
|
||
|
main_content = soup.find("div", {'class': 'wrappercont'})
|
||
|
char_name = main_content.find('div', {'class': 'custom_title'}).text
|
||
|
characters_info_dict["name"] = char_name
|
||
|
# 基础信息
|
||
|
char_info_table = main_content.find('table', {'class': 'item_main_table'}).find_all('tr')
|
||
|
for char_info_item in char_info_table:
|
||
|
content = char_info_item.find_all('td')
|
||
|
if content[0].text == "Title":
|
||
|
char_title = content[1].text
|
||
|
characters_info_dict["title"] = char_title
|
||
|
if content[0].text == "Allegiance":
|
||
|
char_allegiance = content[1].text
|
||
|
characters_info_dict["allegiance"] = char_allegiance
|
||
|
if content[0].text == "Rarity":
|
||
|
char_rarity = len(content[1].find_all('div', {'class': 'sea_char_stars_wrap'}))
|
||
|
characters_info_dict["rarity"] = char_rarity
|
||
|
if content[0].text == "Element":
|
||
|
char_element_icon_url = self.ROOT_URL + content[1].find('img')['data-src'].replace("_35", "")
|
||
|
characters_info_dict["element"]["icon"] = char_element_icon_url
|
||
|
if content[0].text == "Astrolabe Name":
|
||
|
char_astrolabe_name = content[1].text
|
||
|
if content[0].text == "In-game Description":
|
||
|
char_description = content[1].text
|
||
|
characters_info_dict["description"] = char_description
|
||
|
|
||
|
# 角色属性表格 咕咕咕
|
||
|
skill_dmg_wrapper = main_content.find('div', {'class': 'skilldmgwrapper'}).find_all('tr')
|
||
|
|
||
|
# 命之座
|
||
|
constellations_title = main_content.find('span', {'class': 'item_secondary_title'}, string="Constellations")
|
||
|
constellations_table = constellations_title.findNext('table', {'class': 'item_main_table'}).find_all('tr')
|
||
|
constellations_list = []
|
||
|
constellations_list_index = 0
|
||
|
for index, value in enumerate(constellations_table):
|
||
|
# 判断第一行
|
||
|
if index % 2 == 0:
|
||
|
constellations_dict = {
|
||
|
"icon": "",
|
||
|
"name": "",
|
||
|
"description": ""
|
||
|
}
|
||
|
constellations_list.append(constellations_dict)
|
||
|
icon_url = self.ROOT_URL + value.find_all('img', {'class': 'itempic'})[-1]['data-src']
|
||
|
constellations_name = value.find_all('a', href=re.compile("/db/skill"))[-1].text
|
||
|
constellations_list[constellations_list_index]["icon"] = icon_url
|
||
|
constellations_list[constellations_list_index]["name"] = constellations_name
|
||
|
if index % 2 == 1:
|
||
|
constellations_description = value.find('div', {'class': 'skill_desc_layout'}).text
|
||
|
constellations_list[constellations_list_index]["description"] = constellations_description
|
||
|
constellations_list_index += 1
|
||
|
|
||
|
characters_info_dict["constellations"] = constellations_list
|
||
|
|
||
|
# 技能
|
||
|
skills_title = main_content.find('span', string='Attack Talents')
|
||
|
|
||
|
# 普攻
|
||
|
normal_attack_area = skills_title.find_next_sibling()
|
||
|
normal_attack_info = normal_attack_area.find_all('tr')
|
||
|
normal_attack_icon = self.ROOT_URL + normal_attack_info[0].find('img', {'class': 'itempic'})['data-src']
|
||
|
normal_attack_name = normal_attack_info[0].find('a', href=re.compile('/db/skill/')).text
|
||
|
normal_attack_desc = normal_attack_info[1].find('div', {'class': 'skill_desc_layout'}).text.replace(" ", "\n")
|
||
|
normal_attack = characters_info_dict["skills"]["normal_attack"]
|
||
|
normal_attack["icon"] = normal_attack_icon
|
||
|
normal_attack["name"] = normal_attack_name
|
||
|
normal_attack["description"] = normal_attack_desc
|
||
|
|
||
|
normal_attack_table_area = normal_attack_area.find_next_sibling()
|
||
|
# normal_attack_table = normal_attack_table_area.find_all('tr')
|
||
|
|
||
|
skill_e_area = normal_attack_table_area.find_next_sibling()
|
||
|
skill_e_info = skill_e_area.find_all('tr')
|
||
|
skill_e_icon = self.ROOT_URL + skill_e_info[0].find('img', {'class': 'itempic'})['data-src']
|
||
|
skill_e_name = skill_e_info[0].find('a', href=re.compile('/db/skill/')).text
|
||
|
skill_e_desc = skill_e_info[1].find('div', {'class': 'skill_desc_layout'}).text.replace(" ", "\n")
|
||
|
skill_e = characters_info_dict["skills"]["skill_e"]
|
||
|
skill_e["icon"] = skill_e_icon
|
||
|
skill_e["name"] = skill_e_name
|
||
|
skill_e["description"] = skill_e_desc
|
||
|
|
||
|
skill_e_table_area = skill_e_area.find_next_sibling()
|
||
|
# skillE_table = skillE_table_area.find_all('tr')
|
||
|
|
||
|
load_another_talent_q: bool = False
|
||
|
if char_name in ("神里绫华", "莫娜"):
|
||
|
load_another_talent_q = True
|
||
|
|
||
|
skill_q_area = skill_e_table_area.find_next_sibling()
|
||
|
skill_q_info = skill_q_area.find_all('tr')
|
||
|
skill_q_icon = self.ROOT_URL + skill_q_info[0].find('img', {'class': 'itempic'})['data-src']
|
||
|
skill_q_name = skill_q_info[0].find('a', href=re.compile('/db/skill/')).text
|
||
|
skill_q_desc = skill_q_info[1].find('div', {'class': 'skill_desc_layout'}).text.replace(" ", "\n")
|
||
|
skill_q_table_area = skill_q_area.find_next_sibling()
|
||
|
# skill_q_table = skill_q_table_area.find_all('tr')
|
||
|
|
||
|
if load_another_talent_q:
|
||
|
skill_replace = characters_info_dict["skills"]["skill_replace"]
|
||
|
skill_replace["icon"] = skill_q_icon
|
||
|
skill_replace["name"] = skill_q_name
|
||
|
skill_replace["description"] = skill_q_desc
|
||
|
else:
|
||
|
skill_q = characters_info_dict["skills"]["skill_q"]
|
||
|
skill_q["icon"] = skill_q_icon
|
||
|
skill_q["name"] = skill_q_name
|
||
|
skill_q["description"] = skill_q_desc
|
||
|
|
||
|
if load_another_talent_q:
|
||
|
skill_q2_area = skill_q_table_area.find_next_sibling()
|
||
|
skill_q2_info = skill_q2_area.find_all('tr')
|
||
|
skill_q2_icon = self.ROOT_URL + skill_q2_info[0].find('img', {'class': 'itempic'})['data-src']
|
||
|
skill_q2_name = skill_q2_info[0].find('a', href=re.compile('/db/skill/')).text
|
||
|
skill_q2_desc = skill_q2_info[1].find('div', {'class': 'skill_desc_layout'}).text.replace(" ", "\n")
|
||
|
skill_q2 = characters_info_dict["skills"]["skill_q"]
|
||
|
skill_q2["icon"] = skill_q2_icon
|
||
|
skill_q2["name"] = skill_q2_name
|
||
|
skill_q2["description"] = skill_q2_desc
|
||
|
|
||
|
# 角色图片
|
||
|
char_pic_area = main_content.find('span', string='Character Gallery').find_next_sibling()
|
||
|
all_char_pic = char_pic_area.find("div", {"class": "gallery_cont"})
|
||
|
|
||
|
gacha_splash_text = all_char_pic.find("span", {"class": "gallery_cont_span"}, string="Gacha Splash")
|
||
|
gacha_splash_pic_url = self.ROOT_URL + gacha_splash_text.previous_element.previous_element["data-src"].replace(
|
||
|
"_70", "")
|
||
|
characters_info_dict["gacha_splash"] = gacha_splash_pic_url
|
||
|
|
||
|
return characters_info_dict
|