使用Beautiful Soup获取第一个子元素

22 投票
3 回答
48095 浏览
提问于 2025-04-17 19:35

我怎么才能获取第一个子元素?

 <div class="cities"> 
       <div id="3232"> London </div>
       <div id="131"> York </div>
  </div>

我怎么才能获取伦敦这个值?

for div in nsoup.find_all(class_='cities'):
    print (div.children.contents)

属性错误:'listiterator'对象没有'contents'这个属性

3 个回答

8

现在的答案是获取所有城市,但问题其实只想要第一个城市。

如果你只需要第一个孩子(城市),可以利用 .children 返回的是一个迭代器,而不是一个列表。记住,迭代器是按需生成列表项的,因为我们只需要迭代器的第一个元素,所以我们不需要生成其他所有城市元素(这样可以节省时间)。

for div in nsoup.find_all(class_='cities'):
    first_child = next(div.children, None)
    if first_child is not None:
        print(first_child.string.strip())
15

在现代版本的bs4(至少是bs4 4.7.1及以上)中,你可以使用:first-child这个CSS伪选择器。这个选择器的名字很直观,容易理解。如果你只想获取第一个匹配的元素,可以用soup.select_one,比如soup.select_one('.cities div:first-child').text。在使用.text之前,最好先检查一下返回的结果是不是None,这被认为是一个好的编程习惯。

from bs4 import BeautifulSoup as bs

html = '''
<div class="cities"> 
       <div id="3232"> London </div>
       <div id="131"> York </div>
  </div>
  '''
soup = bs(html, 'lxml') #or 'html.parser'
first_children = [i.text for i in soup.select('.cities div:first-child')]
print(first_children)
14

div.children 返回的是一个迭代器。

for div in nsoup.find_all(class_='cities'):
    for childdiv in div.find_all('div'):
        print (childdiv.string) #london, york

出现了 AttributeError 错误,因为 .children 中有一些不是标签的东西,比如 '\n'。你只需要使用合适的子选择器来找到特定的 div。

(更多编辑) 我无法重现你的异常情况 - 这是我所做的:

In [137]: print foo.prettify()
<div class="cities">
 <div id="3232">
  London
 </div>
 <div id="131">
  York
 </div>
</div>

In [138]: for div in foo.find_all(class_ = 'cities'):
   .....:     for childdiv in div.find_all('div'):
   .....:         print childdiv.string
   .....: 
 London 
 York 

In [139]: for div in foo.find_all(class_ = 'cities'):
   .....:     for childdiv in div.find_all('div'):
   .....:         print childdiv.string, childdiv['id']
   .....: 
 London  3232
 York  131

撰写回答