BeautifulSoup:如何从包含嵌套<ul>的<ul>列表中提取所有<li>?

37 投票
3 回答
86570 浏览
提问于 2025-04-16 08:06

我是一名新手程序员,想通过编写一个脚本来学习Python,这个脚本的目的是从http://en.wikipedia.org/wiki/2000s_in_film上抓取数据,并提取出“电影标题(年份)”的列表。

我的HTML源代码看起来是这样的:

<h3>Header3 (Start here)</h3>
<ul>
    <li>List items</li>
    <li>Etc...</li>
</ul>
<h3>Header 3</h3>
<ul>
    <li>List items</li>
    <ul>
        <li>Nested list items</li>
        <li>Nested list items</li></ul>
    <li>List items</li>
</ul>
<h2>Header 2 (end here)</h2>

我想要获取第一个

标签后面的所有
  • 标签,直到下一个

    标签为止,包括所有嵌套的
  • 标签。

    firstH3 = soup.find('h3')
    

    ...这段代码能正确找到我想要开始的地方。

    firstH3 = soup.find('h3') # Start here
    uls = []
    for nextSibling in firstH3.findNextSiblings():
        if nextSibling.name == 'h2':
            break
        if nextSibling.name == 'ul':
            uls.append(nextSibling)
    

    ...这段代码给我提供了一个包含我需要的

  • 内容的
      列表。

      这是

        列表的一部分:

        <ul>
        ...
            <li><i><a href="/wiki/Agent_Cody_Banks" title="Agent Cody Banks">Agent Cody Banks</a></i> (2003)</li>
            <li><i><a href="/wiki/Agent_Cody_Banks_2:_Destination_London" title="Agent Cody Banks 2: Destination London">Agent Cody Banks 2: Destination London</a></i> (2004)</li>
            <li>Air Bud series:
                <ul>
                    <li><i><a href="/wiki/Air_Bud:_World_Pup" title="Air Bud: World Pup">Air Bud: World Pup</a></i> (2000)</li>
                    <li><i><a href="/wiki/Air_Bud:_Seventh_Inning_Fetch" title="Air Bud: Seventh Inning Fetch">Air Bud: Seventh Inning Fetch</a></i> (2002)</li>
                    <li><i><a href="/wiki/Air_Bud:_Spikes_Back" title="Air Bud: Spikes Back">Air Bud: Spikes Back</a></i> (2003)</li>
                    <li><i><a href="/wiki/Air_Buddies" title="Air Buddies">Air Buddies</a></i> (2006)</li>
                </ul>
            </li>
            <li><i><a href="/wiki/Akeelah_and_the_Bee" title="Akeelah and the Bee">Akeelah and the Bee</a></i> (2006)</li>
        ...
        </ul>
        

        但我不太确定接下来该怎么做。


        更新:

        最终代码:

        lis = []
            for ul in uls:
                for li in ul.findAll('li'):
                    if li.find('ul'):
                        break
                    lis.append(li)
        
            for li in lis:
                print li.text.encode("utf-8")
        

        这段代码中的if...break会排除掉包含

        • ,因为嵌套的
        • 现在是重复的。

          现在打印输出的结果是:

          • 102 Dalmatians(2000)
          • 10th & Wolf(2006)
          • 11:14(2006)
          • 12:08 East of Bucharest(2006)
          • 13 Going on 30(2004)
          • 1408(2007)
          • ...
  • 3 个回答

    3
    import requests
    from bs4 import BeautifulSoup
    r = requests.get("https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_list_test")
    soup =   BeautifulSoup(r.content,"lxml")
    w3schollsList = soup.find_all('body')
    for w3scholl in w3schollsList:
        ulList = w3scholl.find_all('li')
        for li in ulList:
            print(li)
    

    注意:这里是为了获取我们创建的div里面的"li"元素。

    13

    列表推导式也可以用来解决这个问题。

    lis = [li for ul in uls for li in ul.findAll('li')]
    
    30

    .findAll() 可以用来查找嵌套的 li 元素:

    for ul in uls:
        for li in ul.findAll('li'):
            print(li)
    

    输出结果:

    <li>List items</li>
    <li>Etc...</li>
    <li>List items</li>
    <li>Nested list items</li>
    <li>Nested list items</li>
    <li>List items</li>
    

    撰写回答