相关文章推荐
阳刚的路灯  ·  String.raw() - ...·  1 月前    · 
苦恼的鸡蛋面  ·  Svelte ...·  2 周前    · 
果断的冲锋衣  ·  php - MySQL实验: ...·  2 年前    · 
礼貌的炒饭  ·  枚举与define的区别 - ...·  2 年前    · 

Input:

<div class="body"><p><strong></strong></p>
<p><strong></strong>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Consectetuer adipiscing elit. <a href="http://example.com/" target="_blank" class="source">Some Link</a> Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Aenean massa.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p></div>

Desired output:

意思是说,如果你是一个人,那么你就必须要有一个人的身份。医学博士 衣服的颜色。医学专家

纵观全局,我们可以发现,我们的工作并不轻松。 链接 Aenean commodo ligula eget dolor。医学专家

艾尼安 massa.Lorem ipsum dolor sit amet, consectetuer adipiscing elit.医学 衣服的颜色。医学专家

详见 意思是说,如果你是一个人,那么你就必须要有自己的想法。我的朋友们,你们好!我的朋友们,你们好!我的朋友们,你们好!我的朋友们,你们好!我的朋友们,你们好 医学专家

纵观全局,我们可以发现,我们的工作并不轻松。医学博士 丰富多样的活动。医学专家

I tried the html2text module without much success:

#!/usr/bin/env python
import urllib2
import html2text
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(urllib2.urlopen('http://example.com/page.html').read())
txt = soup.find('div', {'class' : 'body'})
print(html2text.html2text(txt))

txt对象产生上面的html块。我想把它转换为文本并打印在屏幕上。

1 个评论
你必须使用Python吗?lynx -dump filename.html就可以做到这一点。lynx.browser.org另外,你可以使用XPath表达式和w3.org/Tools/HTML-XML-utils.
python
html
web-scraping
text
beautifulsoup
Aaron Bandelli
Aaron Bandelli
发布于 2013-02-05
15 个回答
root
root
发布于 2022-01-18
已采纳
0 人赞同

soup.get_text()输出你想要的东西。

from bs4 import BeautifulSoup
soup = BeautifulSoup(html)
print(soup.get_text())

output:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Consectetuer adipiscing elit. Some Link Aenean commodo ligula eget dolor. Aenean massa
Aenean massa.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa

To keep newlines:

print(soup.get_text('\n'))

为了与你的例子相同,你可以用两个换行来替换一个换行。

soup.get_text().replace('\n','\n\n')
    
soup.get_text()正是我需要的。谢谢你!"。
很遗憾,只有BeautifulSoup 4。
这救了我一命!我更新了对Python3的回应,并加入了@t-8ch的换行想法。
FrBrGeorge
FrBrGeorge
发布于 2022-01-18
0 人赞同

使用Python标准可以做到这一点html.parser:

from html.parser import HTMLParser
class HTMLFilter(HTMLParser):
    text = ""
    def handle_data(self, data):
        self.text += data
f = HTMLFilter()
f.feed(data)
print(f.text)
    
Devy
这个答案非常好,没有第三方包的依赖!我的PyCharm编辑器提示我,我需要使用ABC混合器,这样就可以摆脱所有抽象方法需要实现的错误。gist.github.com/ye/050e898fbacdede5a6155da5b3db078d
请注意,初始化text的类属性和分配self.text的实例属性是不符合Pythonic的,但由于重新分配,在这里确实有效。如果我们使用一个可变的列表来代替(pieces = []self.pieces.append(data)),该类的所有实例将共享同一个列表对象。
很好的回答!虽然html并不是作为python2标准库的一部分可用。所以这个方案只适用于python3。
我在返回的文本中得到了一些javascript,但只有标准lib仍然很好。
ATOzTOA
ATOzTOA
发布于 2022-01-18
0 人赞同

你可以使用正则表达式,但不建议这样做。 下面的代码删除了你的数据中所有的HTML标签,给你的是文本。

import re
data = """<div class="body"><p><strong></strong></p>
<p><strong></strong>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Consectetuer adipiscing elit. <a href="http://example.com/" target="_blank" class="source">Some Link</a> Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Aenean massa.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p></div>"""
data = re.sub(r'<.*?>', '', data)
print(data)

Output

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Consectetuer adipiscing elit. Some Link Aenean commodo ligula eget dolor. Aenean massa
Aenean massa.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
    
@DaveJarvis Lol......在这里,OP并不想对HTML做什么,他只是想把HTML完全拔掉。
Still, stackoverflow.com/a/1732454/517371是非常有意义的。替换代码0】的问题比我在这里用600字列举的要多。
Andreas
Andreas
发布于 2022-01-18
0 人赞同

主要问题是你如何保持一些基本的格式化。这里是我自己的最低限度的方法,以保持新行和子弹。我确信这不是你想保留的所有东西的解决方案,但它是一个起点。

from bs4 import BeautifulSoup
def parse_html(html):
    elem = BeautifulSoup(html, features="html.parser")
    text = ''
    for e in elem.descendants:
        if isinstance(e, str):
            text += e.strip()
        elif e.name in ['br',  'p', 'h1', 'h2', 'h3', 'h4','tr', 'th']:
            text += '\n'
        elif e.name == 'li':
            text += '\n- '
    return text

