新闻动态

python 提取html文本的方法

发布日期:2022-05-24 14:57 | 文章来源:gibhub

假设我们需要从各种网页中提取全文,并且要剥离所有HTML标记。通常,默认解决方案是使用BeautifulSoup软件包中的get_text方法,该方法内部使用lxml。这是一个经过充分测试的解决方案,但是在处理成千上万个HTML文档时可能会非常慢。
通过用selectolax替换BeautifulSoup,您几乎可以免费获得5-30倍的加速!
这是一个简单的基准测试,可分析commoncrawl(`处理NLP问题时,有时您需要获得大量的文本集。互联网是文本的最大来源,但是不幸的是,从任意HTML页面提取文本是一项艰巨而痛苦的任务。
假设我们需要从各种网页中提取全文,并且要剥离所有HTML标记。通常,默认解决方案是使用BeautifulSoup软件包中的get_text方法,该方法内部使用lxml。这是一个经过充分测试的解决方案,但是在处理成千上万个HTML文档时可能会非常慢。
通过用selectolax替换BeautifulSoup,您几乎可以免费获得5-30倍的加速!这是一个简单的基准测试,可分析commoncrawl(https://commoncrawl.org/)的10,000个HTML页面:

#coding:utf-8
fromtimeimporttime
importwarc
frombs4importBeautifulSoup
fromselectolax.parserimportHTMLParser

defget_text_bs(html):
tree=BeautifulSoup(html,'lxml')
body=tree.body
ifbodyisNone:
returnNone
fortaginbody.select('script'):
tag.decompose()
fortaginbody.select('style'):
tag.decompose()
text=body.get_text(separator='\n')
returntext

defget_text_selectolax(html):
tree=HTMLParser(html)
iftree.bodyisNone:
returnNone
fortagintree.css('script'):
tag.decompose()
fortagintree.css('style'):
tag.decompose()
text=tree.body.text(separator='\n')
returntext

defread_doc(record,parser=get_text_selectolax):
url=record.url
text=None
ifurl:
payload=record.payload.read()
header,html=payload.split(b'\r\n\r\n',maxsplit=1)
html=html.strip()
iflen(html)>0:
text=parser(html)
returnurl,text

defprocess_warc(file_name,parser,limit=10000):
warc_file=warc.open(file_name,'rb')
t0=time()
n_documents=0
fori,recordinenumerate(warc_file):
url,doc=read_doc(record,parser)
ifnotdocornoturl:
continue
n_documents+=1
ifi>limit:
break
warc_file.close()
print('Parser:%s'%parser.__name__)
print('Parsingtook%ssecondsandproduced%sdocuments\n'%(time()-t0,n_documents))
>>>!wgethttps://commoncrawl.s3.amazonaws.com/crawl-data/CC-MAIN-2018-05/segments/1516084886237.6/warc/CC-MAIN-20180116070444-20180116090444-00000.warc.gz
>>>file_name="CC-MAIN-20180116070444-20180116090444-00000.warc.gz"
>>>process_warc(file_name,get_text_selectolax,10000)
Parser:get_text_selectolax
Parsingtook16.170367002487183secondsandproduced3317documents
>>>process_warc(file_name,get_text_bs,10000)
Parser:get_text_bs
Parsingtook432.6902508735657secondsandproduced3283documents

显然,这并不是对某些事物进行基准测试的最佳方法,但是它提供了一个想法,即selectolax有时比lxml快30倍。
selectolax最适合将HTML剥离为纯文本。如果我有10,000多个HTML片段,需要将它们作为纯文本索引到Elasticsearch中。(Elasticsearch有一个html_strip文本过滤器,但这不是我想要/不需要在此上下文中使用的过滤器)。事实证明,以这种规模将HTML剥离为纯文本实际上是非常低效的。那么,最有效的方法是什么?

  • PyQuery
frompyqueryimportPyQueryaspq
text=pq(html).text()
  • selectolax
fromselectolax.parserimportHTMLParser
text=HTMLParser(html).text()
  • 正则表达式
importre
regex=re.compile(r'<.*?>')
text=clean_regex.sub('',html)

结果

我编写了一个脚本来计算时间,该脚本遍历包含HTML片段的10,000个文件。注意!这些片段不是完整的<html>文档(带有<head>和<body>等),只是HTML的一小部分。平均大小为10,314字节(中位数为5138字节)。结果如下:

pyquery
SUM:18.61seconds
MEAN:1.8633ms
MEDIAN:1.0554ms
selectolax
SUM:3.08seconds
MEAN:0.3149ms
MEDIAN:0.1621ms
regex
SUM:1.64seconds
MEAN:0.1613ms
MEDIAN:0.0881ms

我已经运行了很多次,结果非常稳定。重点是:selectolax比PyQuery快7倍。

正则表达式好用?真的吗?

对于最基本的HTML Blob,它可能工作得很好。实际上,如果HTML是<p> Foo&amp; Bar </ p>,我希望纯文本转换应该是Foo&Bar,而不是Foo&amp; bar。
更重要的一点是,PyQuery和selectolax支持非常特定但对我的用例很重要的内容。在继续之前,我需要删除某些标签(及其内容)。例如:

<h4class="warning">Thisshouldgetstripped.</h4>
<p>Pleasekeep.</p>
<divstyle="display:none">Thisshouldalsogetstripped.</div>

正则表达式永远无法做到这一点。

2.0 版本

因此,我的要求可能会发生变化,但基本上,我想删除某些标签。例如:<div class =“ warning”> 、 <div class =“ hidden”> 和 <div style =“ display:none”>。因此,让我们实现一下:

  • PyQuery
frompyqueryimportPyQueryaspq
_display_none_regex=re.compile(r'display:\s*none')
doc=pq(html)
doc.remove('div.warning,div.hidden')
fordivindoc('div[style]').items():
style_value=div.attr('style')
if_display_none_regex.search(style_value):
div.remove()
text=doc.text()
  • selectolax
fromselectolax.parserimportHTMLParser
_display_none_regex=re.compile(r'display:\s*none')
tree=HTMLParser(html)
fortagintree.css('div.warning,div.hidden'):
tag.decompose()
fortagintree.css('div[style]'):
style_value=tag.attributes['style']
ifstyle_valueand_display_none_regex.search(style_value):
tag.decompose()
text=tree.body.text()

这实际上有效。当我现在为10,000个片段运行相同的基准时,新结果如下:

pyquery
SUM:21.70seconds
MEAN:2.1701ms
MEDIAN:1.3989ms
selectolax
SUM:3.59seconds
MEAN:0.3589ms
MEDIAN:0.2184ms
regex
Skip

同样,selectolax击败PyQuery约6倍。

结论

正则表达式速度快,但功能弱。selectolax的效率令人印象深刻。

以上就是python 提取html文本的方法的详细内容,更多关于python 提取html文本的资料请关注本站其它相关文章!

香港快速服务器

版权声明:本站文章来源标注为YINGSOO的内容版权均为本站所有,欢迎引用、转载,请保持原文完整并注明来源及原文链接。禁止复制或仿造本网站,禁止在非www.yingsoo.com所属的服务器上建立镜像,否则将依法追究法律责任。本站部分内容来源于网友推荐、互联网收集整理而来,仅供学习参考,不代表本站立场,如有内容涉嫌侵权,请联系alex-e#qq.com处理。

相关文章

实时开通

自选配置、实时开通

免备案

全球线路精选!

全天候客户服务

7x24全年不间断在线

专属顾问服务

1对1客户咨询顾问

在线
客服

在线客服:7*24小时在线

客服
热线

400-630-3752
7*24小时客服服务热线

关注
微信

关注官方微信
顶部