2009-10-23 2 views
5

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

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-ом полукокса, последнего символа (чтобы увидеть, если они выглядят как строка кода # < и берут образец строки, а затем проверяют, являются ли токены английскими словами или числами. Если для нескольких токенов есть слова или цифры, я полагаю, что строка - код.

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

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

+0

Ну, решение не стойкое, новость, с которой вы связались, была отличной. Некоторые люди, да? :) –

+1

@ Lesse, я думаю, есть и неверные люди. – Johnny4000

ответ

5

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

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

У меня нет lynx = (и они не будут устанавливать его. У них есть ELinks, которые, как они сказали мне, должны быть похожими. Посмотрите на документацию ELinks, чтобы увидеть это, если будете работать. Полезно знать о рыси. – Johnny4000

+0

ELinks and Lynx kick butt Спасибо за то, что сообщили мне о них. – Johnny4000

+0

Это было рождено из отчаяния на моей стороне, я могу вам сказать. Я рад, что это полезно для вас! –

0

Ну, это зависит от того, насколько хорошо должно быть решение. У меня была аналогичная проблема, импортировав сотни старых 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 не может спасти много.

0

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

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

Смежные вопросы