Парсинг сайта и перевод текста

Рейтинг: 2Ответов: 1Опубликовано: 16.07.2023

Столкнулся с такой задачей:
Необходимо спарсить сайт и перевести полученный текст на русский язык, с сохранением структуры текста

Вот HTML, который нужно спарсить:

<div>
   <style data-emotion="css gy2lsd">
      .css-gy2lsd{
         margin:0;
         font-family:'DM Sans',sans-serif;
         font-weight:400;
         font-size:1rem;
         line-height:1.5;
         margin:15px 0;
      }
   </style>
   <p class="MuiTypography-root MuiTypography-body1 css-gy2lsd">
      <strong>Nexus </strong>is the pioneering AI-powered navigator <em>designed to assist users</em> in effectively navigating their entire network.
   </p>
   <p class="MuiTypography-root MuiTypography-body1 css-gy2lsd">
      <strong>Key Features:</strong>
   </p>
   <style data-emotion="css 196imzh">
      .css-196imzh{
         list-style:none;
         margin:0;
         padding:0;
         position:relative;
         padding-top:8px;
         padding-bottom:8px;
         list-style-type:disc;
         padding-left:16px;
      }
      
      .css-196imzh .MuiListItem-root{
         display:-webkit-box;
         display:-webkit-list-item;
         display:-ms-list-itembox;
         display:list-item;
         }
      </style>
   <ul class="MuiList-root MuiList-padding css-196imzh">=
      <li class="MuiListItem-root MuiListItem-gutters MuiListItem-padding css-1uxc9es">
         <style data-emotion="css 1tsvksn">.css-1tsvksn{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;min-width:0;margin-top:4px;margin-bottom:4px;}</style>
         <div class="MuiListItemText-root css-1tsvksn">
            <style data-emotion="css iwjgli">.css-iwjgli{margin:0;font-family:'DM Sans',sans-serif;font-weight:400;font-size:1rem;line-height:1.5;display:block;}</style>
            <span class="MuiTypography-root MuiTypography-body1 MuiListItemText-primary css-iwjgli"><strong>AI-powered network navigation:</strong> Leverage cutting-edge AI technology to effectively navigate your entire network.</span>
         </div>
      </li>
      <li class="MuiListItem-root MuiListItem-gutters MuiListItem-padding css-1uxc9es">
         <div class="MuiListItemText-root css-1tsvksn"><span class="MuiTypography-root MuiTypography-body1 MuiListItemText-primary css-iwjgli"><strong>Comprehensive relationship context:</strong> Access contextual knowledge about your connections to facilitate smoother interactions.</span></div>
      </li>
      <li class="MuiListItem-root MuiListItem-gutters MuiListItem-padding css-1uxc9es">
         <div class="MuiListItemText-root css-1tsvksn"><span class="MuiTypography-root MuiTypography-body1 MuiListItemText-primary css-iwjgli"><strong>Assistance with various networking tasks: </strong>Seek help from Nexus for reasons to reconnect, outreach email ideas, and personalized gift recommendations.</span></div>
      </li>
   </ul>
   <p class="MuiTypography-root MuiTypography-body1 css-gy2lsd"><strong>Use Cases:</strong></p>
   <p class="MuiTypography-root MuiTypography-body1 css-gy2lsd"><strong>• Strengthening client relationships:</strong> Deepen your connections with key clients using Nexus's insights and guidance.</p>
   <p class="MuiTypography-root MuiTypography-body1 css-gy2lsd"><strong>• Managing stakeholder relationships:</strong> Effectively handle multiple stakeholders with Nexus's support and recommendations.</p>
   <p class="MuiTypography-root MuiTypography-body1 css-gy2lsd"><strong>• Enhancing networking efficiency: </strong>Save time and improve networking outcomes by leveraging Nexus's comprehensive understanding of your network.</p>
   <p class="MuiTypography-root MuiTypography-body1 css-gy2lsd">Experience the future of networking today with Nexus, the first AI navigator for your entire network.</p>
</div>

Спарсить его не проблема, она заключается в переводе. main.py

from bs4 import BeautifulSoup
from googletrans import Translator

def get_soup(url):
    # Запрос на сайт
    q = requests.get(url)
    result = q.content
    # Экземпляр модуля bs4
    soup = BeautifulSoup(result, 'lxml')

    return soup

def translate_string(string) -> str:
    translator = Translator()
    translation = translator.translate(string, dest='ru')
    return translation.text

def main():
    soup = get_soup('https;//123')
    response = soup.select('div.MuiBox-root.css-0 div')
    text = ''
    text += translate_string(str(i)) for i in response[0]

Нужно сделать так, чтобы при переводе строки не переводились теги, сейчас это выглядит +- вот так:

<данные стилей -emotion="css 196imzh">.css-196imzh{стиль-списка:нет;маржа:0;отступ:0;позиция:относительная;отступ-сверху:8px;отступ-снизу:8px;тип-стиля-списка:диск ;padding-left:16px;}.css-196imzh .MuiListItem-root{display:-webkit-box;display:-webkit-list-item;display:-ms-list-itembox;display:list-item;}< /style>

Т. е. нужно сделать перевод только текста, не тегов. Пытался реализовать вот так, но мои попытки были тщётными:

    for i in response[0]:
        line = str(i)
        text_in_line = i.get_text()
        translated = transkate_string(i.get_text())
        line = line.replace(text_in_line, translated)
        text += line

Так как text_in_line - это просто текст, без тегов по типу <strong>, и из-за этого replace ничего не менял.
Подскажите, пожалуйста, как это можно реализовать?

Ответы

▲ 2Принят

Можно пройтись по всем элементам содержащим текст и перевести:

from bs4 import BeautifulSoup, Comment
from googletrans import Translator


# https://stackoverflow.com/questions/1936466/how-to-scrape-only-visible-webpage-text-with-beautifulsoup
def tag_visible(element):
    if element.name is not None:
        return False
    if element.parent.name in ['style', 'script', 'head', 'title', 'meta', '[document]']:
        return False
    if isinstance(element, Comment):
        return False
    return True


with open('test.html', 'rb') as f:
    soup = BeautifulSoup(f.read(), "lxml")

to_translate = [elem for elem in soup.find_all(string=True) if tag_visible(elem)]
translator = Translator()

for element in to_translate:
    print(str(element))
    result = translator.translate(str(element), dest="ru").text
    element.replaceWith(BeautifulSoup(result, "html.parser"))

with open('test_translated.html', 'wb') as f:
    f.write(soup.prettify('utf-8'))

Для UTF-8 в html файл нужно добавить <meta charset="UTF-8">.