在解决自然语言处理问题时,有时你需要获得大量的文本集。互联网是文本的最大来源,但是从任意HTML页面提取文本是一项艰巨而痛苦的任务。

假设我们需要从各种网页中提取全文,并且要剥离所有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-8from time import timeimport warc
from bs4 import BeautifulSoup
from selectolax.parser import HTMLParserdef get_text_bs(html):tree = BeautifulSoup(html, 'lxml')body = tree.bodyif body is None:return Nonefor tag in body.select('script'):tag.decompose()for tag in body.select('style'):tag.decompose()text = body.get_text(separator='\n')return textdef get_text_selectolax(html):tree = HTMLParser(html)if tree.body is None:return Nonefor tag in tree.css('script'):tag.decompose()for tag in tree.css('style'):tag.decompose()text = tree.body.text(separator='\n')return textdef read_doc(record, parser=get_text_selectolax):url = record.urltext = Noneif url:payload = record.payload.read()header, html = payload.split(b'\r\n\r\n', maxsplit=1)html = html.strip()if len(html) > 0:text = parser(html)return url, textdef process_warc(file_name, parser, limit=10000):warc_file = warc.open(file_name, 'rb')t0 = time()n_documents = 0for i, record in enumerate(warc_file):url, doc = read_doc(record, parser)if not doc or not url:continuen_documents += 1if i > limit:breakwarc_file.close()print('Parser: %s' % parser.__name__)print('Parsing took %s seconds and produced %s documents\n' % (time() - t0, n_documents))
>>> ! wget https://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
Parsing took 16.170367002487183 seconds and produced 3317 documents
>>> process_warc(file_name, get_text_bs, 10000)
Parser: get_text_bs
Parsing took 432.6902508735657 seconds and produced 3283 documents

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:**810735403**

显然,这并不是对某些事物进行基准测试的最佳方法,但是它提供了一个想法,即selectolax有时比lxml快30倍。

selectolax最适合将HTML剥离为纯文本。如果我有10,000多个HTML片段,需要将它们作为纯文本索引到Elasticsearch中。(Elasticsearch有一个html_strip文本过滤器,但这不是我想要/不需要在此上下文中使用的过滤器)。事实证明,以这种规模将HTML剥离为纯文本实际上是非常低效的。那么,最有效的方法是什么?

PyQuery

from pyquery import PyQuery as pqtext = pq(html).text()

selectolax

from selectolax.parser import HTMLParsertext = HTMLParser(html).text()

正则表达式

import reregex = re.compile(r'<.*?>')
text = clean_regex.sub('', html)

结果

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

pyquerySUM:    18.61 secondsMEAN:   1.8633 msMEDIAN: 1.0554 ms
selectolaxSUM:    3.08 secondsMEAN:   0.3149 msMEDIAN: 0.1621 ms
regexSUM:    1.64 secondsMEAN:   0.1613 msMEDIAN: 0.0881 ms

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

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

对于最基本的HTML Blob,它可能工作得很好。实际上,如果HTML是<p> Foo&amp; Bar </ p>,我希望纯文本转换应该是Foo&Bar,而不是Foo&amp; bar

更重要的一点是,PyQuery和selectolax支持非常特定但对我的用例很重要的内容。在继续之前,我需要删除某些标签(及其内容)。例如:

<h4 class="warning">This should get stripped.</h4>
<p>Please keep.</p>
<div style="display: none">This should also get stripped.</div>

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

2.0 版本

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

PyQuery

from pyquery import PyQuery as pq_display_none_regex = re.compile(r'display:\s*none')doc = pq(html)
doc.remove('div.warning, div.hidden')
for div in doc('div[style]').items():style_value = div.attr('style')if _display_none_regex.search(style_value):div.remove()
text = doc.text()

selectolax

from selectolax.parser import HTMLParser_display_none_regex = re.compile(r'display:\s*none')tree = HTMLParser(html)
for tag in tree.css('div.warning, div.hidden'):tag.decompose()
for tag in tree.css('div[style]'):style_value = tag.attributes['style']if style_value and _display_none_regex.search(style_value):tag.decompose()
text = tree.body.text()

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

pyquerySUM:    21.70 secondsMEAN:   2.1701 msMEDIAN: 1.3989 ms
selectolaxSUM:    3.59 secondsMEAN:   0.3589 msMEDIAN: 0.2184 ms
regexSkip

同样,selectolax击败PyQuery约6倍。

结论

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

在这里还是要推荐下我自己建的Python开发交流学习(qq)群:810735403,群里都是学Python开发的,如果你正在学习Python ,欢迎你加入,大家都是软件开发党,不定期分享干货(只有Python软件开发相关的),包括我自己整理的一份2021最新的Python进阶资料和高级开发教程,欢迎进阶中和想深入Python的小伙伴!

