204 lines
9.3 KiB
Python
204 lines
9.3 KiB
Python
#!/usr/bin/env python3
|
||
|
||
import re
|
||
import logging
|
||
import html2text
|
||
import urllib.parse
|
||
from bs4 import BeautifulSoup
|
||
|
||
|
||
class ContentProcessor:
|
||
def __init__(self):
|
||
self.logger = logging.getLogger(__name__)
|
||
|
||
def make_soup(self, response):
|
||
self.logger.debug("Создаем объект BeautifulSoup")
|
||
return BeautifulSoup(response.text, 'html.parser')
|
||
|
||
def html_to_text(self, html_content):
|
||
self.logger.debug(f"Конвертируем HTML в текст")
|
||
self.logger.debug(f"HTML на входе: {html_content}")
|
||
|
||
h = html2text.HTML2Text()
|
||
h.ignore_links = False
|
||
h.ignore_images = True
|
||
h.bypass_tables = True
|
||
h.reference_links = True
|
||
markdown_text = h.handle(html_content)
|
||
|
||
self.logger.debug(f"Текст до обработки регулярными выражениями: {markdown_text}")
|
||
|
||
# Удаление переносов строк из-за -
|
||
markdown_text = re.sub(r'-\s*\n\s*', '-', markdown_text, flags=re.DOTALL)
|
||
markdown_text = re.sub(r'-\s*\n*', '-', markdown_text, flags=re.DOTALL)
|
||
|
||
# Убираем переносы строк внутри круглых скобок ()
|
||
markdown_text = re.sub(r'\((.*?)\)', lambda x: '(' + x.group(1).replace('\n', ' ') + ')', markdown_text, flags=re.DOTALL)
|
||
|
||
# Убираем переносы строк внутри квадратных скобок []
|
||
markdown_text = re.sub(r'\[(.*?)\]', lambda x: '[' + x.group(1).replace('\n', ' ') + ']', markdown_text, flags=re.DOTALL)
|
||
|
||
# Удаление строк, содержащих '* * *'
|
||
markdown_text = re.sub(r'^.*\* \* \*.*$', '', markdown_text, flags=re.MULTILINE)
|
||
|
||
# Преобразование всех ссылок с параметрами URL
|
||
markdown_text = self.convert_links(markdown_text)
|
||
|
||
# Работа с #
|
||
patterns_to_remove = [
|
||
r'###',
|
||
r'##',
|
||
r'#',
|
||
r'\[scripts\]\(\/tag\/scripts\) version \d+ ',
|
||
r'##\[scripts\]\(\) version \d+ ',
|
||
r'\d{4}×\d{3} \d+ KB'
|
||
]
|
||
for pattern in patterns_to_remove:
|
||
markdown_text = re.sub(pattern, '', markdown_text)
|
||
|
||
# Удаление избыточных пустых строк после удаления строк
|
||
markdown_text = re.sub(r'\n\s*\n', '\n', markdown_text)
|
||
|
||
# Замена текстов типа "image1280×474 99.7 KB", "807×454 64.1 KB" на "."
|
||
markdown_text = re.sub(r'image\d+×\d+\s+\d+(\.\d+)?\s+KB', '.', markdown_text)
|
||
markdown_text = re.sub(r'\d+×\d+\s+\d+(\.\d+)?\s+KB', '.', markdown_text)
|
||
|
||
# Изменение ссылок без описания
|
||
markdown_text = re.sub(r'\[\]\((https:\/\/[^\)]+)\)', r'[.](\1)', markdown_text)
|
||
markdown_text = re.sub(r'\[\s]\((https:\/\/[^\)]+)\)', r'[.](\1)', markdown_text)
|
||
|
||
# Удаление дублирующихся ссылок
|
||
markdown_text = self.remove_duplicate_links(markdown_text)
|
||
|
||
# Удаление лишних отступов для строк, начинающихся с '*'
|
||
markdown_text = re.sub(r' \*', r'*', markdown_text)
|
||
|
||
# Перемещение ссылки на изображение в конец последней строки
|
||
image_link = "[.](https://linux-gaming.ru/uploads/default/original/1X/5cfa59077a5275971401fab0114e56f3ffdd0ec4.png)"
|
||
if image_link in markdown_text:
|
||
markdown_text = markdown_text.replace(image_link, '')
|
||
markdown_text = markdown_text + image_link
|
||
|
||
self.logger.debug(f"Текст после обработки: {markdown_text}")
|
||
return markdown_text
|
||
|
||
def convert_links(self, text):
|
||
self.logger.debug("Конвертируем ссылки")
|
||
url_pattern = re.compile(r'https?://[^\s\)]+')
|
||
url_pattern = url_pattern.sub(lambda match: self.decode_url_params(match.group(0)), text)
|
||
self.logger.debug(f"Результат конвертации ссылок: {url_pattern}")
|
||
return url_pattern
|
||
|
||
def decode_url_params(self, url):
|
||
self.logger.debug(f"Декодируем URL параметры: {url}")
|
||
parsed_url = urllib.parse.urlparse(url)
|
||
query_params = urllib.parse.parse_qs(parsed_url.query)
|
||
for key, values in query_params.items():
|
||
if key.lower() == 'to' and values:
|
||
return urllib.parse.unquote(values[0])
|
||
self.logger.debug(f"Возвращаем URL: {url}")
|
||
return url
|
||
|
||
def remove_empty_lines(self, text_data):
|
||
self.logger.debug("Удаляем пустые строки")
|
||
lines = text_data.splitlines()
|
||
non_empty_lines = [line for line in lines if line.strip()]
|
||
non_empty_lines = '\n'.join(non_empty_lines)
|
||
self.logger.debug(f"Результат удаления пустых строк: {non_empty_lines}")
|
||
return non_empty_lines
|
||
|
||
def remove_markdown_links(self, markdown_text):
|
||
self.logger.debug("Удаляем markdown ссылки")
|
||
markdown_text = re.sub(r'\[.*?\]\((https?://.*?)\)', r'\1', markdown_text)
|
||
self.logger.debug(f"Результат удаления markdown ссылок: {markdown_text}")
|
||
return markdown_text
|
||
|
||
def remove_duplicate_links(self, text):
|
||
self.logger.debug("Удаляем дубликаты ссылок")
|
||
seen_links = set()
|
||
|
||
def replace_link(match):
|
||
link = match.group(2)
|
||
if link in seen_links:
|
||
return ''
|
||
seen_links.add(link)
|
||
return match.group(0)
|
||
|
||
link_pattern = re.compile(r'(\[.*?\]\((https:\/\/.*?)\))')
|
||
text = re.sub(link_pattern, replace_link, text)
|
||
self.logger.debug(f"Результат удаления дубликатов ссылок: {text}")
|
||
return text
|
||
|
||
def extract_links(self, text):
|
||
self.logger.debug("Извлекаем ссылки из текста")
|
||
# Улучшенное регулярное выражение, исключающее конечные знаки препинания
|
||
url_pattern = re.compile(r'https?://[^\s\)\]\}\>,;]+')
|
||
links = url_pattern.findall(text)
|
||
# Дополнительная очистка: убираем точки и запятые в конце
|
||
cleaned_links = []
|
||
for link in links:
|
||
link = link.rstrip('.,!?')
|
||
cleaned_links.append(link)
|
||
self.logger.debug(f"Найденные ссылки: {cleaned_links}")
|
||
return cleaned_links
|
||
|
||
def format_for_vk(self, content):
|
||
"""Форматирование контента для VK"""
|
||
self.logger.debug("Форматируем контент для VK")
|
||
|
||
# Замена маркеров списка
|
||
content = re.sub(r'\* ', '•', content)
|
||
content = re.sub(r' •', '➜', content)
|
||
content = re.sub(r' •', '➜', content)
|
||
|
||
# Удаление markdown ссылок
|
||
content = self.remove_markdown_links(content)
|
||
|
||
# Замена изображения
|
||
content = re.sub(
|
||
r'https://linux-gaming.ru/uploads/default/original/1X/5cfa59077a5275971401fab0114e56f3ffdd0ec4.png',
|
||
'\n',
|
||
content,
|
||
flags=re.DOTALL
|
||
)
|
||
|
||
return content
|
||
|
||
def format_for_telegram(self, content):
|
||
"""Форматирование контента для Telegram"""
|
||
self.logger.debug("Форматируем контент для Telegram")
|
||
return content # Telegram поддерживает markdown
|
||
|
||
def create_script_content(self, script_ver, next_version, response):
|
||
"""Создание контента для обновления скрипта"""
|
||
self.logger.debug(f"Создаем контент для версии скрипта {script_ver}")
|
||
soup = self.make_soup(response)
|
||
page_text = str(soup)
|
||
page_text = page_text.replace("Вы можете помочь развитию проекта: https://linux-gaming.ru/donate/", '')
|
||
|
||
last_text = f"###Scripts version {next_version}### / stable"
|
||
index_last_text = page_text.find(last_text)
|
||
|
||
if index_last_text != -1:
|
||
changelog_text_last = page_text[:index_last_text]
|
||
prev_text = f"###Scripts version {script_ver}### / stable"
|
||
index_script_ver = changelog_text_last.find(prev_text)
|
||
changelog_text = changelog_text_last[index_script_ver:]
|
||
|
||
changelog_text = re.sub(
|
||
r'###Scripts version (\d+)### / Дата: (\d{2}\.\d{2}\.\d{4}) / Размер скачиваемого обновления: \d+ \S+',
|
||
r'\1 - \2' + ":",
|
||
changelog_text
|
||
)
|
||
changelog_text = re.sub(
|
||
r'###Scripts version (\d+)### / stable / Дата: (\d{2}\.\d{2}\.\d{4}) / Размер скачиваемого обновления: \d+ \S+',
|
||
r'\1 - \2' + ":",
|
||
changelog_text
|
||
)
|
||
|
||
post_text = "-----------------------------\n" + changelog_text
|
||
|
||
self.logger.debug(f"Возвращаем post_text: {post_text}")
|
||
return post_text
|
||
|
||
return None |