117 lines
5.5 KiB
Python
117 lines
5.5 KiB
Python
import os
|
|
import random
|
|
import subprocess
|
|
|
|
from bs4 import BeautifulSoup
|
|
|
|
class SCP:
|
|
__ANUBIS = os.path.expanduser("~/.nix-profile/bin/anubis-fetch")
|
|
|
|
def __init__(self, num = None):
|
|
self.__scp = {
|
|
"title" : "SCP Foundation"
|
|
}
|
|
|
|
self_num = False
|
|
|
|
if num != None:
|
|
self_num = True
|
|
|
|
while self.__scp["title"] == "SCP Foundation":
|
|
if num == None:
|
|
num = random.randint(1, 4000)
|
|
|
|
url = ""
|
|
|
|
if num == 1:
|
|
self.__scp = {
|
|
"title" : "SCP-001",
|
|
"text" : "ПРИВЕДЁННЫЕ НИЖЕ МАТЕРИАЛЫ ЗАСЕКРЕЧЕНЫ\nПРИКАЗОМ АДМИНИСТРАТОРА\nСОВЕРШЕННО СЕКРЕТНО"
|
|
}
|
|
return
|
|
|
|
if num < 10:
|
|
url = f"https://scpfoundation.net/scp-00{num}"
|
|
elif num < 100:
|
|
url = f"https://scpfoundation.net/scp-0{num}"
|
|
else:
|
|
url = f"https://scpfoundation.net/scp-{num}"
|
|
|
|
print(url)
|
|
|
|
scp_html = self.__fetch_with_anubis(url)
|
|
self.__scp = self.__parse_html(scp_html)
|
|
|
|
if self_num:
|
|
break
|
|
else:
|
|
num = None
|
|
|
|
|
|
def get_text(self) -> str:
|
|
return f"{self.__scp["title"]}\n{self.__scp["text"]}"
|
|
|
|
@staticmethod
|
|
def get_classified() -> str:
|
|
return "Основные классы SCP:\n" \
|
|
"«Безопасный» — это аномалии, которые проще всего содержать без последствий.\n" \
|
|
"«Евклид» — относятся недостаточно изученные или изначально непредсказуемые аномалии, надёжное" \
|
|
"содержание которых не всегда возможно или требует бо́льших затрат, чем на содержание «безопасных».\n" \
|
|
"Вторичные классы:\n" \
|
|
"«Кетер» — это аномалии, постоянное или надёжное содержание которых тяжело реализуемо и сопряжено со сложными процедурами сдерживания.\n" \
|
|
"«Таумиэль» применяются Фондом исключительно для содержания других аномалий.\n" \
|
|
"«Аполлион» являются аномалиями, которые или невозможно содержать, и они неминуемо нарушат" \
|
|
"условия содержания, или предполагается развитие событий по схожему сценарию.\n" \
|
|
"«Архонт» являются аномалиями, чье содержание теоретически возможно, но по каким-либо причинам их лучше не содержать.\n" \
|
|
"«Тикондерога» невозможно содержать, но в этом и нет необходимости." \
|
|
"Эти аномалии схожи с объектами класса «Архонт» в том, что их содержание не обязательно," \
|
|
"но отличны тем, что на данный момент для их содержания у Фонда недостаточно ресурсов и " \
|
|
"компетенции из-за повсеместной распространённости таких аномалий по Земле." \
|
|
"При этом их существование или аномальная природа непостижимы для широких масс. "
|
|
|
|
def __fetch_with_anubis(self, url: str) -> str:
|
|
try:
|
|
result = subprocess.run(
|
|
[self.__ANUBIS, url],
|
|
capture_output = True, text = True, check = True
|
|
)
|
|
|
|
return result.stdout
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"anubis-fetch завершился с кодом {e.returncode}: {e.stderr}")
|
|
raise
|
|
except subprocess.TimeoutExpired:
|
|
print("anubis-fetch не успел завершиться за отведённое время")
|
|
raise
|
|
|
|
def __parse_html(self, text: str) -> dict:
|
|
soup = BeautifulSoup(text, "lxml")
|
|
|
|
for tag in soup(["script", "style", "nostyle"]):
|
|
tag.decompose()
|
|
|
|
content = soup.find(id = "page-content") or soup.find("div", id = "content")
|
|
|
|
parse_text = content.get_text("\n", strip = True) if content else None
|
|
|
|
if parse_text:
|
|
marker = "Класс объекта:"
|
|
indx = parse_text.find(marker)
|
|
if indx != -1:
|
|
parse_text = parse_text[indx:]
|
|
else:
|
|
marker = "Объект №:"
|
|
indx = parse_text.find(marker)
|
|
if indx != -1:
|
|
parse_text = parse_text[indx:]
|
|
|
|
marker = "«\n"
|
|
indx = parse_text.find(marker)
|
|
if indx != -1:
|
|
parse_text = parse_text[:indx]
|
|
|
|
return {
|
|
"title" : soup.title.string.strip() if soup.title else None,
|
|
#"heading" : content.find("h1").get_text(strip = True) if content and content.find("h1") else None,
|
|
"text" : parse_text
|
|
} |