Files
bot-news-linux-gaming/content_processor.py

204 lines
9.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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