Wyodrębnianie tekstu z pliku HTML za pomocą Pythona

243

Chciałbym wyodrębnić tekst z pliku HTML za pomocą Pythona. Chcę zasadniczo taki sam wynik, jaki uzyskałbym, gdy skopiowałem tekst z przeglądarki i wkleiłem go do notatnika.

Chciałbym czegoś bardziej niezawodnego niż używanie wyrażeń regularnych, które mogą zawieść na źle sformatowanym HTML. Widziałem wiele osób polecających piękną zupę, ale miałem kilka problemów z jej użyciem. Po pierwsze, odebrał niechciany tekst, na przykład źródło JavaScript. Ponadto nie interpretował encji HTML. Na przykład oczekiwałbym & # 39; w źródle HTML do konwersji na apostrof w tekście, tak jak gdybym wkleił zawartość przeglądarki do notatnika.

Aktualizacja html2text wygląda obiecująco. Obsługuje jednostki HTML poprawnie i ignoruje JavaScript. Jednak nie produkuje dokładnie zwykłego tekstu; generuje przecenę, którą należałoby przekształcić w zwykły tekst. Nie zawiera przykładów ani dokumentacji, ale kod wygląda na czysty.


Powiązane pytania:

John D. Cook
źródło
Od dłuższego czasu wydaje mi się, że moja odpowiedź NLTK (całkiem nowa) jest niezwykle przydatna, więc możesz rozważyć zmianę zaakceptowanej odpowiedzi. Dzięki!
Shatu,
1
Nigdy nie myślałem, że natrafię na pytanie zadane przez autora mojego ulubionego bloga! The Endeavour!
Ryan G
1
@Shatu Teraz, gdy Twoje rozwiązanie straciło ważność, możesz usunąć swój komentarz. Dzięki! ;)
Sна16ошƒаӽ

Odpowiedzi:

136

html2text to program w języku Python, który robi w tym całkiem niezłą robotę.

RexE
źródło
5
bit to gpl 3.0, co oznacza, że ​​może być niekompatybilny
frog32
138
Niesamowity! jego autorem jest RIP Aaron Swartz.
Atul Arvind,
2
Czy ktoś znalazł jakieś alternatywy dla html2text z powodu GPL 3.0?
jontsai
1
GPL nie jest tak zła, jak ludzie tego chcą. Aaron wiedział najlepiej.
Steve K
2
Próbowałem zarówno html2text, jak i nltk, ale one nie działały dla mnie. Skończyło się na Beautiful Soup 4, która działa pięknie (bez zamierzonej gry słów).
Ryan
150

Najlepszy kawałek kodu, jaki znalazłem do wyodrębniania tekstu bez uzyskiwania javascript lub niepotrzebnych rzeczy:

import urllib
from bs4 import BeautifulSoup

url = "http://news.bbc.co.uk/2/hi/health/2284783.stm"
html = urllib.urlopen(url).read()
soup = BeautifulSoup(html)

# kill all script and style elements
for script in soup(["script", "style"]):
    script.extract()    # rip it out

# get text
text = soup.get_text()

# break into lines and remove leading and trailing space on each
lines = (line.strip() for line in text.splitlines())
# break multi-headlines into a line each
chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
# drop blank lines
text = '\n'.join(chunk for chunk in chunks if chunk)

print(text)

Musisz tylko zainstalować BeautifulSoup przed:

pip install beautifulsoup4
PeYoTlL
źródło
2
Jak jeśli chcemy wybrać jakąś linię, właśnie powiedziałem, linię nr 3?
hepidad
3
Skrypty do zabijania trochę, wybawicielu !!
Nanda,
2
Po przejrzeniu wielu odpowiedzi na przepełnienie stosu wydaje mi się, że jest to dla mnie najlepsza opcja. Jednym z napotkanych przeze mnie problemów jest to, że w niektórych przypadkach linie były dodawane razem. Udało mi się to pokonać, dodając separator w funkcji get_text:text = soup.get_text(separator=' ')
Joswin KJ
5
Zamiast tego soup.get_text()użyłem soup.body.get_text(), aby nie uzyskać żadnego tekstu z <headelementu>, takiego jak tytuł.
Sjoerd
10
Dla Pythona 3from urllib.request import urlopen
Jacob Kalakal Joseph
99

