Python Beautifulsoup: поиск элемента после определенной строки - PullRequest
0 голосов
/ 30 октября 2018

У меня есть следующий HTML-код:

<div class="xyOfqd">
<div class="aAAD">
   <div class="Bgbcca">Updated</div>
   <span class="hthtb">
      <div>
         <span class="hthtb">September 30, 2018</span>
      </div>
   </span>
</div>
<div class="aAAD">
   <div class="Bgbcca">Text1</div>
   <span class="hthtb">
      <div><span class="hthtb">Text2</span></div>
   </span>
</div>
<div 
   class="aAAD">
   <div class="Bgbcca">MyText</div>
   <span class="hthtb">
      <div> 
         <span class="hthtb">Text3</span>
      </div>
   </span>
</div>
<div class="aAAD">
   <div class="Bgbcca">Text4</div>
   <span class="hthtb">
      <div><span 
         class="hthtb">Text5</span></div>
   </span>
</div>
<div class="aAAD">
   <div 
      class="Bgbcca">Text6</div>
   <span class="hthtb">
      <div><span 
         class="hthtb">Text7</span></div>
   </span>
</div>
<div class="aAAD">
<div 
   class="Bgbcca">
   Text8/div>
   <span class="hthtb">
      <div>
         <span class="hthtb">
            <div>Text9</div>
            <div><a href="https://google.com">Text10</a></div>
         </span>
      </div>
   </span>
</div>
<div class="aAAD">
   <div 
      class="Bgbcca">Text11</div>
   <span class="hthtb">
      <div><span class="hthtb">Text12</span></div>
   </span>
</div>

Как найти Text3, который расположен сразу после элемента div со строкой MyText?

Ответы [ 3 ]

0 голосов
/ 30 октября 2018

Вы можете использовать lxml.html решение:

from lxml import html

source = """
<div class="xyOfqd">
<div class="aAAD">
   <div class="Bgbcca">Updated</div>
   ...
   <span class="hthtb">
      <div><span class="hthtb">Text12</span></div>
   </span>
</div>"""

tree = html.fromstring(source)
print(tree.xpath('//div[.="MyText"]/following-sibling::span/div/span/text()'))
0 голосов
/ 30 октября 2018

Вы можете создать пользовательскую функцию запроса для передачи в find():

def has_my_text(tag):
    found = tag.select_one('.Bgbcca')
    # important to assign the result to avoid calling
    # .get_text() on a NoneType, resulting in an error.
    if found:
        return found.get_text() == "MyText"

soup = bs4.... # assign your soup object
found = soup.find(has_my_text)

# <div class="Bgbcca">MyText</div>
#  <span class="hthtb">
#   <div>
#    <span class="hthtb">Text3</span>
#   </div>
#  </span>
# </div>

# Note your span class is nested so we go two level in
result = found.select_one('.hthtb').select_one('.hthtb').get_text()

# 'Text3'

# This below also works if your other span are always empty texts
result = found.select_one('.hthtb').get_text().strip()

Обратите внимание, find() и select_one предполагают, что нам нужно только первое найденное совпадение. Если вам нужно обрабатывать несколько совпадений, вам нужно использовать find_all() и select() и соответственно вносить изменения в код.

Если вы хотите обрабатывать переменные тексты, вы можете определить свою функцию следующим образом:

def has_my_text(tag, text):
    found = tag.select_one('.Bgbcca')
    if found:
        return found.get_text() == text

И оберните функцию в find() так:

txt = "MyText"
soup.find(lambda tag: has_my_text(tag, txt))
0 голосов
/ 30 октября 2018

Только если ваша структура является окончательной, вы можете получить правильное значение, делая это:

from bs4 import BeautifulSoup as bfs

 html = """<div class="xyOfqd">
   <div class="aAAD">
    <div class="Bgbcca">Updated</div>
      <span class="hthtb">
      <div>
         <span class="hthtb">September 30, 2018</span>
      </div>
   </span>
</div>
<div class="aAAD">
   <div class="Bgbcca">Text1</div>
   <span class="hthtb">
      <div><span class="hthtb">Text2</span></div>
   </span>
</div>
<div 
   class="aAAD">
   <div class="Bgbcca">MyText</div>
   <span class="hthtb">
      <div> 
         <span class="hthtb">Text3</span>
      </div>
   </span>
</div>
<div class="aAAD">
   <div class="Bgbcca">Text4</div>
   <span class="hthtb">
      <div><span 
         class="hthtb">Text5</span></div>
   </span>
</div>
<div class="aAAD">
   <div 
      class="Bgbcca">Text6</div>
   <span class="hthtb">
      <div><span 
         class="hthtb">Text7</span></div>
   </span>
</div>
<div class="aAAD">
<div 
   class="Bgbcca">
   Text8/div>
   <span class="hthtb">
      <div>
         <span class="hthtb">
            <div>Text9</div>
            <div><a href="https://google.com">Text10</a></div>
         </span>
      </div>
   </span>
</div>
<div class="aAAD">
   <div 
      class="Bgbcca">Text11</div>
   <span class="hthtb">
      <div><span class="hthtb">Text12</span></div>
   </span>
</div>"""


soup = bfs(html, 'html.parser')

result = ''

for div0 in soup.find_all('div',{'class':'aAAD'}):
    for div1 in div0.find_all('div', {'class':'Bgbcca'}):
        if div1.get_text() == 'MyText':
            span = div0.find('span',{'class':'hthtb'})
            if span:
                span_to_return = span.find('span',{'class':'hthtb'})
                if span_to_return:
                    result = span_to_return.get_text()

print(result)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...