使用 Python 解析 HTML

Parsing HTML using Python

提问人:ffledgling 提问时间:7/29/2012 最后编辑:Benjamin Loisonffledgling 更新时间:2/18/2023 访问量:458103

问:

我正在寻找一个用于 Python 的 HTML 解析器模块,它可以帮助我以 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 访问嵌套标签的方法,这样我基本上可以要求它为我获取标签中包含的标签中的内容/文本,或类似的东西。divclass='container'body

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

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


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

python xml html 解析

评论

3赞 Pascal Rosin 7/29/2012
像所有其他回答者一样,我会推荐 BeautifulSoup,因为它在处理损坏的 HTML 文件方面非常出色。

答:

50赞 Qiau 7/29/2012 #1

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

Python HTML 解析器性能

我推荐 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

评论

2赞 ffledgling 7/29/2012
我一直在寻找一些细节特性/功能而不是性能/效率的东西。编辑:对不起,答案不成熟,该链接实际上很好。谢谢。
0赞 Qiau 7/29/2012
第一种要点列表类型总结了特性和功能:)
9赞 Franck Dernoncourt 5/22/2014
如果您使用 BeautifulSoup4(最新版本):from bs4 import BeautifulSoup
0赞 kristianp 12/13/2022
解析器性能文章已移至:ianbicking.org/blog/2008/03/python-html-parser-performance.html
276赞 Aadaam 7/29/2012 #2

这样我就可以要求它让我获得 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 的工作原理即可。查看其官方文档

评论

4赞 ffledgling 7/29/2012
parsed_html对象到底是什么?
2赞 Aadaam 7/29/2012
parsed_html是一个 BeautifulSoup 对象,可以把它想象成一个 DOMElement 或 DOMDocument,除了它有“棘手”的属性,比如 “body” 将引用 BeautifulSoup 对象(记住,它基本上是一个树节点)根元素的第一个(在本例中是唯一的)body 元素(在我们的例子中是 html)
5赞 Lenar Hoyt 11/8/2014
一般信息:如果性能至关重要,最好改用该库(请参阅下面的答案)。它也非常有用,性能通常比其他可用的库好 10 到 100 倍。lxmlcssselect
2赞 Pavel 3/14/2017
parsed_html = BeautifulSoup(html)对我不起作用,确实parsed_html = BeautifulSoup(html, 'html.parser')
3赞 user202729 1/24/2022
@Nathan 公平地说,主要版本更新意味着重大的不兼容更改,因此无论如何,代码很可能会以某种方式中断。早点休息总比晚点休息好。
106赞 YusuMishi 7/29/2012 #3

我猜你要找的是pyquery

pyquery:一个类似 JQure 的 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的inspect元素相同的选择器。例如:

the element selector is 'div#mw-head.noprint'

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

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

评论

0赞 Jay Dadhania 7/20/2021
对于来自jQuery前端的人来说非常有用!
3赞 user202729 1/24/2022
备注。该库在后台使用 lxml
11赞 Love and peace - Joe Codeswell 10/26/2014 #4

我推荐 lxml 来解析 HTML。请参阅“解析 HTML”(在 lxml 站点上)。

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

评论

4赞 ffledgling 10/26/2014
AIUI Beautiful Soup 可以与大多数“后端”XML 解析器一起使用,lxml 似乎是支持的解析器之一 crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
0赞 Lenar Hoyt 11/8/2014
@ffledgling 然而,BeautifulSoup的某些功能相当缓慢。
35赞 Lenar Hoyt 11/8/2014 #5

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

而且它也很容易用于抓取 HTML 页面:cssselect

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 文档

评论

0赞 Sergio 5/26/2019
不支持 HTTPS
0赞 Reptile 5/28/2019
@Sergio使用 ,将缓冲区保存到文件:stackoverflow.com/a/14114741/1518921(或 urllib),使用 parse 加载保存的文件后,import requestsdoc = parse('localfile.html').getroot()
3赞 Alex-Bogdanov 5/29/2020
我解析了特定数据的巨大 HTML。用 BeautifulSoup 做这件事花了几秒钟,但应用 lxml 却让它的速度提高了近几倍!如果关心性能,lxml 是最佳选择1.7*100
0赞 user202729 1/24/2022
另一方面,lxml 带有 12MB C 扩展名。大多数情况下是微不足道的,但可能取决于你做了什么(在极少数情况下)。
0赞 Unknown Soldier 3/20/2016 #6

我会使用 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

评论

8赞 ChaimG 9/22/2016
请解释。你会用什么 EHP 而不是流行的 BeautifulSoup 或 lxml?
2赞 Wesam Na 7/15/2016 #7

我推荐使用 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

蟒蛇3:

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)