上述内容为'br', 'p', 'h1', 'h2', 'h3', 'h4','tr', 'th'添加了一个新行 以及在li元素的文本前添加一个带有-的新行。

t-8ch
t-8ch
发布于 2022-01-18
0 人赞同

替换代码0】在段落之间放置一个换行。

from bs4 import Beautifulsoup
soup = Beautifulsoup(text)
print(soup.get_text('\n'))
    
如果你有换行符,In也会在句子中间放置换行符,例如:"<p>That's <strong>not</strong> what I want</p>"
我仍然在输出中看到XML元素(尽管那些不是严格的HTML元素,如[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG></o:AllowPNG>...。我怎样才能把这些也过滤掉?
我还想转换任何HTML字符,如&nbsp;&copy;
与@CsabaToth的问题相同。
Mark Chackerian
Mark Chackerian
发布于 2022-01-18
0 人赞同

I liked @FrBrGeorge's no dependency答案是如此之多,以至于我把它扩展到只提取body标签,并添加了一个方便的方法,以便HTML到文本是一个单行。

from abc import ABC
from html.parser import HTMLParser
class HTMLFilter(HTMLParser, ABC):
    A simple no dependency HTML -> TEXT converter.
    Usage:
          str_output = HTMLFilter.convert_html_to_text(html_input)
    def __init__(self, *args, **kwargs):
        self.text = ''
        self.in_body = False
        super().__init__(*args, **kwargs)
    def handle_starttag(self, tag: str, attrs):
        if tag.lower() == "body":
            self.in_body = True
    def handle_endtag(self, tag):
        if tag.lower() == "body":
            self.in_body = False
    def handle_data(self, data):
        if self.in_body:
            self.text += data
    @classmethod
    def convert_html_to_text(cls, html: str) -> str:
        f = cls()
        f.feed(html)
        return f.text.strip()           

用途见评论。

这就转换了body内的所有文本,理论上可以包括stylescript标签。 进一步的过滤可以通过对body的模式的扩展来实现--即设置实例变量in_stylein_script

dermasmid
dermasmid
发布于 2022-01-18
0 人赞同

这里有一些很好的东西,我也不妨把我的解决方案扔进去。

from html.parser import HTMLParser
def _handle_data(self, data):
    self.text += data + '\n'
HTMLParser.handle_data = _handle_data
def get_html_text(html: str):
    parser = HTMLParser()
    parser.text = ''
    parser.feed(html)
    return parser.text.strip()
    
emehex
emehex
发布于 2022-01-18
0 人赞同

凉拌菜这可能是一个不错的选择!

Input:

from gazpacho import Soup
html = """\
<div class="body"><p><strong></strong></p>
<p><strong></strong>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Consectetuer adipiscing elit. <a href="http://example.com/" target="_blank" class="source">Some Link</a> Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Aenean massa.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p>
<p>Consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa</p></div>

Output:

text = Soup(html).strip(whitespace=False) # to keep "\n" characters intact
print(text)
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Consectetuer adipiscing elit. Some Link Aenean commodo ligula eget dolor. Aenean massa
Aenean massa.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
Consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa
    
Joseph Roten
Joseph Roten
发布于 2022-01-18
0 人赞同

我需要一种方法在客户的系统上这样做,而不需要下载额外的库。我一直没有找到一个好的解决方案,所以我自己创建了一个。如果你喜欢,可以随意使用。

import urllib 
def html2text(strText):
    str1 = strText
    int2 = str1.lower().find("<body")
    if int2>0:
       str1 = str1[int2:]
    int2 = str1.lower().find("</body>")
    if int2>0:
       str1 = str1[:int2]
    list1 = ['<br>',  '<tr',  '<td', '</p>', 'span>', 'li>', '</h', 'div>' ]
    list2 = [chr(13), chr(13), chr(9), chr(13), chr(13),  chr(13), chr(13), chr(13)]
    bolFlag1 = True
    bolFlag2 = True
    strReturn = ""
    for int1 in range(len(str1)):
      str2 = str1[int1]
      for int2 in range(len(list1)):
        if str1[int1:int1+len(list1[int2])].lower() == list1[int2]:
           strReturn = strReturn + list2[int2]
      if str1[int1:int1+7].lower() == '<script' or str1[int1:int1+9].lower() == '<noscript':
         bolFlag1 = False
      if str1[int1:int1+6].lower() == '<style':
         bolFlag1 = False
      if str1[int1:int1+7].lower() == '</style':
         bolFlag1 = True
      if str1[int1:int1+9].lower() == '</script>' or str1[int1:int1+11].lower() == '</noscript>':
         bolFlag1 = True
      if str2 == '<':
         bolFlag2 = False
      if bolFlag1 and bolFlag2 and (ord(str2) != 10) :
        strReturn = strReturn + str2
      if str2 == '>':
         bolFlag2 = True
      if bolFlag1 and bolFlag2:
        strReturn = strReturn.replace(chr(32)+chr(13), chr(13))
        strReturn = strReturn.replace(chr(9)+chr(13), chr(13))
        strReturn = strReturn.replace(chr(13)+chr(32), chr(13))
        strReturn = strReturn.replace(chr(13)+chr(9), chr(13))
        strReturn = strReturn.replace(chr(13)+chr(13), chr(13))
    strReturn = strReturn.replace(chr(13), '\n')
    return strReturn
url = "http://www.theguardian.com/world/2014/sep/25/us-air-strikes-islamic-state-oil-isis"    
html = urllib.urlopen(url).read()    
print html2text(html)
    
被降权的原因是缩进不当。由于该代码的复杂程度中等。要解决这个问题有点困难。
Sarah Messer
Sarah Messer
发布于 2022-01-18
0 人赞同

可以使用BeautifulSoup来删除不需要的脚本和类似的东西,尽管你可能需要在几个不同的网站上进行试验,以确保你已经涵盖了你希望排除的不同类型的东西。 试试这个。

from requests import get
from bs4 import BeautifulSoup as BS
response = get('http://news.bbc.co.uk/2/hi/health/2284783.stm')
soup = BS(response.content, "html.parser")
for child in soup.body.children:
   if child.name == 'script':
       child.decompose() 
print(soup.body.get_text())
    
ccpizza
ccpizza
发布于 2022-01-18
0 人赞同

一个两步法lxml-基于标记的方法,在转换为纯文本之前对标记进行消毒。

该脚本接受HTML文件的路径或管道输入的stdin。

将删除脚本块和所有可能不需要的文本。你可以配置lxml清洗剂适应你的需求的实例。

#!/usr/bin/env python3
import sys
from lxml import html
from lxml.html import tostring
from lxml.html.clean import Cleaner
def sanitize(dirty_html):
    cleaner = Cleaner(page_structure=True,
                  meta=True,
                  embedded=True,
                  links=True,
                  style=True,
                  processing_instructions=True,
                  inline_style=True,
                  scripts=True,
                  javascript=True,
                  comments=True,
                  frames=True,
                  forms=True,
                  annoying_tags=True,
                  remove_unknown_tags=True,
                  safe_attrs_only=True,
                  safe_attrs=frozenset(['src','color', 'href', 'title', 'class', 'name', 'id']),
                  remove_tags=('span', 'font', 'div')
    return cleaner.clean_html(dirty_html)
if len(sys.argv) > 1:
  fin = open(sys.argv[1], encoding='utf-8')
else:
  fin = sys.stdin
source = fin.read()
source = sanitize(source)
source = source.replace('<br>', '\n')
tree = html.fromstring(source)
plain = tostring(tree, method='text', encoding='utf-8')
print(plain.decode('utf-8'))
    
quick
quick
发布于 2022-01-18
0 人赞同

我个人喜欢Gazpacho方案,由emehex, but it only use regular expression for filtering out the tags. No more magic. This means that solution keep text inside <style> and <script>.

所以我宁愿实现一个基于正则表达式的简单解决方案,并使用标准的Python 3.4库来取消HTML实体。

import re
from html import unescape
def html_to_text(html):
    # use non-greedy for remove scripts and styles
    text = re.sub("<script.*?</script>", "", html, flags=re.DOTALL)
    text = re.sub("<style.*?</style>", "", text, flags=re.DOTALL)
    # remove other tags
    text = re.sub("<[^>]+>", " ", text)
    # strip whitespace
    text = " ".join(text.split())
    # unescape html entities
    text = unescape(text)
    return text

当然,这并不能像BeautifulSoup或其他解析器解决方案那样证明错误。但你不需要任何第三方软件包。

Jaypee Tan
Jaypee Tan
发布于 2022-01-18
0 人赞同

我在使用Scrapy时也遇到了同样的问题,你可以尝试在settings.py中加入这个内容

#settings.py
FEED_EXPORT_ENCODING = 'utf-8'
    
chicchera
chicchera
发布于 2022-01-18
0 人赞同

有一个库叫inscripts真的很简单和轻便,可以从一个文件或直接从一个URL获得输入。

from inscriptis import get_text
text = get_text(html)
print(text)

The output is:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.尊敬的女士们 衣服的颜色。医学专家

纵观全局,我们可以从以下几个方面入手。一些链接 Aenean commodo ligula eget 遗憾的是。医学专家

Aenean massa.Lorem ipsum dolor sit amet, consectetuer adipiscing 意思是说。我们的目标是要让我们的生活更美好。医学专家

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.尊敬的女士们 衣服的颜色。医学专家

纵观全局,我们可以发现,在我们的生活中,有很多事情是需要我们去做的。在这里,我们可以看到,在我们的生活中,有很多人都在为我们的生活而努力,有很多人都在为我们的生活而奋斗。

Ivy Chiu
Ivy Chiu
发布于 2022-01-18
0 人赞同
from html.parser import HTMLParser
class HTMLFilter(HTMLParser):
    text = ''
    def handle_data(self, data):
        self.text += f'{data}\n'
def html2text(html):
    filter = HTMLFilter()
    filter.feed(html)