2013-03-25 12 views
9

uczę BeautifulSoup i znaleźć wiele rozwiązań „html2text”, ale jeden szukam powinna naśladować formatowanie:Python przekonwertować html do tekstu i formatowania naśladować

<ul> 
<li>One</li> 
<li>Two</li> 
</ul> 

staną

* One 
* Two 

i

Some text 
<blockquote> 
More magnificent text here 
</blockquote> 
Final text 

do

Some text 

    More magnificent text here 

Final text 

Czytam dokumenty, ale nie widzę niczego prostego. Jakaś pomoc? Jestem otwarty na używanie czegoś innego niż beautifulsoup.

+0

chcesz coś, co” Zamienisz tagi html na coś podobnego do formatu przeceny? –

Odpowiedz

9

Spójrz na skrypt Aarona Swartz'a: html2text (można zainstalować przy pomocy pip install html2text). Zwróć uwagę, że dane wyjściowe są ważne Markdown. Jeśli z jakiegoś powodu, że nie w pełni dla ciebie, niektóre dość trywialne szczypie powinien dostać dokładną moc w swoim pytaniu:

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 
+0

Przykłady na jego własnej stronie nie wyglądają wcale przyjaźnie dla użytkownika, biorąc pod uwagę obrazy, linki, a zwłaszcza lokalne linki zaczynające się od /. Może potrzebuję lepszego zrozumienia Markdown, ale czy możesz podać przykład sugerowanego ulepszenia? czy byłoby to zakodowane w funkcji html2text? – Mikhail

+0

@Mikhail - Nie jestem pewien, czy podążam - jak chcesz, aby linki, obrazy były obsługiwane? – root

+0

Powiedzmy, że obrazy mają zostać zignorowane, a linki mają format 'text (link)' Jego witryna jest w tej chwili niedostępna, więc nie mogę podać szczegółów. – Mikhail

5

mam kod dla bardziej prostego zadania: Usuń znaczniki HTML i wstawić nowe linie na odpowiednie miejsca. Może to może być dla ciebie punkt wyjścia.

Moduł Pythona textwrap może być pomocny przy tworzeniu wciętych bloków tekstu.

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 

Nie może być kilka zbędnych Wyrażenia regularne pozostawione w kodzie.

3

Wbudowany moduł html.parser w języku Python (HTMLParser we wcześniejszych wersjach) można łatwo rozszerzyć, aby utworzyć prostego tłumacza, który można dostosować do konkretnych potrzeb. Pozwala przechwycić pewne zdarzenia, gdy parser je przez HTML.

Ze względu na prostą naturę nie można nawigować po drzewie HTML, tak jak w przypadku Beautiful Soup (np. Rodzeństwo, dziecko, węzły rodzica itp.), Ale w przypadku prostego przypadku, takiego jak Twoje, powinno wystarczyć.

html.parser homepage

W twoim przypadku można użyć go w ten sposób, dodając odpowiednie formatowanie ilekroć jest napotkany start-tag lub end-tag określonego typu:

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