Python将html转换为文本并模仿格式

时间:2013-03-25 05:57:37

标签: python html beautifulsoup

我正在学习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 个答案:

答案 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树(例如兄弟姐妹,孩子,父节点等),但对于像您这样的简单案例,它应该足够了。

html.parser homepage

在您的情况下,只要遇到特定类型的起始标记或结束标记,您就可以通过添加适当的格式来使用它:

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()