UWAGA: NTLK nie obsługuje już clean_htmlfunkcji

Oryginalna odpowiedź poniżej i alternatywa w sekcjach komentarzy.


Użyj NLTK

Zmarnowałem swoje 4-5 godzin na rozwiązywanie problemów z html2text. Na szczęście mogłem spotkać NLTK.
Działa magicznie.

import nltk   
from urllib import urlopen

url = "http://news.bbc.co.uk/2/hi/health/2284783.stm"    
html = urlopen(url).read()    
raw = nltk.clean_html(html)  
print(raw)
Shatu
źródło
8
czasem to wystarczy :)
Sharmila,
8
Chcę pod głosować to tysiąc razy. Utknąłem w regexowym piekle, ale oto widzę mądrość NLTK.
BenDundee
26
Najwyraźniej clean_html nie jest już obsługiwany: github.com/nltk/nltk/commit/…
alexanderlukanin13
5
importowanie ciężkiej biblioteki takiej jak nltk do tak prostego zadania byłoby zbyt duże
Richie,
54
@ alexanderlukanin13 Ze źródła:raise NotImplementedError ("To remove HTML markup, use BeautifulSoup's get_text() function")
Chris Arena
54

Znalazłem się dzisiaj w obliczu tego samego problemu. Napisałem bardzo prosty parser HTML, aby usunąć przychodzące treści ze wszystkich znaczników, zwracając pozostały tekst z minimalnym formatowaniem.

from HTMLParser import HTMLParser
from re import sub
from sys import stderr
from traceback import print_exc

class _DeHTMLParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.__text = []

    def handle_data(self, data):
        text = data.strip()
        if len(text) > 0:
            text = sub('[ \t\r\n]+', ' ', text)
            self.__text.append(text + ' ')

    def handle_starttag(self, tag, attrs):
        if tag == 'p':
            self.__text.append('\n\n')
        elif tag == 'br':
            self.__text.append('\n')

    def handle_startendtag(self, tag, attrs):
        if tag == 'br':
            self.__text.append('\n\n')

    def text(self):
        return ''.join(self.__text).strip()


def dehtml(text):
    try:
        parser = _DeHTMLParser()
        parser.feed(text)
        parser.close()
        return parser.text()
    except:
        print_exc(file=stderr)
        return text


def main():
    text = r'''
        <html>
            <body>
                <b>Project:</b> DeHTML<br>
                <b>Description</b>:<br>
                This small script is intended to allow conversion from HTML markup to 
                plain text.
            </body>
        </html>
    '''
    print(dehtml(text))


if __name__ == '__main__':
    main()
Xperroni
źródło
5
To wydaje się być najprostszym sposobem na zrobienie tego w Pythonie (2.7) przy użyciu tylko domyślnych modułów. Co jest naprawdę głupie, ponieważ jest to tak często potrzebna rzecz i nie ma dobrego powodu, dla którego nie ma parsera w domyślnym module HTMLParser.
Ingmar Hupp
2
Nie sądzę, że przekonwertuje znaki HTML na Unicode, prawda? Na przykład &amp;nie zostanie przekonwertowany na &, prawda?
speedplane
Do użytku w Pythonie 3from html.parser import HTMLParser
sebhaase
14

