BeautifulSoup:AttributeError:' NavigableString'对象没有属性' children'

时间:2015-05-30 09:45:53

标签: python beautifulsoup

当使用BeautifulSoup4时,我可以运行此代码来获得一个" Shout"没有问题。当我使用for循环时,我收到错误AttributeError: 'NavigableString' object has no attribute 'children'

class Shout:
    def __init__(self, user, msg, date):
        self.user = user
        self.msg = msg
        self.date = date

def getShouts():
    #s is a requests Session()
    new_shouts = s.get(shouts_url).text
    #set shouts page as parsable object
    soup = BeautifulSoup(new_shouts)
    shouts = []
    shout_heads = soup.find_all("h2", {'class': 'A'})
    shout_feet = soup.find_all("h2", {'class': 'B'})
    for i in range(len(shout_heads)):
        shout = Shout('', '', '')
        shout.user = list(list(list(shout_heads[i].children)[0].children)[1].children)[1].get_text()
        foot = shout_feet[i].get_text().split('-')
        shout.msg = foot[1]
        foot[2] = foot[2].split()
        shout.date = foot[2][0] + " " + foot[2][1]
        shouts.append(shout)
    return shouts

什么会导致此错误仅在循环期间发生?

1 个答案:

答案 0 :(得分:1)

children不仅包含元素中的标记,还包含任何 text (使用NavigableString个对象建模)。即使是空格也可能导致第一个元素之前出现文本:

<h2>
    <a href="...">Some text</a>
</h2>

将文本节点作为第一个子节点。您必须过滤掉这些文本节点,或使用element.find_all(True, recursive=False)仅列出直接子标记。 element.find(True)找到第一个子标记,如果没有此类标记,则为None

或许您可以寻找更具体的标签,而不仅仅是第一个孩子,然后是第二个孩子,然后再次第二个孩子;如果你有特定的标签,那么只需使用他们的名字:

shout_heads[i].a.i.span.string

例如。

请注意.children为您提供迭代器;如果您需要列表,*请勿在{{1​​}}上使用list()。请改用.children属性,这是一个列表对象。

最后但并非最不重要的是,当您可以直接遍历列表时,不要在.contents上使用循环:

range()

如果您需要合并两个列表,可以使用for shout_head in shout_heads: shout = Shout('', '', '') shout.user = shout_head.find(True)[0] # etc.

zip()

虽然您也可以使用for shout_head, shout_foot in zip(shout_heads, shout_feet): 来查找这些额外的find_next_sibling()元素,但这些元素是否会交替出现。