123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import re
- from bs4 import BeautifulSoup as bs
- from telegraph import Telegraph, utils
- from config import CHANNEL_PICTURE_URL, CHANNELS_NAME
- from tidylib import tidy_document
- from logger import logging
- def __get_image_width(img_el):
- """Проверяет ширину HTML элемента img и возвращает ее числовое значение в пикселях"""
- try:
- width = img_el['width']
- except KeyError:
- try:
- width = img_el['style'].split('width:')[1]
- except Exception:
- return 0
- return int(width.split('px')[0])
- def __add_html_links(html: str) -> str:
- """
- Если в коде есть ссылки просто текстом, без хтмл элемента а, то функция
- заменит их все на полноценный html тэг с нужным атрибутом href
- """
- links = []
- for p in html.strip().split('http'):
- if 'assets' not in p and 'a>' not in p and (p.startswith('://') \
- or p.startswith('s://')):
- p = p.split('\n')
- links.append('http' + p[0])
- for l in links:
- link = ' '.join(l.split()) # убираем символы другой кодировки, которые
- # не убираются по-другому
- a_elem = f'<a href="{link}">{link}</a>'.replace(" </p>", "").replace("</p>", "")
- html = html.replace(l, a_elem)
- return html
- def __get_main_image(soup) -> str:
- """Проверяет ширину всех изображений в новости и возвращает
- ссылку на первое подходящее, либо на заданное по умолчанию,
- если не нашлось подходящего"""
- images = [i['src']
- for i in soup.find_all('img') if __get_image_width(i) >= 200]
- if images:
- return images[0]
- else:
- return CHANNEL_PICTURE_URL
- def make_telegraph_post(title: str, url: str, html: str) -> dict:
- """Формирует телеграф пост из HTML и отправляет его. Возвращает резельтат отправки"""
- telegraph = Telegraph()
- telegraph.create_account(short_name='16108')
-
- soup = bs(html, 'html.parser')
-
- html_spec = str(soup)
- html_spec = __add_html_links(html_spec)
- document, errors = tidy_document(html_spec, options={'numeric-entities':1})
- soup = bs(document, 'html.parser')
- html_spec = str(soup.body)
- # Обработка исходного HTML. Удаление неподходящих для телеграф тегов и замена
- html_spec = re.sub('<\/*body>', '', html_spec)
- html_spec = re.sub('<\/h\d>', '</h1><br />', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('h\d[^>]*>', 'strong>', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('<\/*table[^>]*>', '', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('<\/*tbody>', '', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('div[^>]*>', 'p>', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('article[^>]*>', 'p>', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('<\/*span[^>]*>', '', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('<\/*td>', '', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('tr>', 'p>', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub('<\/*font[^>]*>', '', html_spec, flags=re.IGNORECASE)
- # Вставка заглавного изображения в верх поста и удаление его копии из основного HTML
- main_image = f'<img src="{__get_main_image(soup)}" alt="{title}">'
- html_spec = re.sub(
- f'<\/*img[^>]*{__get_main_image(soup)}[^>]*\/*>', '', html_spec, flags=re.IGNORECASE)
- html_spec = re.sub(
- f'<\/*img[^>]*thumbs_up.png[^>]*\/*>', '🙏', html_spec, flags=re.IGNORECASE)
- html_spec = main_image + html_spec
- # Специфическая функция для удаления лишнего текст в некоторых постах в канале 151
- html_spec = html_spec.replace('- >', '➡️ ')
- html_spec = html_spec.replace('- >', '➡️ ')
- try:
- html_spec = '\n'.join(html_spec.split(
- 'Мы в социальных сетях')[0].split('\n')[:-1])
- except Exception:
- pass
-
- try:
- html_spec = '\n'.join(html_spec.split(
- 'Copyright ©')[0].split('\n')[:-1])
- except Exception:
- pass
- try:
- nodes = utils.html_to_nodes(html_spec)
- except Exception as e:
- logging.exception('Exception when html convert to node')
- if str(e).endswith("tag is not closed"):
- html = main_image
- for l in soup.body.get_text().split('\n'):
- if l.strip():
- l = l.replace('- >', '➡️ ')
- l = __add_html_links(l)
- html += "<p>" + l + "</p>\n"
- else:
- raise e
- return telegraph.create_page(
- title,
- author_name=CHANNELS_NAME,
- author_url=url,
- html_content=html
- )
- return telegraph.create_page(
- title,
- author_name=CHANNELS_NAME,
- author_url=url,
- content=nodes
- )
|