BeautifulSoup get text ne supprime pas toutes les balises et JavaScript
j'essaie d'utiliser BeautifulSoup pour obtenir du texte à partir de pages web.
ci-dessous est un script que j'ai écrit pour le faire. Il prend deux arguments, le premier est le fichier HTML ou XML d'entrée, le deuxième fichier de sortie.
import sys
from bs4 import BeautifulSoup
def stripTags(s): return BeautifulSoup(s).get_text()
def stripTagsFromFile(inFile, outFile):
open(outFile, 'w').write(stripTags(open(inFile).read()).encode("utf-8"))
def main(argv):
if len(sys.argv) <> 3:
print 'Usage:tt', sys.argv[0], 'input.html output.txt'
return 1
stripTagsFromFile(sys.argv[1], sys.argv[2])
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))
malheureusement, pour de nombreuses pages web, par exemple: http://www.greatjobsinteaching.co.uk/career/134112/Education-Manager-Location J'obtiens quelque chose comme ceci (Je ne montre que quelques premières lignes):
html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
Education Manager Job In London With Caleeda | Great Jobs In Teaching
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-15255540-21']);
_gaq.push(['_trackPageview']);
_gaq.push(['_trackPageLoadTime']);
y a-t-il un problème avec mon script? J'ai essayé de passer 'xml' comme second argument pour embellir le constructeur de Soup, ainsi que 'html5lib' et 'lxml', mais ça n'aide pas. Existe-t-il une alternative à BeautifulSoup qui fonctionnerait mieux pour cette tâche? Tout ce que je veux est d'extraire le texte qui sera rendu dans un navigateur pour cette page web.
Toute aide sera très appréciée.
3 réponses
nltk clean_html()
est assez bonne à ce!
en supposant que vous avez déjà votre html stocké dans une variable html
comme
html = urllib.urlopen(address).read()
alors il suffit d'utiliser
import nltk
clean_text = nltk.clean_html(html)
mise à JOUR
Soutien pour clean_html
et clean_url
sera abandonné pour les futures versions de nltk. S'il vous plaît utiliser BeautifulSoup pour l'instant...il est très regrettable.
un exemple sur la façon de réaliser ceci est sur cette page:
Voici une approche qui est basée sur la réponse ici: BeautifulSoup Grab Visible page Web texte par jbochi. Cette approche permet des commentaires intégrés dans des éléments contenant du texte de page, et fait un peu pour nettoyer la sortie en enlevant des lignes, en consolidant l'espace, etc.
html = urllib.urlopen(address).read()
soup = BeautifulSoup.BeautifulSoup(html)
texts = soup.findAll(text=True)
def visible_text(element):
if element.parent.name in ['style', 'script', '[document]', 'head', 'title']:
return ''
result = re.sub('<!--.*-->|\r|\n', '', str(element), flags=re.DOTALL)
result = re.sub('\s{2,}| ', ' ', result)
return result
visible_elements = [visible_text(elem) for elem in texts]
visible_text = ''.join(visible_elements)
print(visible_text)
C'était le problème que j'ai. aucune solution ne semblait être en mesure de retourner le texte (le texte qui serait effectivement rendu dans le broswer web). D'autres solutions ont mentionné que BS n'est pas idéal pour le rendu et que html2text était une bonne approche. J'ai essayé html2text et nltk.clean_html et a été surpris par les résultats du timing donc pensé qu'ils justifiaient une réponse pour la postérité. Bien sûr, la vitesse delta peut fortement dépendre du contenu des données...
une réponse ici de @Helge était d'utiliser nltk de toutes choses.
import nltk
%timeit nltk.clean_html(html)
was returning 153 us per loop
cela fonctionnait vraiment bien pour retourner une chaîne de caractères Avec rendu html. Ce module nltk était plus rapide que même html2text, bien que html2text soit peut-être plus robuste.
betterHTML = html.decode(errors='ignore')
%timeit html2text.html2text(betterHTML)
%3.09 ms per loop