【问题标题】:Beautiful soup getting the first child美丽的汤得到第一个孩子
【发布时间】:2013-03-07 14:37:50
【问题描述】:

我怎样才能得到第一个孩子?

 <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)

AttributeError: 'listiterator' 对象没有属性 'contents'

【问题讨论】:

  • children 是一系列孩子,每个孩子都有contents。序列本身没有contents。就像[1, 2, 3] 不是整数一样。同时,像任何序列一样,要获得第一个值,您只需 next(iter(div.children))

标签: python beautifulsoup


【解决方案1】:

使用现代版本的 bs4(当然是 bs4 4.7.1+),您可以访问 :first-child css 伪选择器。尼斯和描述性的。如果您只想返回第一个匹配项,即soup.select_one('.cities div:first-child').text,请使用soup.select_one。在使用.text 访问器之前测试not 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)

【讨论】:

    【解决方案2】:

    当问题只想要第一个时,当前接受的答案会得到所有城市。

    如果你只需要第一个孩子,你可以利用.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())
    

    【讨论】:

      【解决方案3】:

      div.children 返回一个迭代器。

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

      出现了AttributeError,因为'\n' 之类的非标签在.children 中。只需使用适当的子选择器来查找特定的 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
      

      【讨论】:

      • AttributeError: 'NavigableString' object has no attribute 'contents',当我使用字符串而不是内容时,它会给出RuntimeError: maximum recursion depth exceeded while calling a Python object
      • 它打印 None, None 然后 RuntimeError: maximum recursion depth exceeded while calling a Python object
      • div['id'] 或喜欢div.get('id', None)。就像您从 dict 检索某些东西一样。
      猜你喜欢
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-01
      • 2011-11-15
      • 1970-01-01
      • 2016-12-18
      • 2021-01-15
      相关资源
      最近更新 更多