<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块。我想把它转换为文本并打印在屏幕上。
15 个回答
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')
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)
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
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元素的文本前添加一个带有-的新行。
0 人赞同
替换代码0】在段落之间放置一个换行。
from bs4 import Beautifulsoup
soup = Beautifulsoup(text)
print(soup.get_text('\n'))
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内的所有文本,理论上可以包括style和script标签。 进一步的过滤可以通过对body的模式的扩展来实现--即设置实例变量in_style或in_script。
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()
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
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)
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())
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'))
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或其他解析器解决方案那样证明错误。但你不需要任何第三方软件包。
0 人赞同
我在使用Scrapy时也遇到了同样的问题,你可以尝试在settings.py中加入这个内容
#settings.py
FEED_EXPORT_ENCODING = 'utf-8'
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.尊敬的女士们
衣服的颜色。医学专家
纵观全局,我们可以发现,在我们的生活中,有很多事情是需要我们去做的。在这里,我们可以看到,在我们的生活中,有很多人都在为我们的生活而努力,有很多人都在为我们的生活而奋斗。
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)