La búsqueda de contenido entre dos palabras sin expresiones regulares, BeautifulSoup, LXML ... etc.
-
12-09-2019 - |
Pregunta
Cómo averiguar el contenido entre dos palabras o dos conjuntos de caracteres al azar?
La página raspado no se garantiza que sea sólo HTML y los datos importantes pueden estar dentro de un bloque de Javascript. Por lo tanto, no puedo quitar el JavaScript.
considere esto:
<html>
<body>
<div>StartYYYY "Extract HTML", ENDYYYY
</body>
Some Java Scripts code STARTXXXX "Extract JS Code" ENDXXXX.
</html>
Así que como ves el código HTML puede no ser completa. Que puedo pedir a la página, y luego sin preocuparse de nada, quiero encontrar el contenido llamado "Extraer el nombre" y "extraer los datos aquí en un JavaScript".
Lo que yo busco es en python:
De esta manera:
data = FindBetweenText(UniqueTextBeforeContent, UniqueTextAfterContent, page)
Cuando la página está descargado y datos tendría el texto que estoy buscando. Yo prefiero quedarme lejos de expresiones regulares como algunos de los casos puede ser demasiado complejo para expresiones regulares.
Solución
Aquí está mi intento, esto se prueba. Mientras recursivo, no debería haber ninguna duplicación innecesaria de cadena, aunque un generador podría ser más óptima
def bracketed_find(s, start, end, startat=0):
startloc=s.find(start, startat)
if startloc==-1:
return []
endloc=s.find(end, startloc+len(start))
if endloc == -1:
return [s[startloc+len(start):]]
return [s[startloc+len(start):endloc]] + bracketed_find(s, start, end, endloc+len(end))
y aquí es una versión del generador
def bracketed_find(s, start, end, startat=0):
startloc=s.find(start, startat)
if startloc==-1:
return
endloc=s.find(end, startloc+len(start))
if endloc == -1:
yield s[startloc+len(start):]
return
else:
yield s[startloc+len(start):endloc]
for found in bracketed_find(s, start, end, endloc+len(end)):
yield found
Otros consejos
si está seguro de sus marcadores son únicos, hacer algo como esto
s="""
<html>
<body>
<div>StartYYYY "Extract HTML", ENDYYYY
</body>
Some Java Scripts code STARTXXXX "Extract JS Code" ENDXXXX.
</html>
"""
def FindBetweenText(startMarker, endMarker, text):
startPos = text.find(startMarker)
if startPos < 0: return
endPos = text.find(endMarker)
if endPos < 0: return
return text[startPos+len(startMarker):endPos]
print FindBetweenText('STARTXXXX', 'ENDXXXX', s)
Bueno, esto es lo que sería en PHP. No hay duda de que hay una manera mucho más sexy Pythonic.
function FindBetweenText($before, $after, $text) {
$before_pos = strpos($text, $before);
if($before_pos === false)
return null;
$after_pos = strpos($text, $after);
if($after_pos === false || $after_pos <= $before_pos)
return null;
return substr($text, $before_pos, $after_pos - $before_pos);
}
[Ligeramente probado]
def bracketed_find_first(prefix, suffix, page, start=0):
prefixpos = page.find(prefix, start)
if prefixpos == -1: return None # NOT ""
startpos = prefixpos + len(prefix)
endpos = page.find(suffix, startpos) # DRY
if endpos == -1: return None # NOT ""
return page[startpos:endpos]
Nota: sólo los rendimientos por encima de la primera aparición. Aquí es un generador que produce cada ocurrencia.
def bracketed_finditer(prefix, suffix, page, start_at=0):
while True:
prefixpos = page.find(prefix, start_at)
if prefixpos == -1: return # StopIteration
startpos = prefixpos + len(prefix)
endpos = page.find(suffix, startpos)
if endpos == -1: return
yield page[startpos:endpos]
start_at = endpos + len(suffix)