BeautifulSoup 使用循环从多个 div 中抓取信息到 JSON

Posted

技术标签:

【中文标题】BeautifulSoup 使用循环从多个 div 中抓取信息到 JSON【英文标题】:BeautifulSoup scraping information from multiple divs using loops into JSON 【发布时间】:2016-07-10 00:24:23 【问题描述】:

我正在从遵循相同结构的多个 div 中抓取标题、描述、链接和人名。我正在使用 BeautifulSoup,我能够从第一个 div 中刮掉所有东西。但是,我无法从长长的 div 列表中抓取数据,并以 CSV 或 JSON 等可移植格式获取数据。

如何从长长的 div 列表中抓取每个项目,并将这些信息存储在 JSON 对象中,用于每个 mp3?

div 看起来像这样:

<div class="audioBoxWrap clearBoth">
    <h3>Title 1</h3>
    <p>Description 1</p>
    <div class="info" style="line-height: 1px; height: 1px; font-size: 1px;"></div>
    <div class="audioBox" style="display: none;">
        stuff
    </div>
    <div> [ <a href="link1.mp3">Right-click to download</a>] </div>
</div>
<div class="audioBoxWrap clearBoth">
    <h3>Title 2</h3>
    <p>Description 2</p>
    <div class="info" style="line-height: 1px; height: 1px; font-size: 1px;"></div>
    <div class="audioBox" style="display: none;">
        stuff
    </div>
    <div> [ <a href="link2.mp3">Right-click to download</a>] </div>
</div>

我已经弄清楚如何从第一个 div 中抓取,但我无法获取每个 div 的信息。例如,我下面的代码只会一遍又一遍地为第一个 div 吐出 h3。

我知道我可以为标题、描述等创建一个 python 列表,但是我如何保持像 JSON 这样的元数据结构,以便 title1、link1 和 description1 保持在一起,以及 title2 的信息。

with open ('soup.html', 'r') as myfile:
    html_doc = myfile.read()

    soup = BeautifulSoup(html_doc, 'html.parser')

    audio_div = soup.find_all('div', 'class':"audioBoxWrap clearBoth")

    print len(audio_div)
    #create dictionary for storing scraped data. I don't know how to store the values for each mp3 separately.

    for i in audio_div:
        print soup.find('h3').text

我希望我的 JSON 看起来像这样:

  
   "podcasts":[  
        
         "title":"title1",
         "description":"description1",
         "link":"link1"
      ,
        
         "title":"title2",
         "description":"description2",
         "link":"link2"
      
   ]

【问题讨论】:

【参考方案1】:

遍历每个音轨并进行特定于上下文的搜索:

from pprint import pprint

from bs4 import BeautifulSoup

data = """
<div>
    <div class="audioBoxWrap clearBoth">
        <h3>Title 1</h3>
        <p>Description 1</p>
        <div class="info" style="line-height: 1px; height: 1px; font-size: 1px;"></div>
        <div class="audioBox" style="display: none;">
            stuff
        </div>
        <div> [ <a href="link1.mp3">Right-click to download</a>] </div>
    </div>
    <div class="audioBoxWrap clearBoth">
        <h3>Title 2</h3>
        <p>Description 2</p>
        <div class="info" style="line-height: 1px; height: 1px; font-size: 1px;"></div>
        <div class="audioBox" style="display: none;">
            stuff
        </div>
        <div> [ <a href="link2.mp3">Right-click to download</a>] </div>
    </div>
</div>"""

soup = BeautifulSoup(data, "html.parser")

tracks = soup.find_all('div', 'class':"audioBoxWrap clearBoth")
result = 
    "podcasts": [
        
            "title": track.h3.get_text(strip=True),
            "description": track.p.get_text(strip=True),
            "link": track.a["href"]
        
        for track in tracks
    ]

pprint(result)

打印:

'podcasts': ['description': 'Description 1',
               'link': 'link1.mp3',
               'title': 'Title 1',
              'description': 'Description 2',
               'link': 'link2.mp3',
               'title': 'Title 2']

【讨论】:

谢谢你的工作!除了为什么结果的描述、链接和标题的顺序与你在 result= 中的顺序不同?此外,我打印的描述在终端中占据了很多行(描述实际上是整段)。这只是pprint的一个特性,而不是描述中引号的实际内容吗? @moglido 当然,这只是一本字典 - 它没有预定义的顺序。

以上是关于BeautifulSoup 使用循环从多个 div 中抓取信息到 JSON的主要内容,如果未能解决你的问题,请参考以下文章

Selenium/BeautifulSoup - Python - 循环多个页面

使用 BeautifulSoup 从 `div` 中的 `p` 中提取文本

如何使用python和beautifulsoup4循环和抓取多个页面的数据

使用python BeautifulSoup从balise内部div中废弃链接

使用 php 和 laravel 将数据库数据从一个循环传递到多个 div

div的BeautifulSoup子项