Oto wersja odpowiedzi Xperroni, która jest nieco bardziej kompletna. Pomija sekcje skryptów i stylów oraz tłumaczy charrefs (np. & # 39;) i encje HTML (np. & Amp;).

Zawiera także trywialny odwrotny konwerter zwykłego tekstu na HTML.

"""
HTML <-> text conversions.
"""
from HTMLParser import HTMLParser, HTMLParseError
from htmlentitydefs import name2codepoint
import re

class _HTMLToText(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self._buf = []
        self.hide_output = False

    def handle_starttag(self, tag, attrs):
        if tag in ('p', 'br') and not self.hide_output:
            self._buf.append('\n')
        elif tag in ('script', 'style'):
            self.hide_output = True

    def handle_startendtag(self, tag, attrs):
        if tag == 'br':
            self._buf.append('\n')

    def handle_endtag(self, tag):
        if tag == 'p':
            self._buf.append('\n')
        elif tag in ('script', 'style'):
            self.hide_output = False

    def handle_data(self, text):
        if text and not self.hide_output:
            self._buf.append(re.sub(r'\s+', ' ', text))

    def handle_entityref(self, name):
        if name in name2codepoint and not self.hide_output:
            c = unichr(name2codepoint[name])
            self._buf.append(c)

    def handle_charref(self, name):
        if not self.hide_output:
            n = int(name[1:], 16) if name.startswith('x') else int(name)
            self._buf.append(unichr(n))

    def get_text(self):
        return re.sub(r' +', ' ', ''.join(self._buf))

def html_to_text(html):
    """
    Given a piece of HTML, return the plain text it contains.
    This handles entities and char refs, but not javascript and stylesheets.
    """
    parser = _HTMLToText()
    try:
        parser.feed(html)
        parser.close()
    except HTMLParseError:
        pass
    return parser.get_text()

def text_to_html(text):
    """
    Convert the given text to html, wrapping what looks like URLs with <a> tags,
    converting newlines to <br> tags and converting confusing chars into html
    entities.
    """
    def f(mo):
        t = mo.group()
        if len(t) == 1:
            return {'&':'&amp;', "'":'&#39;', '"':'&quot;', '<':'&lt;', '>':'&gt;'}.get(t)
        return '<a href="%s">%s</a>' % (t, t)
    return re.sub(r'https?://[^] ()"\';]+|[&\'"<>]', f, text)
bit4
źródło
W get_text '' .join powinno być '' .join. Powinna być pusta przestrzeń, w przeciwnym razie niektóre teksty połączą się.
Obinna Nnenanya
1
Ponadto nie będzie to obejmować WSZYSTKICH tekstów, z wyjątkiem innych tagów kontenera tekstu, takich jak H1, H2 ...., span itp. Musiałem go dostosować, aby uzyskać lepszy zasięg.
Obinna Nnenanya
11

Wiem, że jest już wiele odpowiedzi, ale najbardziej eleganckie i pytoniczne rozwiązanie, które znalazłem, zostało częściowo opisane tutaj .

from bs4 import BeautifulSoup

text = ''.join(BeautifulSoup(some_html_string, "html.parser").findAll(text=True))

Aktualizacja

Na podstawie komentarza Frasera, oto bardziej eleganckie rozwiązanie:

from bs4 import BeautifulSoup

clean_text = ''.join(BeautifulSoup(some_html_string, "html.parser").stripped_strings)
Floyd
źródło
2
Aby uniknąć ostrzeżenia, określ parser, którego ma używać BeautifulSoup:text = ''.join(BeautifulSoup(some_html_string, "lxml").findAll(text=True))
Floyd,
Możesz użyć generatora stripped_strings, aby uniknąć nadmiernej spacji - tj.clean_text = ''.join(BeautifulSoup(some_html_string, "html.parser").stripped_strings
Fraser
8

Możesz także użyć metody html2text w bibliotece stripogramów.

from stripogram import html2text
text = html2text(your_html_string)

Aby zainstalować stripogram, uruchom sudo easy_install stripogram

GeekTantra
źródło
23
Ten moduł, zgodnie ze stroną pypi , jest przestarzały: „Chyba że masz jakiś historyczny powód korzystania z tego pakietu, odradzam go!”
intuicyjnie
7

Istnieje biblioteka wzorców do eksploracji danych.

http://www.clips.ua.ac.be/pages/pattern-web

Możesz nawet zdecydować, które tagi zachować:

s = URL('http://www.clips.ua.ac.be').download()
s = plaintext(s, keep={'h1':[], 'h2':[], 'strong':[], 'a':['href']})
print s
Nuncjo
źródło
6

PyParsing wykonuje świetną robotę. Wiki PyParsing zostało zabite, więc tutaj jest inna lokalizacja, w której znajdują się przykłady użycia PyParsing ( przykładowy link ). Jednym z powodów, dla których warto poświęcić trochę czasu na pyparsowanie, jest to, że napisał również bardzo krótki, dobrze zorganizowany podręcznik O'Reilly Short Cut, który jest również niedrogi.

Powiedziawszy to, często używam BeautifulSoup i nie jest tak trudno poradzić sobie z problemami z podmiotami, możesz je przekonwertować przed uruchomieniem BeautifulSoup.

Powodzenia

PyNEwbie
źródło
1
Link jest martwy lub zepsuty.
Yvette,
4

To nie jest dokładnie rozwiązanie Pythona, ale przekształci tekst, który JavaScript wygeneruje w tekst, co moim zdaniem jest ważne (EG google.com). Łącza przeglądarki (nie Lynx) mają silnik Javascript i przekonwertują kod źródłowy na tekst za pomocą opcji -dump.

Więc możesz zrobić coś takiego:

fname = os.tmpnam()
fname.write(html_source)
proc = subprocess.Popen(['links', '-dump', fname], 
                        stdout=subprocess.PIPE,
                        stderr=open('/dev/null','w'))
text = proc.stdout.read()
Andrzej
źródło
4

Zamiast modułu HTMLParser sprawdź htmllib. Ma podobny interfejs, ale wykonuje dla ciebie więcej pracy. (Jest dość starożytny, więc nie pomaga w pozbyciu się javascript i css. Możesz stworzyć klasę pochodną, ​​ale dodać metody o nazwach takich jak start_script i end_style (szczegóły w dokumentacji Pythona), ale jest to trudne zrobić to niezawodnie w przypadku zniekształconego html.) W każdym razie oto coś prostego, co drukuje zwykły tekst na konsoli

from htmllib import HTMLParser, HTMLParseError
from formatter import AbstractFormatter, DumbWriter
p = HTMLParser(AbstractFormatter(DumbWriter()))
try: p.feed('hello<br>there'); p.close() #calling close is not usually needed, but let's play it safe
except HTMLParseError: print ':(' #the html is badly malformed (or you found a bug)
znak
źródło
NB: HTMLError i HTMLParserError powinny czytać zarówno HTMLParseError. Działa to, ale źle radzi sobie z utrzymywaniem podziałów linii.
Dave Knight
4

Polecam pakiet Python o nazwie goose-extractor Goose spróbuje wyodrębnić następujące informacje:

Główny tekst artykułu Główny obraz artykułu Wszelkie filmy z Youtube / Vimeo osadzone w artykule Meta Opis Meta tagi

Więcej: https://pypi.python.org/pypi/goose-extractor/

Li Yingjun
źródło
4

jeśli potrzebujesz większej prędkości i mniejszej dokładności, możesz użyć raw lxml.

import lxml.html as lh
from lxml.html.clean import clean_html

def lxml_to_text(html):
    doc = lh.fromstring(html)
    doc = clean_html(doc)
    return doc.text_content()
Anton Shelin
źródło
4

zainstaluj html2text za pomocą

pip zainstaluj html2text

następnie,

>>> import html2text
>>>
>>> h = html2text.HTML2Text()
>>> # Ignore converting links from HTML
>>> h.ignore_links = True
>>> print h.handle("<p>Hello, <a href='http://earth.google.com/'>world</a>!")
Hello, world!
Pravitha V.
źródło
4

Wiem, że wiele odpowiedzi tutaj już ale myślę newspaper3k również zasługuje na wzmiankę. Niedawno musiałem wykonać podobne zadanie wyodrębnienia tekstu z artykułów w Internecie, a biblioteka ta wykonała świetną robotę, osiągając to do tej pory w moich testach. Ignoruje tekst znajdujący się w elementach menu i paskach bocznych, a także w dowolnym JavaScript, który pojawia się na stronie, gdy żąda OP.

from newspaper import Article

article = Article(url)
article.download()
article.parse()
article.text

Jeśli masz już pobrane pliki HTML, możesz zrobić coś takiego:

article = Article('')
article.set_html(html)
article.parse()
article.text

Ma nawet kilka funkcji NLP do podsumowywania tematów artykułów:

article.nlp()
article.summary
spatel4140
źródło
3

Piękna zupa przekształca jednostki HTML. Jest to prawdopodobnie najlepszy wybór, biorąc pod uwagę, że HTML jest często błędny i pełen problemów z kodowaniem Unicode i HTML. Oto kod, którego używam do konwersji html na surowy tekst:

import BeautifulSoup
def getsoup(data, to_unicode=False):
    data = data.replace("&nbsp;", " ")
    # Fixes for bad markup I've seen in the wild.  Remove if not applicable.
    masssage_bad_comments = [
        (re.compile('<!-([^-])'), lambda match: '<!--' + match.group(1)),
        (re.compile('<!WWWAnswer T[=\w\d\s]*>'), lambda match: '<!--' + match.group(0) + '-->'),
    ]
    myNewMassage = copy.copy(BeautifulSoup.BeautifulSoup.MARKUP_MASSAGE)
    myNewMassage.extend(masssage_bad_comments)
    return BeautifulSoup.BeautifulSoup(data, markupMassage=myNewMassage,
        convertEntities=BeautifulSoup.BeautifulSoup.ALL_ENTITIES 
                    if to_unicode else None)

remove_html = lambda c: getsoup(c, to_unicode=True).getText(separator=u' ') if c else ""
szybowiec
źródło
3

Inną opcją jest uruchomienie html przez przeglądarkę tekstową i zrzucenie go. Na przykład (przy użyciu Lynx):

lynx -dump html_to_convert.html > converted_html.txt

Można to zrobić w skrypcie python w następujący sposób:

import subprocess

with open('converted_html.txt', 'w') as outputFile:
    subprocess.call(['lynx', '-dump', 'html_to_convert.html'], stdout=testFile)

Nie da ci dokładnie tylko tekstu z pliku HTML, ale w zależności od przypadku użycia może być lepszym rozwiązaniem niż wyjście html2text.

John Lucas
źródło
3

Najlepsze dla mnie były napisy.

https://github.com/weblyzard/inscriptis

import urllib.request
from inscriptis import get_text

url = "http://www.informationscience.ch"
html = urllib.request.urlopen(url).read().decode('utf-8')

text = get_text(html)
print(text)

Wyniki są naprawdę dobre

Wigor
źródło
2

Inne rozwiązanie niebędące pythonem: Libre Office:

soffice --headless --invisible --convert-to txt input1.html

Powodem, dla którego wolę tę niż inne alternatywy, jest to, że każdy akapit HTML jest konwertowany na jedną linię tekstu (bez podziałów linii), czego szukałem. Inne metody wymagają przetwarzania końcowego. Lynx produkuje niezłe wyniki, ale nie dokładnie to, czego szukałem. Poza tym Libre Office może być wykorzystywany do konwersji z różnych formatów ...

JakowK
źródło
2

Czy ktoś próbował bleach.clean(html,tags=[],strip=True)z wybielaczem ? to działa dla mnie.

rox
źródło
Wydaje się również, że działa dla mnie, ale nie zaleca się używania go w tym celu: „Ta funkcja jest funkcją ukierunkowaną na bezpieczeństwo, której jedynym celem jest usunięcie złośliwej zawartości z łańcucha, tak aby mogła być wyświetlana jako treść w sieci strona." -> bleach.readthedocs.io/en/latest/clean.html#bleach.clean
Loktopus
2

Mam dobre wyniki z Apache Tika . Jego celem jest wyodrębnianie metadanych i tekstu z zawartości, dlatego bazowy analizator składni jest odpowiednio dostosowywany po wyjęciu z pudełka.

Tika może być uruchamiana jako serwer , uruchamianie / wdrażanie w kontenerze Docker jest banalne, a stamtąd można uzyskać do niej dostęp poprzez powiązania Pythona .

u-phoria
źródło
1

w prosty sposób

import re

html_text = open('html_file.html').read()
text_filtered = re.sub(r'<(.*?)>', '', html_text)

ten kod znajduje wszystkie części tekstu HTML zaczynające się od „<” i kończące się na „>” i zastępuje wszystkie znalezione pustym ciągiem

David Fraga
źródło
1

Odpowiedź @ PeYoTIL przy użyciu BeautifulSoup i eliminacji stylu i treści skryptu nie działała dla mnie. Wypróbowałem go decomposezamiast, extractale nadal nie działało. Więc stworzyłem własny, który również formatuje tekst za pomocą <p>tagów i zamienia <a>tagi na link href. Radzi sobie również z linkami w tekście. Dostępne w tym zestawieniu z osadzonym dokumentem testowym.

from bs4 import BeautifulSoup, NavigableString

def html_to_text(html):
    "Creates a formatted text email message as a string from a rendered html template (page)"
    soup = BeautifulSoup(html, 'html.parser')
    # Ignore anything in head
    body, text = soup.body, []
    for element in body.descendants:
        # We use type and not isinstance since comments, cdata, etc are subclasses that we don't want
        if type(element) == NavigableString:
            # We use the assumption that other tags can't be inside a script or style
            if element.parent.name in ('script', 'style'):
                continue

            # remove any multiple and leading/trailing whitespace
            string = ' '.join(element.string.split())
            if string:
                if element.parent.name == 'a':
                    a_tag = element.parent
                    # replace link text with the link
                    string = a_tag['href']
                    # concatenate with any non-empty immediately previous string
                    if (    type(a_tag.previous_sibling) == NavigableString and
                            a_tag.previous_sibling.string.strip() ):
                        text[-1] = text[-1] + ' ' + string
                        continue
                elif element.previous_sibling and element.previous_sibling.name == 'a':
                    text[-1] = text[-1] + ' ' + string
                    continue
                elif element.parent.name == 'p':
                    # Add extra paragraph formatting newline
                    string = '\n' + string
                text += [string]
    doc = '\n'.join(text)
    return doc
racitup
źródło
1
Dzięki, ta odpowiedź jest niedoceniana. Dla tych z nas, którzy chcą mieć czystą reprezentację tekstową, która zachowuje się bardziej jak przeglądarka (ignorowanie znaków nowej linii i uwzględnianie tylko akapitów i podziałów wierszy), BeautifulSoup get_textpo prostu tego nie wycina.
jrial
@jrial cieszę się, że okażą się przydatne, również dzięki za wkład. Dla każdego innego, link został znacznie ulepszony. Zdaje się, że OP wskazuje na narzędzie, które renderuje HTML do tekstu, podobnie jak przeglądarka tekstowa, taka jak ryś. Właśnie to próbuje to rozwiązanie. Większość ludzi wnosi tylko ekstraktory tekstu.
wyścig
1

W Pythonie 3.x możesz to zrobić w bardzo prosty sposób, importując pakiety „imaplib” i „email”. Mimo, że jest to starszy post, ale może moja odpowiedź może pomóc nowym użytkownikom tego postu.

status, data = self.imap.fetch(num, '(RFC822)')
email_msg = email.message_from_bytes(data[0][1]) 
#email.message_from_string(data[0][1])

#If message is multi part we only want the text version of the body, this walks the message and gets the body.

if email_msg.is_multipart():
    for part in email_msg.walk():       
        if part.get_content_type() == "text/plain":
            body = part.get_payload(decode=True) #to control automatic email-style MIME decoding (e.g., Base64, uuencode, quoted-printable)
            body = body.decode()
        elif part.get_content_type() == "text/html":
            continue

Teraz możesz wydrukować zmienną ciała i będzie ona w formacie zwykłego tekstu :) Jeśli jest dla Ciebie wystarczająco dobra, dobrze byłoby wybrać ją jako zaakceptowaną odpowiedź.

Wahib Ul Haq
źródło
To niczego nie konwertuje .
Antti Haapala
1
To pokazuje, jak wyodrębnić text/plainczęść z wiadomości e-mail, jeśli ktoś ją tam umieści. Nie robi nic, aby przekonwertować HTML na zwykły tekst i nie robi nic zdalnie przydatnego, jeśli próbujesz przekonwertować HTML z, powiedzmy, strony internetowej.
tripleee
1

możesz wyodrębnić tylko tekst z HTML za pomocą BeautifulSoup

url = "https://www.geeksforgeeks.org/extracting-email-addresses-using-regular-expressions-python/"
con = urlopen(url).read()
soup = BeautifulSoup(con,'html.parser')
texts = soup.get_text()
print(texts)
Sai Gopi N.
źródło
1

Podczas gdy wiele osób wspomniało o używaniu wyrażenia regularnego do usuwania tagów HTML, istnieje wiele wad.

na przykład:

<p>hello&nbsp;world</p>I love you

Należy przeanalizować do:

Hello world
I love you

Oto krótki fragment, który wymyśliłem, możesz dostosować go do swoich konkretnych potrzeb i działa jak urok

import re
import html
def html2text(htm):
    ret = html.unescape(htm)
    ret = ret.translate({
        8209: ord('-'),
        8220: ord('"'),
        8221: ord('"'),
        160: ord(' '),
    })
    ret = re.sub(r"\s", " ", ret, flags = re.MULTILINE)
    ret = re.sub("<br>|<br />|</p>|</div>|</h\d>", "\n", ret, flags = re.IGNORECASE)
    ret = re.sub('<.*?>', ' ', ret, flags=re.DOTALL)
    ret = re.sub(r"  +", " ", ret)
    return ret
Uri Goren
źródło
1

Kolejny przykład użycia BeautifulSoup4 w Pythonie 2.7.9+

obejmuje:

import urllib2
from bs4 import BeautifulSoup

Kod:

def read_website_to_text(url):
    page = urllib2.urlopen(url)
    soup = BeautifulSoup(page, 'html.parser')
    for script in soup(["script", "style"]):
        script.extract() 
    text = soup.get_text()
    lines = (line.strip() for line in text.splitlines())
    chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
    text = '\n'.join(chunk for chunk in chunks if chunk)
    return str(text.encode('utf-8'))

Wyjaśnione:

Wczytaj dane adresu URL jako html (używając BeautifulSoup), usuń wszystkie elementy skryptu i stylu, a także uzyskaj tylko tekst za pomocą .get_text (). Podziel na linie i usuń początkowe i końcowe spacje na każdym z nich, a następnie podziel nagłówki wielu nagłówków na linie, każdy z nich = (fraza.strip () dla linii w linii dla frazy w linii.split („”)). Następnie używając text = '\ n' .join, upuść puste linie, w końcu wróć jako usankcjonowany utf-8.

Uwagi:

  • Niektóre systemy, na których jest uruchomiony, nie będą działać z połączeniami https: // z powodu problemu z SSL, możesz wyłączyć weryfikację, aby rozwiązać ten problem. Przykładowa poprawka: http://blog.pengyifan.com/how-to-fix-python-ssl-certificate_verify_failed/

  • Python <2.7.9 może mieć problem z uruchomieniem tego

  • text.encode ('utf-8') może pozostawić dziwne kodowanie, zamiast tego może po prostu zwrócić str (tekst).

Mike Q
źródło
0

Oto kod, którego używam regularnie.

from bs4 import BeautifulSoup
import urllib.request


def processText(webpage):

    # EMPTY LIST TO STORE PROCESSED TEXT
    proc_text = []

    try:
        news_open = urllib.request.urlopen(webpage.group())
        news_soup = BeautifulSoup(news_open, "lxml")
        news_para = news_soup.find_all("p", text = True)

        for item in news_para:
            # SPLIT WORDS, JOIN WORDS TO REMOVE EXTRA SPACES
            para_text = (' ').join((item.text).split())

            # COMBINE LINES/PARAGRAPHS INTO A LIST
            proc_text.append(para_text)

    except urllib.error.HTTPError:
        pass

    return proc_text

Mam nadzieję że to pomogło.

troymyname00
źródło
0

Komentarz autora LibreOffice ma tę zaletę, że aplikacja może wykorzystywać makra python. Wydaje się, że oferuje wiele korzyści zarówno w przypadku odpowiedzi na to pytanie, jak i rozszerzenia bazy makr LibreOffice. Jeśli ta rozdzielczość jest jednorazową implementacją, a nie powinna być używana jako część większego programu produkcyjnego, otwarcie kodu HTML w programie do zapisywania i zapisanie strony jako tekstu wydaje się rozwiązywać omawiane tutaj problemy.

1 z 7
źródło
0

Sposób Perla (przepraszam mamo, nigdy nie zrobię tego w produkcji).

import re

def html2text(html):
    res = re.sub('<.*?>', ' ', html, flags=re.DOTALL | re.MULTILINE)
    res = re.sub('\n+', '\n', res)
    res = re.sub('\r+', '', res)
    res = re.sub('[\t ]+', ' ', res)
    res = re.sub('\t+', '\t', res)
    res = re.sub('(\n )+', '\n ', res)
    return res
brunql
źródło
Jest to zła praktyka z wielu powodów, na przykład&nbsp;
Uri Goren
Tak! To prawda! Nigdzie nie rób tego!
brunql