CSS селектор с: не ведет себя не так, как ожидалось - PullRequest
1 голос
/ 06 июля 2019

Я хочу использовать селектор CSS, чтобы выбрать все после элемента со значением SOUND WORD, но перед элементом со значением, называемым COMPONENTS, с помощью селектора CSS в Python.

<p class="p_cat_heading">SOUND WORD</p>
<p class="p_normal__and__avoid_page_break_after"><span class="c_tone_char">Vene</span><span class="c_tone_char__and__underline">zue</span><span class="c_tone_char">la</span> /<span class="calibre22">venedswela</span>/</p>
<p class="p_normal__and__avoid_page_break_after">South American country over the equator, known in part for its sunny beaches. Pronounce it in Italian for a better sound match.</p>
<p class="p_normal__and__avoid_page_break_after"><img width="30%" alt="" src="../images/00461.jpeg" class="calibre18"/></p>
<p class="p_cat_heading__and__centre_alignment">COMPONENTS</p>

Я использую следующееСелектор CSS:

content = str(soup.select_one('.p_cat_heading:contains("SOUND WORD") + :not(.p_cat_heading)'))  # type: str

Это должно выбрать все, вплоть до элемента с классом p_cat_heading.Однако он только выбирает:

<p class="p_normal__and__avoid_page_break_after"><span class="c_tone_char">Vene</span><span class="c_tone_char__and__underline">zue</span><span class="c_tone_char">la</span> /<span class="calibre22">venedswela</span>/</p>

Я должен неправильно понять, как работает селектор CSS.Я думал, что : работает как срез Python, но, похоже, дело не в этом.Тем не менее, я не уверен, что мне не хватает.

Ответы [ 2 ]

0 голосов
/ 06 июля 2019

Если это так, как вы показываете, вы можете использовать фильтрацию и отфильтровывать теги p, которые являются либо второй строкой поиска, либо следуют за братом или сестрой из тегов p родственного элемента первой строки поиска.Это довольно точно, чтобы соответствовать тому, что вы показываете.

from bs4 import BeautifulSoup as bs

html = '''
<html>
 <head></head>
 <body>
  <p class="p_cat_heading">SOUND WORD</p> 
  <p class="p_normal__and__avoid_page_break_after"><span class="c_tone_char">Vene</span><span class="c_tone_char__and__underline">zue</span><span class="c_tone_char">la</span> /<span class="calibre22">venedswela</span>/</p> 
  <p class="p_normal__and__avoid_page_break_after">South American country over the equator, known in part for its sunny beaches. Pronounce it in Italian for a better sound match.</p> 
  <p class="p_normal__and__avoid_page_break_after"><img width="30%" alt="" src="../images/00461.jpeg" class="calibre18"></p> 
  <p class="p_cat_heading__and__centre_alignment">COMPONENTS</p>
 </body>
</html>
'''
soup = bs(html, 'lxml')
result = [item.text.strip() for item in soup.select('p:contains("SOUND WORD") ~ p:not(p:contains("COMPONENTS") ~ p, p:contains("COMPONENTS"))')]
0 голосов
/ 06 июля 2019

Спасибо @Barmar за помощь в этом. Чтобы повторить его комментарий, вы не можете сделать это с помощью селектора CSS. Вместо этого я перебирал элементы, пока не достиг разделителя:

for temp_heading in heading.find_next_siblings():
    if temp_heading.attrs["class"][0] == "p_cat_heading":
        break
    else:
        print(str(temp_heading))
organized_entry["soundword"] = content

где temp_heading был экземпляром bs.element.Tag, который начинался с указания на:

<p class="p_cat_heading">SOUND WORD</p>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...