Pergunta

Aqui está o negócio. Existe uma maneira de ter cordas tokenized em uma linha com base em várias expressões regulares?

Um exemplo:

Eu tenho que pegar todas as tags href, o texto correspondente e algum outro texto baseado em um regex diferente. Então, eu tenho 3 expressões e gostaria de tokenizar as linhas e extrair os tokens de texto correspondente a cada expressão.

Eu realmente fizeram isso usando Flex (para não ser confundido com Adobe), que é uma implementação da boa lex de idade. lex fornece uma maneira elegante de fazer isso através da execução de "ações" com base em expressões. Pode-se controlar a forma lex lendo um arquivo também (bloco / linha de leitura com base).

O problema é que o Flex realmente produz código C / C ++ que realmente faz o trabalho tokenizing. eu tenho um fazer arquivo que envolve todas essas coisas. Fiquei me perguntando se perl / python lata de alguma forma fazer a mesma coisa. Seu justo que eu gostaria de fazer tudo I como em um único própria linguagem de programação.

tokenizing é apenas uma das coisas que eu quero fazer como parte do meu aplicativo.

Além de perl ou python pode qualquer língua (também funcional) fazer isso?

Eu li sobre PLY e ANTLR aqui ( de análise, onde lata I aprender sobre ele ).

Mas há uma maneira de fazê-lo naturalmente em si python? desculpem a minha ignorância, mas são essas as ferramentas utilizadas em quaisquer produtos populares / serviços?

Obrigado.

Foi útil?

Solução

Se você é especificamente após a análise ligações para fora das páginas de Web, em seguida, do Perl WWW: : módulo Mecanizar vai descobrir as coisas para você de uma forma muito elegante. Aqui está um exemplo de programa que agarra a primeira página de Stack Overflow e analisa todas as ligações, imprimindo o seu texto e URLs correspondentes:

#!/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";
}

No circuito principal, cada $link é um WWW :: mechanize :: Fazer a ligação objeto, de modo que você não está apenas restrita a obtenção do texto e URL.

Todo o melhor,

Paul

Outras dicas

Olhe documentação para seguir módulos sobre CPAN

HTML :: TreeBuilder

HTML :: TableExtract

e

Parse :: RecDescent

Eu usei esses módulos para processar muito grandes e complexas páginas web.

Parece que você realmente só quero analisar HTML, eu recomendo a olhar para qualquer um dos pacotes maravilhosos para fazê-lo:

Ou! Você pode usar um analisador como um dos seguintes:

  • pyparsing
  • DParser -. Parser A GLR com boas ligações Python
  • ANTLR -. A recursiva gerador de analisador decente que pode gerar o código python

Este exemplo é do BeautifulSoup Documentação :

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>]

Você já olhou para pyparsing ?

A partir de sua página inicial:

Aqui está um programa para analisar "Olá, mundo!" (Ou qualquer saudação da forma "!"):

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

O programa emite o seguinte:

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

Se o seu problema tem absolutamente nada a ver com a raspagem web, eu recomendo olhar Web :: raspador, que fornece seleção elemento fácil via XPath respectivamente seletores CSS. Eu tenho um (alemão) palestra sobre Web :: Scraper , mas se você executá-lo através babelfish ou apenas olhar para os exemplos de código, que pode ajudá-lo a ter uma visão geral da sintaxe.

Mão-análise de HTML é onerosa e não lhe dará muito mais usando um dos analisadores premade HTML. Se o seu HTML é de variação muito limitado, você pode começar por usando expressões regulares inteligentes, mas se você já está quebrando ferramentas analisador hard-core, soa como se o seu HTML é muito mais regular do que o que é sensato para analisar com expressões regulares.

A partir perlop :

A linguagem útil para scanners -como lex é /\G.../gc. Você pode combinar vários regexps como este para processar um corda parte-a-parte, fazendo diferente ações, dependendo de qual regexp coincide. Cada regexp tenta jogo onde os anteriores um sai de cena.

 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";
    }

Também confira pQuery lo como uma forma Perlish muito legal de fazer esse tipo de coisas ....

use pQuery;

pQuery( 'http://www.perl.com' )->find( 'a' )->each( 
    sub {
        my $pQ = pQuery( $_ ); 
        say $pQ->text, ' -> ', $pQ->toHtml;
    }
);

# prints all HTML anchors on www.perl.com
# =>  link text -> anchor HTML

No entanto, se a sua exigência é para além HTML / Web, em seguida, aqui é o anterior "Olá mundo!" exemplo na Parse :: RecDescent ...

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 !

Provavelmente muito de um grande martelo para quebrar esta porca; -)

O exemplo de Modificando Bruno incluem a verificação de erros:

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;
}

(Note que usando escalar // g é, infelizmente, o único lugar onde você realmente não pode evitar o uso de US $ 1, etc. variáveis.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top