Как извлечь текст внутри span без имени класса с помощью BeautifulSoup в python - PullRequest
2 голосов
/ 22 октября 2019

Я делаю словарь, который ищет слово на испанском и дает мне соответствующий английский перевод. Я совершенно новичок в BeautifulSoup, поэтому я пользуюсь этой возможностью, чтобы научиться просматривать веб-страницы.

Ссылка на веб-страницу: https://www.spanishdict.com/translate/rojo. Я просто набрал 'rojo' для примера.

Однако после того, как я успешно извлек перевод, я хотел бы также извлечь некоторые примеры предложений, но здесь я сталкиваюсь с одной проблемой. Я не могу извлечь одно из предложений внутри <span> БЕЗ имени класса.

Я пытался

soup.find_all(name='div', class_='indent--FyTYr')

Но в этом классе появилось много ненужной информации. Я также заметил один ответ из поста ссылка упоминается previous_sibling, но он не работает.

Пример HTML-кода будет выглядеть так:

<div class="indent--FyTYr">
  <div>
    <span>The sky turned red at sundown.</span>
    <span class="dash--SIa20"></span>
    <em class="exampleDesktop--3n1hN">El cielo se tornó rojo al atardecer.</em> 
  </div>
...
</div>

Я хотел бы извлечь предложение из приведенного выше примера кода HTML. Но я не нашел ни одного полезного метода для поиска и извлечения.

Небо стало красным на закате.

Спасибо за вашу помощь.

Ответы [ 3 ]

0 голосов
/ 22 октября 2019

Вы можете выполнить итерацию по самым внешним div из id='dictionary-neodict-es' с помощью рекурсивной функции, чтобы учесть тот факт, что существует несколько вложенных div с классом indent--FyTYr:

from bs4 import BeautifulSoup as soup
import requests, bs4
def has_class(d, c):
   return any(c in i.attrs.get('class', []) or has_class(getattr(i, 'contents', []), c) for i in d if i != '\n' and not isinstance(i, bs4.NavigableString))

def get_sentences(d):
   if 'indent--FyTYr' in d.attrs.get('class', []) and not has_class(d.contents, 'indent--FyTYr'):
      yield [d.div.span.text, d.div.em.text]
   else:
      for i in filter(lambda x:x != '\n' and not isinstance(x, bs4.NavigableString), getattr(d, 'contents', [])):
         yield from get_sentences(i)


result = list(get_sentences(soup(requests.get('https://www.spanishdict.com/translate/rojo').text, 'html.parser').find('div', {'id':'dictionary-neodict-es'})))

Теперь у вас есть доступ ко всем предложениям:

[['The sky turned red at sundown.', 'El cielo se tornó rojo al atardecer.'], ['No quiero ver esa propaganda roja.', "I don't want to see that red propaganda."], ['Ella cree que me veo mejor vestida de rojo, pero no estoy segura.', "She thinks I look best dressed in red, but I'm not sure."], ['Durante la Guerra Fría, a los izquierdistas se les llamaba rojos.', 'During the Cold War, the leftists were called reds.']]

Для доступа к нужной вам строке:

print(result[0][0])

Вывод:

'The sky turned red at sundown.'
0 голосов
/ 23 октября 2019

Вы можете предоставить список селекторов CSS и сгенерировать список соответствующих элементов, а затем словарь для поиска переводов. Поменяйте порядок, чтобы английские фразы были ключами, а испанский - значениями. Требуется BS4 4.7.1+. Совпадающие элементы - это те, в которых есть фраза - перевод.

from bs4 import BeautifulSoup as bs
import requests

r = requests.get('https://www.spanishdict.com/translate/rojo')
soup = bs(r.content, 'lxml')
elems = [i.text for i in soup.select('span:has(+[class^="dash--"]), div:has(span:has(+[class^="dash--"])) em:not([title]), .ex, .ex_unit .tran_group, .idm, .idm_unit .tran_group, .cpd, .cpd_group .tran_group')]
results = {v if k!=elems[0] else k:k if k!=elems[0] else v for k,v in zip(elems[0::2],elems[1::2])} #reverse first item
print(results)

image

В противном случае вы также можете перечислить пары слайсов.

0 голосов
/ 22 октября 2019

Если вы уверены, что span будет первым, вы можете просто использовать .find("span"):

>>> soup.find_all(name='div', class_='indent--FyTYr')[0].find("span").text
'The sky turned red at sundown.'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...