2008-12-11 22 views
7

¿Hay alguna manera de dividir una cadena larga de HTML después de N palabras? Obviamente, podría usar:Dividir HTML después de N palabras en python

' '.join(foo.split(' ')[:n]) 

para obtener los primeros n palabras de una cadena de texto sin formato, pero que podría dividir en medio de una etiqueta HTML, y no producirá HTML válido porque no cerrará la etiquetas que han sido abiertas

Necesito hacer esto en un sitio zope/plone - si hay algo estándar en los productos que pueden hacerlo, sería ideal.

Por ejemplo, decir que tengo el texto:

<p>This is some text with a 
    <a href="http://www.example.com/" title="Example link"> 
    bit of linked text in it 
    </a>. 
</p> 

y te pido para dividir después de 5 palabras, debe devolver:

<p>This is some text with</p> 

7 palabras:

<p>This is some text with a 
    <a href="http://www.example.com/" title="Example link"> 
    bit 
    </a> 
</p> 
+0

¿Desea ignorar las etiquetas para que no se dividan? En otras palabras, solo obtenga y divida el texto que no está contenido en una etiqueta. – monkut

+0

¿Está buscando dividir el texto del documento encapsulado entre etiquetas (por ejemplo, entre las etiquetas

y

)? – gotgenes

Respuesta

6

Eche un vistazo a la función truncate_html_words en django.utils.text. Incluso si no está usando Django, el código allí hace exactamente lo que quiere.

3

He oído que Beautiful Soup es muy bueno para analizar html. Probablemente podrá ayudarlo a obtener html correctos.

0

Iba a mencionar la base HTMLParser que está construida en Python, ya que no estoy seguro de cuál es el resultado final que intenta obtener, puede o no llegar hasta allí, trabajará con el controladores principalmente

0

Puede usar una mezcla de expresiones regulares, BeautifulSoup o Tidy (prefiero BeautifulSoup). La idea es simple: primero quite todas las etiquetas HTML. Encuentre la enésima palabra (n = 7 aquí), encuentre la cantidad de veces que la palabra enésima aparece en la cadena hasta n palabras, ya que solo busca la última ocurrencia que se utilizará para el truncamiento.

Aquí es una pieza de código, aunque un poco desordenado, pero funciona

import re 
from BeautifulSoup import BeautifulSoup 
import tidy 

def remove_html_tags(data): 
    p = re.compile(r'<.*?>') 
    return p.sub('', data) 

input_string='<p>This is some text with a <a href="http://www.example.com/" '\ 
    'title="Example link">bit of linked text in it</a></p>' 

s=remove_html_tags(input_string).split(' ')[:7] 

###required to ensure that only the last occurrence of the nth word is                      
# taken into account for truncating.                              
# coz if the nth word could be 'a'/'and'/'is'....etc                          
# which may occur multiple times within n words                            
temp=input_string 
k=s.count(s[-1]) 
i=1 
j=0 
while i<=k: 
    j+=temp.find(s[-1]) 
    temp=temp[j+len(s[-1]):] 
    i+=1 
####                                       
output_string=input_string[:j+len(s[-1])] 

print "\nBeautifulSoup\n", BeautifulSoup(output_string) 
print "\nTidy\n", tidy.parseString(output_string) 

La salida es lo que quiere u

BeautifulSoup 
<p>This is some text with a <a href="http://www.example.com/" title="Example link">bit</a></p> 

Tidy 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> 
<html> 
<head> 
<meta name="generator" content= 
"HTML Tidy for Linux/x86 (vers 6 November 2007), see www.w3.org"> 
<title></title> 
</head> 
<body> 
<p>This is some text with a <a href="http://www.example.com/" 
title="Example link">bit</a></p> 
</body> 
</html> 

Esperanza esto ayuda

Editar: Una mejor regex

`p = re.compile(r'<[^<]*?>')` 
+0

Cualquier razón por la que está escribiendo su propia función para eliminar etiquetas HTML y no usar Beauitful Soup's [soup.get_text()] (http://www.crummy.com/software/BeautifulSoup/bs4/doc/#get-text) ¿método? – tatlar

Cuestiones relacionadas