【问题标题】:Parsing HTML using Python使用 Python 解析 HTML
【发布时间】:2012-07-27 09:18:31
【问题描述】:

我正在寻找一个用于 Python 的 HTML Parser 模块,它可以帮助我以 Python 列表/字典/对象的形式获取标签。

如果我有以下表格的文件:

<html>
<head>Heading</head>
<body attr1='val1'>
    <div class='container'>
        <div id='class'>Something here</div>
        <div>Something else</div>
    </div>
</body>
</html>

那么它应该给我一种通过HTML标签的名称或ID访问嵌套标签的方法,这样我基本上可以要求它获取div标签中包含class='container'的内容/文本body 标签,或类似的东西。

如果您使用过 Firefox 的“检查元素”功能(查看 HTML),您会知道它会像树一样以漂亮的嵌套方式为您提供所有标签。

我更喜欢内置模块,但这可能要求太多了。


我在 Stack Overflow 和互联网上的一些博客上遇到了很多问题,其中大多数都建议 BeautifulSoup 或 lxml 或 HTMLParser,但其中很少有详细说明功能,并且只是作为关于哪个更快/更多的争论而结束有效。

【问题讨论】:

  • 和所有其他回答者一样,我会推荐 BeautifulSoup,因为它非常适合处理损坏的 HTML 文件。

标签: python xml-parsing html-parsing


【解决方案1】:

这样我就可以要求它获取 div 标签中的内容/文本,其中 class='container' 包含在 body 标签中,或者类似的东西。

try: 
    from BeautifulSoup import BeautifulSoup
except ImportError:
    from bs4 import BeautifulSoup
html = #the HTML code you've written above
parsed_html = BeautifulSoup(html)
print(parsed_html.body.find('div', attrs={'class':'container'}).text)

我猜您不需要性能描述 - 只需阅读 BeautifulSoup 的工作原理即可。看看它的official documentation

【讨论】:

  • parsed_html 对象到底是什么?
  • parsed_html 是一个 BeautifulSoup 对象,可以把它想象成一个 DOMElement 或 DOMDocument,除了它有“棘手”的属性,比如“body”将引用 BeautifulSoup 对象(记住,它基本上是一个树节点)根元素(在我们的例子中是 html)的第一个(在本例中是唯一的)body 元素
  • 一般信息:如果性能至关重要,最好改用lxml 库(请参阅下面的答案)。使用cssselect,它也非常有用,并且性能通常比其他可用的库好 10 到 100 倍。
  • parsed_html = BeautifulSoup(html) 不适合我,parsed_html = BeautifulSoup(html, 'html.parser') 可以
  • @BaileyParker 你会认为在不断与 python2、python3、c++11、c++17 Opencv 4.3 和 Java 2021 打交道的人海中,有人会****想把它命名为import bs,所以当他们用 bs5 改变主意时,他们不会再次破坏每个人的代码
【解决方案2】:

我猜你要找的是pyquery:

pyquery:一个类似 jquery 的 python 库。

你想要的一个例子可能是这样的:

from pyquery import PyQuery    
html = # Your HTML CODE
pq = PyQuery(html)
tag = pq('div#id') # or     tag = pq('div.class')
print tag.text()

它使用与 Firefox 或 Chrome 的检查元素相同的选择器。例如:

检查的元素选择器是“div#mw-head.noprint”。所以在pyquery中,你只需要传递这个选择器:

pq('div#mw-head.noprint')

【讨论】:

  • 对于来自 jQuery 前端的人来说非常有用!
  • 备注。这个库在后台使用lxml
【解决方案3】:

在这里,您可以阅读更多关于 Python 中不同的 HTML 解析器及其性能的信息。尽管这篇文章有点过时,但它仍然为您提供了一个很好的概述。

Python HTML parser performance

我推荐 BeautifulSoup,即使它不是内置的。只是因为它很容易处理这些类型的任务。例如:

import urllib2
from BeautifulSoup import BeautifulSoup

page = urllib2.urlopen('http://www.google.com/')
soup = BeautifulSoup(page)

x = soup.body.find('div', attrs={'class' : 'container'}).text

【讨论】:

  • 我一直在寻找详细说明特性/功能而不是性能/效率的东西。编辑:很抱歉这个过早的答案,那个链接实际上很好。谢谢。
  • 第一个点列表种类总结了特性和功能:)
  • 如果你使用 BeautifulSoup4(最新版本):from bs4 import BeautifulSoup
【解决方案4】:

与其他解析器库相比,lxml 非常快:

使用cssselect,它也很容易用于抓取 HTML 页面:

from lxml.html import parse
doc = parse('http://www.google.com').getroot()
for div in doc.cssselect('a'):
    print '%s: %s' % (div.text_content(), div.get('href'))

lxml.html Documentation

【讨论】:

  • HTTPS 不支持
  • @Sergio 使用import requests,将缓冲区保存到文件:stackoverflow.com/a/14114741/1518921(或urllib),使用解析加载保存的文件后,doc = parse('localfile.html').getroot()
  • 我为特定数据解析巨大的 HTML。使用 BeautifulSoup 花费了 1.7 秒,但应用 lxml 将它提高了将近 *100 倍!如果关心性能,lxml 是最好的选择
  • 另一方面,lxml 带有一个 12MB 的 C 扩展。大多无关紧要,但可能取决于您的工作(在极少数情况下)。
【解决方案5】:

我推荐 lxml 来解析 HTML。见"Parsing HTML" (on the lxml site).

根据我的经验,Beautiful Soup 会在一些复杂的 HTML 上搞砸。我相信这是因为 Beautiful Soup 不是解析器,而是一个非常好的字符串分析器。

【讨论】:

【解决方案6】:

我推荐使用 justext 库:

https://github.com/miso-belica/jusText

用法: Python2:

import requests
import justext

response = requests.get("http://planet.python.org/")
paragraphs = justext.justext(response.content, justext.get_stoplist("English"))
for paragraph in paragraphs:
    print paragraph.text

Python3:

import requests
import justext

response = requests.get("http://bbc.com/")
paragraphs = justext.justext(response.content, justext.get_stoplist("English"))
for paragraph in paragraphs:
    print (paragraph.text)

【讨论】:

    【解决方案7】:

    我会使用 EHP

    https://github.com/iogf/ehp

    这里是:

    from ehp import *
    
    doc = '''<html>
    <head>Heading</head>
    <body attr1='val1'>
        <div class='container'>
            <div id='class'>Something here</div>
            <div>Something else</div>
        </div>
    </body>
    </html>
    '''
    
    html = Html()
    dom = html.feed(doc)
    for ind in dom.find('div', ('class', 'container')):
        print ind.text()
    

    输出:

    Something here
    Something else
    

    【讨论】:

    • 请解释一下。你会在流行的 BeautifulSoup 或 lxml 上使用 EHP 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 2012-04-06
    • 2012-10-15
    相关资源
    最近更新 更多