Pregunta

Aquí está el trato. ¿Hay una manera de tener cadenas de caracteres en una línea basada en múltiples expresiones regulares?

Un ejemplo:

Tengo que obtener todas las etiquetas href, su texto correspondiente y algún otro texto basado en una expresión regular diferente. Así que tengo 3 expresiones y me gustaría tokenizar la línea y extraer tokens de texto que coincidan con cada expresión.

De hecho, he hecho esto usando flex (no confundirlo con Adobe), que es una implementación de la vieja y buena lex. lex proporciona una forma elegante de hacerlo ejecutando " acciones " basado en expresiones. Uno puede controlar el camino. lex también lee un archivo (lectura basada en bloque / línea).

El problema es que flex realmente produce código C / C ++ que realmente hace el trabajo de tokenización. tengo un Hacer archivo que envuelve todas estas cosas. Me preguntaba si Perl / python puede de alguna manera hacer lo mismo. Es solo que me gustaría hacer de todo. Me gusta en un solo lenguaje de programación.

Tokenizing es solo una de las cosas que quiero hacer como parte de mi aplicación.

Aparte de perl o python, ¿puede hacer esto cualquier idioma (funcional también)?

Leí sobre PLY y ANTLR aquí ( Análisis, donde puedo Aprendo sobre esto ).

¿Pero hay una manera de hacerlo de forma natural en Python? perdone mi ignorancia, pero ¿se usan estas herramientas en productos / servicios populares?

Gracias.

¿Fue útil?

Solución

Si está específicamente después de analizar los enlaces de las páginas web, entonces Perla WWW: : El módulo Mecanizar resolverá las cosas de manera elegante. Aquí hay un programa de ejemplo que toma la primera página de Stack Overflow y analiza todos los enlaces, imprimiendo su texto y las URL correspondientes:

#!/usr/bin/perl
use strict;
use warnings;
use WWW::Mechanize;

my $mech = WWW::Mechanize->new;

$mech->get("http://stackoverflow.com/");

$mech->success or die "Oh no! Couldn't fetch stackoverflow.com";

foreach my $link ($mech->links) {
    print "* [",$link->text, "] points to ", $link->url, "\n";
}

En el bucle principal, cada $ link es un WWW :: Mechanize :: Link , por lo que no está limitado a obtener el texto y la URL.

Todo lo mejor,

Paul

Otros consejos

Consulte la documentación de los siguientes módulos en CPAN

HTML :: TreeBuilder

HTML :: TableExtract

y

Parse :: RecDescent

He usado estos módulos para procesar páginas web bastante grandes y complejas.

Parece que realmente quieres analizar HTML, te recomiendo que mires cualquiera de los paquetes maravillosos para hacerlo:

O! Puede usar un analizador como uno de los siguientes:

  • PyParsing
  • DParser : un analizador GLR con buenos enlaces python.
  • ANTLR : un generador de analizador decente recursivo que puede generar código python.

Este ejemplo es de BeautifulSoup Documentación :

from BeautifulSoup import BeautifulSoup, SoupStrainer
import re

links = SoupStrainer('a')
[tag for tag in BeautifulSoup(doc, parseOnlyThese=links)]
# [<a href="http://www.bob.com/">success</a>, 
#  <a href="http://www.bob.com/plasma">experiments</a>, 
#  <a href="http://www.boogabooga.net/">BoogaBooga</a>]

linksToBob = SoupStrainer('a', href=re.compile('bob.com/'))
[tag for tag in BeautifulSoup(doc, parseOnlyThese=linksToBob)]
# [<a href="http://www.bob.com/">success</a>, 
#  <a href="http://www.bob.com/plasma">experiments</a>]

¿Has visto PyParsing ?

Desde su página de inicio:

Aquí hay un programa para analizar " ¡Hola, mundo! " (o cualquier saludo del formulario " ;,! "):

from pyparsing import Word, alphas
greet = Word( alphas ) + "," + Word( alphas ) + "!" # <-- grammar defined here
hello = "Hello, World!"
print hello, "->", greet.parseString( hello )

