2023-06-11 02:40:09 +00:00
|
|
|
|
import re
|
2023-06-22 06:34:26 +00:00
|
|
|
|
from pytz import timezone
|
2023-06-10 14:20:58 +00:00
|
|
|
|
from datetime import datetime
|
|
|
|
|
from typing import List
|
|
|
|
|
|
|
|
|
|
from httpx import get
|
|
|
|
|
from bs4 import BeautifulSoup, Tag
|
|
|
|
|
from .code import Code, Reward
|
|
|
|
|
|
|
|
|
|
|
2023-07-05 03:17:18 +00:00
|
|
|
|
url = "https://honkai.gg/codes/"
|
2023-06-10 14:20:58 +00:00
|
|
|
|
reward_map = {
|
|
|
|
|
"Stellar Jade": "星琼",
|
|
|
|
|
"Credit": "信用点",
|
|
|
|
|
"Credits": "信用点",
|
|
|
|
|
"Traveler's Guide": "漫游指南",
|
2023-07-05 03:17:18 +00:00
|
|
|
|
"Traveler’s Guide": "漫游指南",
|
2023-06-10 14:20:58 +00:00
|
|
|
|
"Refined Aether": "提纯以太",
|
|
|
|
|
"Adventure Log": "冒险记录",
|
|
|
|
|
"Dust of Alacrity": "疾速粉尘",
|
|
|
|
|
"Condensed Aether": "凝缩以太",
|
|
|
|
|
"Cosmic Fried Rice": "大宇宙炒饭",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_reward(reward: List[str]) -> Reward:
|
|
|
|
|
try:
|
|
|
|
|
name = reward_map.get(reward[0])
|
|
|
|
|
if not name:
|
2023-06-11 02:40:09 +00:00
|
|
|
|
# 判断是否为中文
|
|
|
|
|
if not re.search("[\u4e00-\u9fa5]", reward[0]):
|
|
|
|
|
print("Unknown reward: ", reward[0])
|
2023-06-10 14:20:58 +00:00
|
|
|
|
name = reward[0]
|
|
|
|
|
return Reward(
|
|
|
|
|
name=name,
|
|
|
|
|
cnt=int(reward[1]),
|
|
|
|
|
)
|
2023-06-11 02:40:09 +00:00
|
|
|
|
except Exception as e:
|
2023-06-10 14:20:58 +00:00
|
|
|
|
print("Bad reward data: ", reward)
|
2023-06-11 02:40:09 +00:00
|
|
|
|
raise e
|
2023-06-10 14:20:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_code(tr: Tag) -> Code:
|
|
|
|
|
tds = tr.find_all("td")
|
|
|
|
|
code = tds[0].text.strip()
|
2023-07-05 03:17:18 +00:00
|
|
|
|
try:
|
|
|
|
|
expire = tds[2].text.strip()
|
|
|
|
|
except IndexError:
|
|
|
|
|
expire = datetime(1970, 1, 1, 1, 0, 0, 0)
|
|
|
|
|
if isinstance(expire, str):
|
|
|
|
|
if expire.endswith("?"):
|
|
|
|
|
expire = datetime(2099, 12, 31, 23, 59, 59, 999999)
|
|
|
|
|
else:
|
|
|
|
|
expires = expire.split(" – ")
|
|
|
|
|
day = expires[1].split(" ")[-1]
|
|
|
|
|
month = expires[0].split(" ")[0]
|
|
|
|
|
try:
|
|
|
|
|
if " " not in expires[1]:
|
|
|
|
|
raise ValueError
|
|
|
|
|
month = expires[1].split(" ")[0]
|
|
|
|
|
except ValueError:
|
|
|
|
|
pass
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
expire = datetime.strptime(f"{day} {month}", "%d %b")
|
|
|
|
|
expire = expire.replace(year=now.year, hour=23, minute=59, second=59, microsecond=999999)
|
2023-06-22 06:34:26 +00:00
|
|
|
|
expire = timezone("Asia/Shanghai").localize(expire)
|
2023-06-10 14:20:58 +00:00
|
|
|
|
expire = int(expire.timestamp() * 1000)
|
|
|
|
|
rewards = []
|
2023-07-05 03:17:18 +00:00
|
|
|
|
for reward in str(tds[1]).split("<br/>"):
|
|
|
|
|
reward = BeautifulSoup(reward, "lxml")
|
|
|
|
|
reward_div = " ".join(reward.text.strip().split()).split(" x ")
|
2023-06-11 02:40:09 +00:00
|
|
|
|
if len(reward_div) < 2:
|
|
|
|
|
print("Bad td data: ", tds[1])
|
|
|
|
|
continue
|
2023-06-10 14:20:58 +00:00
|
|
|
|
parsed_reward = parse_reward(reward_div)
|
|
|
|
|
if parsed_reward:
|
|
|
|
|
rewards.append(parsed_reward)
|
2023-06-11 02:40:09 +00:00
|
|
|
|
if not rewards:
|
|
|
|
|
for reward in tds[1].find_all("a"):
|
|
|
|
|
reward_a = reward.text.strip().split(" x ")
|
|
|
|
|
if len(reward_a) < 2:
|
|
|
|
|
print("Bad a data: ", tds[1])
|
|
|
|
|
continue
|
|
|
|
|
parsed_reward = parse_reward(reward_a)
|
|
|
|
|
if parsed_reward:
|
|
|
|
|
rewards.append(parsed_reward)
|
2023-06-10 14:20:58 +00:00
|
|
|
|
return Code(code=code, reward=rewards, expire=expire)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_code():
|
|
|
|
|
html = get(url).text
|
|
|
|
|
soup = BeautifulSoup(html, "lxml")
|
|
|
|
|
tables = soup.find_all("table")
|
|
|
|
|
codes = []
|
|
|
|
|
for table in tables:
|
|
|
|
|
trs = table.find_all("tr")[1:]
|
|
|
|
|
for tr in trs:
|
|
|
|
|
codes.append(parse_code(tr))
|
|
|
|
|
codes.sort(key=lambda x: x.expire, reverse=True)
|
|
|
|
|
return codes
|