Python将HTML转换为文本并模仿格式
我正在学习BeautifulSoup,发现了很多关于“html2text”的解决方案,但我想要的那个应该能保持格式:
<ul>
<li>One</li>
<li>Two</li>
</ul>
会变成
* One
* Two
而且
Some text
<blockquote>
More magnificent text here
</blockquote>
Final text
到
Some text
More magnificent text here
Final text
我在看文档,但没有找到简单明了的内容。有谁能帮帮我吗?我也愿意尝试其他的工具,不一定非要用beautifulsoup。
4 个回答
4
Python自带的html.parser模块(在早期版本中叫HTMLParser)可以很容易地扩展,创建一个简单的翻译器,能够根据你的具体需求进行定制。这个模块允许你在解析HTML时,抓住某些事件。
由于它的简单性,你不能像使用Beautiful Soup那样在HTML树中自由导航(比如访问兄弟节点、子节点、父节点等),但对于你这种简单的情况来说,应该已经足够了。
在你的情况下,你可以这样使用它,每当遇到特定类型的开始标签或结束标签时,添加适当的格式:
from html.parser import HTMLParser
from os import linesep
class MyHTMLParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self, strict=False)
def feed(self, in_html):
self.output = ""
super(MyHTMLParser, self).feed(in_html)
return self.output
def handle_data(self, data):
self.output += data.strip()
def handle_starttag(self, tag, attrs):
if tag == 'li':
self.output += linesep + '* '
elif tag == 'blockquote' :
self.output += linesep + linesep + '\t'
def handle_endtag(self, tag):
if tag == 'blockquote':
self.output += linesep + linesep
parser = MyHTMLParser()
content = "<ul><li>One</li><li>Two</li></ul>"
print(linesep + "Example 1:")
print(parser.feed(content))
content = "Some text<blockquote>More magnificent text here</blockquote>Final text"
print(linesep + "Example 2:")
print(parser.feed(content))
5
我有一段代码,可以用来做一个比较简单的任务:去掉HTML标签,并在合适的地方插入换行符。也许这可以作为你的一个起点。
Python的textwrap
模块可能对创建缩进的文本块很有帮助。
http://docs.python.org/2/library/textwrap.html
class HtmlTool(object):
"""
Algorithms to process HTML.
"""
#Regular expressions to recognize different parts of HTML.
#Internal style sheets or JavaScript
script_sheet = re.compile(r"<(script|style).*?>.*?(</\1>)",
re.IGNORECASE | re.DOTALL)
#HTML comments - can contain ">"
comment = re.compile(r"<!--(.*?)-->", re.DOTALL)
#HTML tags: <any-text>
tag = re.compile(r"<.*?>", re.DOTALL)
#Consecutive whitespace characters
nwhites = re.compile(r"[\s]+")
#<p>, <div>, <br> tags and associated closing tags
p_div = re.compile(r"</?(p|div|br).*?>",
re.IGNORECASE | re.DOTALL)
#Consecutive whitespace, but no newlines
nspace = re.compile("[^\S\n]+", re.UNICODE)
#At least two consecutive newlines
n2ret = re.compile("\n\n+")
#A return followed by a space
retspace = re.compile("(\n )")
#For converting HTML entities to unicode
html_parser = HTMLParser.HTMLParser()
@staticmethod
def to_nice_text(html):
"""Remove all HTML tags, but produce a nicely formatted text."""
if html is None:
return u""
text = unicode(html)
text = HtmlTool.script_sheet.sub("", text)
text = HtmlTool.comment.sub("", text)
text = HtmlTool.nwhites.sub(" ", text)
text = HtmlTool.p_div.sub("\n", text) #convert <p>, <div>, <br> to "\n"
text = HtmlTool.tag.sub("", text) #remove all tags
text = HtmlTool.html_parser.unescape(text)
#Get whitespace right
text = HtmlTool.nspace.sub(" ", text)
text = HtmlTool.retspace.sub("\n", text)
text = HtmlTool.n2ret.sub("\n\n", text)
text = text.strip()
return text
代码中可能还有一些多余的正则表达式。
15
看看Aaron Swartz的html2text脚本(可以通过pip install html2text
来安装)。请注意,输出结果是有效的Markdown格式。如果出于某种原因这个输出不完全符合你的需求,做一些简单的调整就能得到你问题中提到的确切输出:
In [1]: import html2text
In [2]: h1 = """<ul>
...: <li>One</li>
...: <li>Two</li>
...: </ul>"""
In [3]: print html2text.html2text(h1)
* One
* Two
In [4]: h2 = """<p>Some text
...: <blockquote>
...: More magnificent text here
...: </blockquote>
...: Final text</p>"""
In [5]: print html2text.html2text(h2)
Some text
> More magnificent text here
Final text