Python 高效提取 HTML 文本的方法相关推荐

  1. python提取html正文为txt,python 提取html文本的方法

    假设我们需要从各种网页中提取全文,并且要剥离所有HTML标记.通常,默认解决方案是使用BeautifulSoup软件包中的get_text方法,该方法内部使用lxml.这是一个经过充分测试的解决方案, ...

  2. python怎么读取pdf为文本_轻松用Python批量提取PDF文本内容,这个小技巧告诉你!...

    轻松用Python批量提取PDF文本内容,这个小技巧告诉你!-1.jpg (22.73 KB, 下载次数: 0) 2018-9-7 08:33 上传 本文为你展示,如何用Python把许多PDF文件的 ...

  3. python读取中文txt文本-python读取中文txt文本的方法

    对于python2.7 字符串在Python2.7内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码成unicode,再从unico ...

  4. python怎么读中文-python读取中文txt文本的方法

    对于python2.7 字符串在Python2.7内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码成unicode,再从unico ...

  5. python离线语音转文本_使用Python将语音转换为文本的方法

    使用Python将语音转换为文本的方法,语音,转换为,文本,您的,麦克风 使用Python将语音转换为文本的方法 易采站长站,站长之家为您整理了使用Python将语音转换为文本的方法的相关内容. 语音 ...

  6. python txt默认读取字符还是行,python读取中文txt文本的方法

    字符串在Python2.7内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码成unicode,再从unicode编码成另一种编码. ...

  7. python如何读取中文文件-python读取中文txt文本的方法

    对于python2.7 字符串在Python2.7内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码成unicode,再从unico ...

  8. 如何用Python批量提取PDF文本内容?

    本文为你展示,如何用Python把许多PDF文件的文本内容批量提取出来,并且整理存储到数据框中,以便于后续的数据分析. 问题 最近,读者们在后台的留言,愈发五花八门了. 写了几篇关于自然语言处理的文章 ...

  9. python 如何批量提取文件中的字符_如何用Python批量提取PDF文本内容?

    本文为你展示,如何用Python把许多PDF文件的文本内容批量提取出来,并且整理存储到数据框中,以便于后续的数据分析. 问题 最近,读者们在后台的留言,愈发五花八门了. 写了几篇关于自然语言处理的文章 ...

最新文章

  1. 使用Process.Start打开文件夹或网页
  2. 页面导航的两种方式——声明式导航、编程式导航||vue-router编程式导航||router.push() 方法的参数规则
  3. mysqldatareader获取整行数据给datarow_C# sqladapter 与sqldataReader
  4. SwiftUI之如何使用@EnvironmentObject在视图之间共享数据
  5. linux composer使用php,记录linux下composer使用的坑爹过程
  6. OSPFv3中LSA详解(八)——Type5类LSA详解
  7. 概率论-1.4 条件概率(重点:对P(A | B)、P(AB)、P(B)之间关系的理解)
  8. 结对项目-数独程序扩展
  9. 一日一签免费算卦_一日一签app免费算卦
  10. 六大类二叉树面试题汇总解答
  11. cousins什么意思_cousin是什么意思_cousin的翻译_音标_读音_用法_例句_爱词霸在线词典...
  12. 如何学习投资 推荐几本教材
  13. 《C系列-实践相关》C语言十
  14. Mac Terminal 终端:入门指南及进阶技巧
  15. 输入10个数字,然后逆序输出。
  16. ubuntu 里安装 OracleXE
  17. linux版本市场占有率,2020年5月OS市场占有率报告:Ubuntu和Linux分别占有1.89%和0.97%...
  18. python手工打码_使用Python + Selenium破解滑块验证码
  19. 《计算机系统与维护》— 计算机硬件的组成
  20. 计算机毕业设计SSM房屋租赁系统【附源码数据库】

热门文章

  1. 抗渗等级p6是什么意思_混凝土抗渗等级w4是什么意思?
  2. Candence中查看MOS管阈值电压Vth、Vgs、Vds、跨导gm、Id等详细MOS参数的方法
  3. 详解pandas编码函数pd.factorize()
  4. 崔希凡JavaWeb笔记day19-day21(2016年10月4日17:35:51)
  5. android支付宝系统繁忙,支付宝支付 系统繁忙,请稍后再试 62008 难道没人碰到过吗...
  6. 网络对抗技术 实验三
  7. angularjs2大漠穷秋视频笔记整理
  8. note-PythonCookbook-第十一章 网络与WEB编程
  9. UML工具Visual Paradigm最新版本16.2发布
  10. 工程化框架之feather