python 提取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-8

from time import time

import warc
from bs4 import BeautifulSoup
from selectolax.parser import HTMLParser

def get_text_bs(html):
    tree = BeautifulSoup(html, 'lxml')

    body = tree.body
    if body is None:
        return None

    for tag in body.select('script'):
        tag.decompose()
    for tag in body.select('style'):
        tag.decompose()

    text = body.get_text(separator='\n')
    return text

def get_text_selectolax(html):
    tree = HTMLParser(html)

    if tree.body is None:
        return None

    for tag in tree.css('script'):
        tag.decompose()
    for tag in tree.css('style'):
        tag.decompose()

    text = tree.body.text(separator='\n')
    return text

def read_doc(record, parser=get_text_selectolax):
    url = record.url
    text = None

    if 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, text

def process_warc(file_name, parser, limit=10000):
    warc_file = warc.open(file_name, 'rb')
    t0 = time()
    n_documents = 0
    for i, record in enumerate(warc_file):
        url, doc = read_doc(record, parser)

        if not doc or not url:
            continue

        n_documents += 1

        if i > limit:
            break

    warc_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

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

  • PyQuery
from pyquery import PyQuery as pq

text = pq(html).text()
  • selectolax
from selectolax.parser import HTMLParser

text = HTMLParser(html).text()
  • 正则表达式
import re

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

结果

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

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

我已经运行了很多次,结果非常稳定。重点是:selectolax比PyQuery快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个片段运行相同的基准时,新结果如下:

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

同样,selectolax击败PyQuery约6倍。

结论

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

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

(0)

相关推荐

  • Python识别html主要文本框过程解析

    这篇文章主要介绍了python识别html主要文本框过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在抓取网页的时候只想抓取主要的文本框,例如 csdn 中的主要文本框为下图红色框: 抓取的思想是,利用 bs4 查找所有的 div,用正则筛选出每个 div 里面的中文,找到中文字数最多的 div 就是属于正文的 div 了.定义一个抓取的头部抓取网页内容: import requests headers = { 'User-Agent'

  • Python转换HTML到Text纯文本的方法

    本文实例讲述了Python转换HTML到Text纯文本的方法.分享给大家供大家参考.具体分析如下: 今天项目需要将HTML转换为纯文本,去网上搜了一下,发现Python果然是神通广大,无所不能,方法是五花八门. 拿今天亲自试的两个方法举例,以方便后人: 方法一: 1. 安装nltk,可以去pipy装 (注:需要依赖以下包:numpy, PyYAML) 2.测试代码: 复制代码 代码如下: >>> import nltk  >>> aa = r''''' <html

  • python 将html转换为pdf的几种方法

    将 HTML 网页转换为 PDF 是很多人常见的一个需求,在浏览器上,我们可以通过浏览器的"打印"功能直接将网页打印输出为 PDF. 但是如果有多个网页就不好办了. 二进制软件 网络上存在很多将 HTML 转换为 PDF 的软件和工具.比较著名的有 Carelib.wkhtmltopdf. whtmltopdf wkhtmltopdf 真是一个优秀的 HTML 转换 PDF 工具.其借助 Qt 的 WebKit 渲染引擎,将 HTML 文档渲染导出为 PDF 文档或图像. 功能十分完善

  • python如何发送带有附件、正文为HTML的邮件

    一.HTML格式怎么发送右键 1.准备HTML代码作为内容 2.把邮件的subtype设置为html 3.发送 4.举个例子:自己发给自己一个HTML格式的文件 from email.mime.text import MIMEText ​ main_content = """ <!DOCTYPE html> <html lang = "en" <head> <meta charset = "UTF-8"

  • python爬虫 requests-html的使用

    一 介绍 Python上有一个非常著名的HTTP库--requests,相信大家都听说过,用过的人都说非常爽!现在requests库的作者又发布了一个新库,叫做requests-html,看名字也能猜出来,这是一个解析HTML的库,具备requests的功能以外,还新增了一些更加强大的功能,用起来比requests更爽!接下来我们来介绍一下它吧. # 官网解释 ''' This library intends to make parsing HTML (e.g. scraping the web

  • python爬虫beautifulsoup解析html方法

    用BeautifulSoup 解析html和xml字符串 实例: #!/usr/bin/python # -*- coding: UTF-8 -*- from bs4 import BeautifulSoup import re #待分析字符串 html_doc = """ <html> <head> <title>The Dormouse's story</title> </head> <body> &

  • python中HTMLParser模块知识点总结

    本章内容,我们主要来讲一下Python内置的HTML解析库HTMLParser模块,基本上也是应用于页面抓取上,假设,我们需要去收集页面上已存在的静态链接,但是页面肯定代码量都非常大,并且页面也很多,这样看来,会比较麻烦,工作量也非常大,这个时候,我们就可以用到htmlparser模块,一起来了解具体使用内容. 安装: npm install htmlparser htmlparser提供构造函数: function Parser(handler) { this._handler = handl

  • 关于pycharm 切换 python3.9 报错 ‘HTMLParser‘ object has no attribute ‘unescape‘ 的问题

    有的bug,莫名其妙就好了- python3.9 报错 "AttributeError: 'HTMLParser' object has no attribute 'unescape'" 异常分析解决. 一.问题描述 安装 python3.9 版本后,pycharm 中切换 python3.9 版本,创建虚拟环境报错:"AttributeError: 'HTMLParser' object has no attribute 'unescape'". Executed

  • python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)

    前言 python爬虫系列文章的第3篇介绍了网络请求库神器 Requests ,请求把数据返回来之后就要提取目标数据,不同的网站返回的内容通常有多种不同的格式,一种是 json 格式,这类数据对开发者来说最友好.另一种 XML 格式的,还有一种最常见格式的是 HTML 文档,今天就来讲讲如何从 HTML 中提取出感兴趣的数据 自己写个 HTML 解析器来解析吗?还是用正则表达式?这些都不是最好的办法,好在,Python 社区在这方便早就有了很成熟的方案,BeautifulSoup 就是这一类问题

  • Python HTMLTestRunner如何下载生成报告

    HTMLTestRunner下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html,选择HTMLTestRunner.py下载 2.打开显示这个样子滴,这里需要注意右击另存为pycharm的Lib\site-packages目录下(不然是没有用滴) 3.我使用的是python 3.7(看别人说需要改文件) 第94行,将import StringIO修改成import io 第539行,将self.outputBuffer = String

  • python邮件中附加文字、html、图片、附件实现方法

    关于python写邮件各种功能我们已经介绍过很多,大家有兴趣可以参考: python自动化发送邮件实例讲解 python实现发送QQ邮件(可加附件) 下面我们看下本次介绍的全部代码实例 import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.image import MIMEImage from email.header i

  • Python使用get_text()方法从大段html中提取文本的实例

    如下所示: <textarea rows="" cols="" name="id"><DIV style="TEXT-INDENT: 18pt; mso-char-indent-count: 2.0000" class=MsoNormal><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt; mso-spacerun: 'yes'; mso-font

随机推荐