Стратегия Python для извлечения текста из искаженных HTML-страниц - PullRequest
5 голосов
/ 23 октября 2009

Я пытаюсь извлечь текст из произвольных HTML-страниц. На некоторых страницах (которые я не контролирую) есть искаженные HTML или сценарии, которые затрудняют это. Также я нахожусь в среде общего хостинга, поэтому я могу установить любую библиотеку Python, но я не могу просто установить на сервер все, что захочу.

pyparsing и html2text.py также, похоже, не работают для искаженных HTML-страниц.

Пример URL-адреса http://apnews.myway.com/article/20091015/D9BB7CGG1.html

Моя текущая реализация примерно следующая:

# 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 

если beautifulsoup по-прежнему не работает, то я прибегаю к эвристике, которая заключается в просмотре 1-го и последнего символа (чтобы увидеть, не похожи ли они на кодовую строку # <; и взятии образца строки и проверке если токены являются английскими словами или числами. Если немногим из токенов являются слова или цифры, то я предполагаю, что строка является кодом. </p>

Я мог бы использовать машинное обучение для проверки каждой строки, но это кажется немного дорогостоящим, и мне, вероятно, пришлось бы обучать его (так как я не очень много знаю об обучаемых машинах без надзора), и, конечно, также написать его.

Любые советы, инструменты, стратегии будут приветствоваться. Также я понимаю, что последняя часть этого довольно грязная, так как, если я получаю строку, в которой определено, что она содержит код, я в настоящее время выбрасываю всю строку, даже если в этой строке есть небольшое количество фактического английского текста.

Ответы [ 3 ]

5 голосов
/ 23 октября 2009

Постарайтесь не смеяться, но:

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

Надеюсь, у тебя рысь!

0 голосов
/ 24 октября 2009

BeautifulSoup плохо работает с искаженным HTML. Как насчет регулярного выражения?

>>> 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.'

Затем вы можете собрать список допустимых тегов, из которых вы хотите извлечь информацию.

0 голосов
/ 23 октября 2009

Ну, это зависит от того, насколько хорошим должно быть решение. У меня была похожая проблема - импортировать сотни старых HTML-страниц на новый веб-сайт. Я в основном сделал

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

и это сработало, но, конечно, документы могут быть настолько плохими, что даже BS не может спасти многое.

...