我正在学习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以外的东西。
答案 0 :(得分:11)
看看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
答案 1 :(得分: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
代码中可能还有一些多余的正则表达式。
答案 2 :(得分:3)
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))
答案 3 :(得分:0)
在使用samaspin的解决方案时,如果存在非英语的unicode字符,则解析器将停止工作并仅返回一个空字符串。初始化每个循环的解析器可确保即使解析器对象损坏,它也不会为后续解析返回空字符串。添加到samaspin的解决方案中,还处理<br>
标签。
在处理HTML代码而不清洗html标签方面,可以添加后续标签,并将其预期输出写入功能handle_starttag
class MyHTMLParser(HTMLParser):
"""
This class will be used to clean the html tags whilst ensuring the
format is maintained. Therefore all the whitespces, newlines, linebrakes, etc are
converted from html tags to their respective counterparts in python.
"""
def __init__(self):
HTMLParser.__init__(self)
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'
elif tag == 'br':
self.output += linesep + '\n'
def handle_endtag(self, tag):
if tag == 'blockquote':
self.output += linesep + linesep
parser = MyHTMLParser()