El programa produce lo siguiente:

Hello, World! -> ['Hello', ',', 'World', '!']

Si su problema tiene algo que ver con el raspado web, recomiendo consultar Web :: Scraper , que proporciona una fácil selección de elementos a través de XPath respectivamente, selectores de CSS. Tengo una (alemana) hablar en Web :: Scraper , pero si lo ejecuta a través de babelfish o simplemente mira los ejemplos de código, eso puede ayudarlo a obtener una visión general rápida de la sintaxis.

El HTML de análisis manual es oneroso y no le dará mucho uso de uno de los analizadores HTML preparados previamente. Si su HTML es de una variación muy limitada, puede hacerlo mediante el uso de expresiones regulares inteligentes, pero si ya está utilizando herramientas de análisis de núcleo duras, suena como si su HTML fuera mucho más regular de lo que es sensato analizar. expresiones regulares.

De perlop :

  

Un lenguaje útil para escáneres de tipo lex   es /\G.../gc . Puedes combinar   varias expresiones regulares como esta para procesar una   cadena parte por parte, haciendo diferente   Acciones en función de las que regexp.   emparejado Cada expresión regular intenta coincidir   donde termina el anterior.

 LOOP:
    {
      print(" digits"),       redo LOOP if /\G\d+\b[,.;]?\s*/gc;
      print(" lowercase"),    redo LOOP if /\G[a-z]+\b[,.;]?\s*/gc;
      print(" UPPERCASE"),    redo LOOP if /\G[A-Z]+\b[,.;]?\s*/gc;
      print(" Capitalized"),  redo LOOP if /\G[A-Z][a-z]+\b[,.;]?\s*/gc;
      print(" MiXeD"),        redo LOOP if /\G[A-Za-z]+\b[,.;]?\s*/gc;
      print(" alphanumeric"), redo LOOP if /\G[A-Za-z0-9]+\b[,.;]?\s*/gc;
      print(" line-noise"),   redo LOOP if /\G[^A-Za-z0-9]+/gc;
      print ". That's all!\n";
    }

También puedes ver pQuery como una manera realmente agradable de hacer esto. cosas ....

use pQuery;

pQuery( 'http://www.perl.com' )->find( 'a' )->each( 
    sub {
        my $pQ = pQuery( 

También puedes ver pQuery como una manera realmente agradable de hacer esto. cosas ....

use strict;
use warnings;
use Parse::RecDescent;

my $grammar = q{
    alpha : /\w+/
    sep   : /,|\s/
    end   : '!'
    greet : alpha sep alpha end { shift @item; return \@item }
};

my $parse = Parse::RecDescent->new( $grammar );
my $hello = "Hello, World!";
print "$hello -> @{ $parse->greet( $hello ) }";

# => Hello, World! -> Hello , World !

Sin embargo, si su requisito está más allá de HTML / Web, aquí está el " Hello World! " ejemplo en Parse :: RecDescent ...

<*>

Probablemente sea un martillo demasiado grande para romper esta tuerca ;-)

); say $pQ->text, ' -> ', $pQ->toHtml; } ); # prints all HTML anchors on www.perl.com # => link text -> anchor HTML

Sin embargo, si su requisito está más allá de HTML / Web, aquí está el " Hello World! " ejemplo en Parse :: RecDescent ...

<*>

Probablemente sea un martillo demasiado grande para romper esta tuerca ;-)

Modificando el ejemplo de Bruno para incluir la comprobación de errores:

my $input = "...";
while (1) {
    if ($input =~ /\G(\w+)/gc) { print "word: '$1'\n"; next }
    if ($input =~ /\G(\s+)/gc) { print "whitespace: '$1'\n"; next }

    if ($input !~ /\G\z/gc)  { print "tokenizing error at character " . pos($input) . "\n" }
    print "done!\n"; last;
}

(Tenga en cuenta que usar scalar // g es desafortunadamente el único lugar donde realmente no puede evitar usar las variables de $ 1, etc.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top