2009-10-23 9 views
5

Próbuję wyodrębnić tekst z dowolnych stron html. Niektóre strony (nad którymi nie mam kontroli) zniekształciły html lub skrypty, które to utrudniają. Również jestem na wspólnym środowisku hostingowym, więc mogę zainstalować dowolną bibliotekę python, ale nie mogę po prostu zainstalować niczego, co chcę na serwerze.Strategia Pythona do wyodrębniania tekstu ze zniekształconych stron HTML

pyparsing i html2text.py również nie działały na źle sformatowanych stronach html.

Przykład URL http://apnews.myway.com/article/20091015/D9BB7CGG1.html

Moja obecna implementacja jest w przybliżeniu następujący:

# Try using BeautifulSoup 3.0.7a 
soup = BeautifulSoup.BeautifulSoup(s) 
comments = soup.findAll(text=lambda text:isinstance(text,Comment)) 
[comment.extract() for comment in comments] 
c=soup.findAll('script') 
for i in c: 
    i.extract()  
body = bsoup.body(text=True) 
text = ''.join(body) 
# if BeautifulSoup can't handle it, 
# alter html by trying to find 1st instance of "<body" and replace everything prior to that, with "<html><head></head>" 
# try beautifulsoup again with new html 

jeśli BeautifulSoup nadal nie działa, a potem uciekać się do korzystania heurystyki patrzenia na 1st char, ostatni char (aby zobaczyć, czy wygląda na linię kodu # < i pobrać próbkę linii, a następnie sprawdzić, czy tokeny są angielskimi słowami lub liczbami. Jeśli dla kilku tokenów są słowa lub liczby, to myślę, że linia jest kodem:

Mogę wykorzystać uczenie maszynowe do sprawdzenia każdej linii, ale wydaje mi się to trochę kosztowne i prawdopodobnie musiałbym ją wyszkolić (ponieważ nie wiem zbyt wiele o maszynach uczących się bez nadzoru) i oczywiście również ją napisać.

Wszelkie rady, narzędzia, strategie byłyby mile widziane. Również zdaję sobie sprawę, że ta druga część jest raczej nieporządna, ponieważ jeśli dostanę linię, która jest określona, ​​aby zawierać kod, obecnie wyrzucam całą linię, nawet jeśli w linii jest niewielka ilość faktycznego tekstu w języku angielskim.

+0

Cóż, rozwiązanie niezawsze, historia wiadomości, z którą się łączyłeś, była świetna. Niektórzy ludzie, co? :) –

+1

@Lesse, myślę, że są też zniekształceni ludzie. – Johnny4000

Odpowiedz

5

nie starają się śmiać, ale:

class TextFormatter: 
    def __init__(self,lynx='/usr/bin/lynx'): 
     self.lynx = lynx 

    def html2text(self, unicode_html_source): 
     "Expects unicode; returns unicode" 
     return Popen([self.lynx, 
         '-assume-charset=UTF-8', 
         '-display-charset=UTF-8', 
         '-dump', 
         '-stdin'], 
         stdin=PIPE, 
         stdout=PIPE).communicate(input=unicode_html_source.encode('utf-8'))[0].decode('utf-8') 

Mam nadzieję, że masz rysie!

+0

Nie mam lynx = (i nie zainstalują go.Mają zainstalowane ELinks, które mi powiedzieli, przypuszczam, że są podobne.Patrz na dokumentację ELinks, żeby zobaczyć, czy zadziała.) Dobrze wiedzieć o rysie mniej – Johnny4000

+0

Elinks i Lynx kopią tyłek Dziękuję za poinformowanie mnie o tym – Johnny4000

+0

Urodziłam się z rozpaczy po mojej stronie, mogę ci powiedzieć, cieszę się, że ci się przydaje! –

0

Cóż, to zależy od tego, jak dobre musi być rozwiązanie. Miałem podobny problem, importując setki starych stron html do nowej witryny. I w zasadzie nie

# remove all that crap around the body and let BS fix the tags 
newhtml = "<html><body>%s</body></html>" % (
    u''.join(unicode(tag) for tag in BeautifulSoup(oldhtml).body.contents)) 
# use html2text to turn it into text 
text = html2text(newhtml) 

i wyszło, ale oczywiście dokumenty może być tak źle, że nawet BS nie może ocalić wiele.

0

BeautifulSoup będzie źle działać ze źle sformułowanym kodem HTML. A co z niektórymi regex-fu?

>>> import re 
>>> 
>>> html = """<p>This is paragraph with a bunch of lines 
... from a news story.</p>""" 
>>> 
>>> pattern = re.compile('(?<=p>).+(?=</p)', re.DOTALL) 
>>> pattern.search(html).group() 
'This is paragraph with a bunch of lines\nfrom a news story.' 

Następnie można utworzyć listę poprawnych tagów, z których mają zostać wyodrębnione informacje.

Powiązane problemy