telegraph_post.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import re
  2. from bs4 import BeautifulSoup as bs
  3. from telegraph import Telegraph, utils
  4. from addHTMLanchore import add_html_links
  5. from config import CHANNEL_PICTURE_URL, CHANNELS_NAME
  6. from tidylib import tidy_document
  7. from logger import logging
  8. def __get_image_width(img_el):
  9. """Проверяет ширину HTML элемента img и возвращает ее числовое значение в пикселях"""
  10. try:
  11. width = img_el['width']
  12. except KeyError:
  13. try:
  14. width = img_el['style'].split('width:')[1]
  15. except Exception:
  16. return 0
  17. return int(width.split('px')[0])
  18. def __get_main_image(soup) -> str:
  19. """Проверяет ширину всех изображений в новости и возвращает
  20. ссылку на первое подходящее, либо на заданное по умолчанию,
  21. если не нашлось подходящего"""
  22. images = [i['src']
  23. for i in soup.find_all('img') if __get_image_width(i) >= 200]
  24. if images:
  25. return images[0]
  26. else:
  27. return CHANNEL_PICTURE_URL
  28. def make_telegraph_post(title: str, url: str, html: str) -> dict:
  29. """Формирует телеграф пост из HTML и отправляет его. Возвращает резельтат отправки"""
  30. telegraph = Telegraph()
  31. telegraph.create_account(short_name='16108')
  32. soup = bs(html, 'html.parser')
  33. html_spec = str(soup)
  34. html_spec = add_html_links(html_spec)
  35. document, _ = tidy_document(html_spec, options={'numeric-entities':1})
  36. soup = bs(document, 'html.parser')
  37. html_spec = str(soup.body)
  38. # Обработка исходного HTML. Удаление неподходящих для телеграф тегов и замена
  39. html_spec = re.sub('<\/*body>', '', html_spec)
  40. html_spec = re.sub('<\/h\d>', '</h1><br />', html_spec, flags=re.IGNORECASE)
  41. html_spec = re.sub('h\d[^>]*>', 'strong>', html_spec, flags=re.IGNORECASE)
  42. html_spec = re.sub('<\/*table[^>]*>', '', html_spec, flags=re.IGNORECASE)
  43. html_spec = re.sub('<\/*tbody>', '', html_spec, flags=re.IGNORECASE)
  44. html_spec = re.sub('div[^>]*>', 'p>', html_spec, flags=re.IGNORECASE)
  45. html_spec = re.sub('article[^>]*>', 'p>', html_spec, flags=re.IGNORECASE)
  46. html_spec = re.sub('<\/*span[^>]*>', '', html_spec, flags=re.IGNORECASE)
  47. html_spec = re.sub('<\/*td>', '', html_spec, flags=re.IGNORECASE)
  48. html_spec = re.sub('tr>', 'p>', html_spec, flags=re.IGNORECASE)
  49. html_spec = re.sub('<\/*font[^>]*>', '', html_spec, flags=re.IGNORECASE)
  50. # Вставка заглавного изображения в верх поста и удаление его копии из основного HTML
  51. main_image = f'<img src="{__get_main_image(soup)}" alt="{title}">'
  52. html_spec = re.sub(
  53. f'<\/*img[^>]*{__get_main_image(soup)}[^>]*\/*>', '', html_spec, flags=re.IGNORECASE)
  54. html_spec = re.sub(
  55. f'<\/*img[^>]*thumbs_up.png[^>]*\/*>', '🙏', html_spec, flags=re.IGNORECASE)
  56. html_spec = main_image + html_spec
  57. # Специфическая функция для удаления лишнего текст в некоторых постах в канале 151
  58. html_spec = html_spec.replace('- >', '➡️ ')
  59. html_spec = html_spec.replace('- &gt;', '➡️ ')
  60. try:
  61. html_spec = '\n'.join(html_spec.split(
  62. 'Мы в социальных сетях')[0].split('\n')[:-1])
  63. except Exception:
  64. pass
  65. try:
  66. html_spec = '\n'.join(html_spec.split(
  67. 'Copyright ©')[0].split('\n')[:-1])
  68. except Exception:
  69. pass
  70. try:
  71. nodes = utils.html_to_nodes(html_spec)
  72. except Exception as e:
  73. logging.exception('Exception when html convert to node')
  74. if str(e).endswith("tag is not closed"):
  75. html = main_image
  76. for l in soup.body.get_text().split('\n'):
  77. if l.strip():
  78. l = l.replace('- >', '➡️ ')
  79. l = add_html_links(l)
  80. html += "<p>" + l + "</p>\n"
  81. else:
  82. raise e
  83. return telegraph.create_page(
  84. title,
  85. author_name=CHANNELS_NAME,
  86. author_url=url,
  87. html_content=html
  88. )
  89. return telegraph.create_page(
  90. title,
  91. author_name=CHANNELS_NAME,
  92. author_url=url,
  93. content=nodes
  94. )