【问题标题】:Scraping un-closed meta tags with BS4使用 BS4 抓取未关闭的元标记
【发布时间】:2016-11-09 14:46:59
【问题描述】:

我正在尝试获取元标记的内容。问题是 BS4 无法在某些网站上正确解析标签,标签没有按应有的方式关闭。使用以下示例中的标签,我的函数的输出包括大量杂乱无章的内容,包括脚本、链接等其他标签。我相信浏览器会自动关闭头部末尾的元标签,这种行为会让 BS4 感到困惑。

我的代码适用于此:

<meta name="description" content="content" />

并且不适用于:

<meta name="description" content="content">

这是我的 BS4 函数的代码:

from bs4 import BeautifulSoup

html = BeautifulSoup(open('/path/file.html'), 'html.parser')
desc = html.find(attrs={'name':'description'})

print(desc)

有什么方法可以让它与那些未关闭的元标记一起工作?

【问题讨论】:

    标签: python python-3.x beautifulsoup html-parsing


    【解决方案1】:

    html5lib or lxml parser 会妥善处理问题:

    In [1]: from bs4 import BeautifulSoup
       ...: 
       ...: data = """
       ...: <html>
       ...:     <head>
       ...:         <meta name="description" content="content">
       ...:         <script>
       ...:             var i = 0;
       ...:         </script>
       ...:     </head>
       ...:     <body>
       ...:         <div id="content">content</div>
       ...:     </body>
       ...: </html>"""
       ...: 
    
    In [2]: BeautifulSoup(data, 'html.parser').find(attrs={'name': 'description'})
    Out[2]: <meta content="content" name="description">\n<script>\n            var i = 0;\n        </script>\n</meta>
    
    In [3]: BeautifulSoup(data, 'html5lib').find(attrs={'name': 'description'})
    Out[3]: <meta content="content" name="description"/>
    
    In [4]: BeautifulSoup(data, 'lxml').find(attrs={'name': 'description'})
    Out[4]: <meta content="content" name="description"/>
    

    【讨论】:

      【解决方案2】:

      得到了一些新的东西,希望它能给你一些帮助,我想每次 BeautifulSoup 找到一个没有正确结束标签的元素,然后它会继续搜索下一个和下一个元素,直到它的父标签结束标签。也许你还在不明白我的想法,在这里我做了一个小演示:

          hello.html
      <!DOCTYPE html>
          <html lang="en">
          <meta name="description" content="content">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <div>
          <p class="title"><b>The Dormouse's story</b>
      
          <p class="story">Once upon a time there were three little sisters; and their names were
          <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
          <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
          <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
          and they lived at the bottom of a well.</p>
          </p></div>
          </body>
          </html>
      

      然后像以前一样运行并在下面找到结果:

      <meta content="content" name="description">
      <head>
      <meta charset="utf-8">
      <title>Title</title>
      </meta></head>
      <body>
      ...
      </div></body>
      </meta>
      

      好的! BeautifulSoup 自动生成结束元标记,其位置在&lt;/body&gt; 标记之后,但仍然看不到元的父结束标记&lt;/html&gt;,所以我的意思是结束标记应该反映与其开始标记相同的位置。但是我仍然无法说服自己这样的意见所以我做了一个测试,删除&lt;p class='title'&gt;结束标签所以&lt;div&gt;...&lt;/div&gt;中只有一个&lt;/p&gt;标签,但运行后

      c = soup.find_all('p', attrs={'class':'title'}) print(c[0])

      结果中有两个&lt;/p&gt; 标签。就像我之前说的那样,这是真的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-20
        • 2017-03-21
        • 2013-12-04
        • 2019-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-07
        相关资源
        最近更新 更多