Frage

Hier ist der Deal. Gibt es eine Möglichkeit Strings in einer Linie auf der Basis mehrerer Regexes Token aufgeteilt haben?

Ein Beispiel:

Ich muss alle href-Tags erhalten, ihre entsprechenden Text und einen anderen Text auf einem anderen regex basiert. So habe ich drei Ausdrücke und möchte die Linie tokenize und extrahieren Zeichen des Textes jeden Ausdruck entsprechen.

Ich habe tatsächlich getan dies mit Flex (nicht mit Adobe verwechselt werden), die eine Implementierung des guten alten lex ist. lex bietet ein eleganter Weg, dies zu tun, indem sie „Aktionen“ auf Basis von Ausdrücken ausgeführt wird. Man kann die Art und Weise steuern lex Lesen einer Datei zu (Block / Zeile basierend Lese).

Das Problem ist, dass Flex-C / C ++ Code tatsächlich erzeugt, die tatsächlich die Tokenisieren Arbeit leistet. Ich habe ein machen Datei, die all diese Dinge wickelt. Ich frage mich, ob Perl / Python in irgendeiner Weise kann das gleiche tun. Es ist nur, dass ich möchte alles tun Ich mag in einer einzigen Programmiersprache selbst.

Tokenizing ist nur eines der Dinge, die ich als Teil meiner Anwendung tun will.

Neben Perl oder Python kann jede Sprache (funktionale auch) tun?

ich über PLY und ANTLR hier las ( Parsing, wo ich lerne darüber ).

Aber ist es eine Möglichkeit, es natürlich in Python selbst zu tun? entschuldigen Sie meine Unwissenheit, aber diese Werkzeuge sind in allen gängigen Produkten verwendet / Dienstleistungen?

Danke.

War es hilfreich?

Lösung

Wenn Sie speziell nach Links aus Web-Seiten, dann Perl WWW-Analyse: : Modul werden die Dinge herauszufinden, für Sie in einem sehr eleganten Art und Weise Mechanize. Hier ist ein Beispielprogramm, das die erste Seite von Stack-Überlauf packt und parst heraus alle Links, Druck ihren Textes und entsprechenden URLs:

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

In der Hauptschleife, die jeweils $link ist ein WWW :: Mechanize :: Link Objekt, so dass Sie nicht nur gezwungen zu bekommen, den Text und URL.

Alles Gute,

Paul

Andere Tipps

Sehen Sie in der Dokumentation für folgende Module auf CPAN

HTML :: TreeBuilder

HTML :: TABLEEXTRACT

und

Parse :: RecDescent

Ich habe diese Module sehr große und komplexe Web-Seiten zu verarbeiten.

Klingt wie Sie wirklich nur HTML analysieren wollen, empfehle ich an einem der wunderbaren Pakete suchen dafür:

oder! Sie können einen Parser wie eine der folgenden Optionen verwenden:

  • PyParsing
  • DParser -. Ein GLR-Parser mit guten Python-Bindungen
  • ANTLR -. Ein rekursive anständigen Parser-Generator, der Python-Code generieren

Dieses Beispiel stammt aus der BeautifulSoup Dokumentation :

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

Haben Sie unter PyParsing ?

Von der Homepage:

Hier ist ein Programm zu analysieren „Hallo, Welt!“ (Oder jede Begrüßung der Form ""):

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

Das Programm gibt folgende Möglichkeiten:

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

Wenn Ihr Problem etwas überhaupt hat mit Web-Scraping zu tun, ich empfehlen, sich unter Web :: Scraper , die über XPath einfache Elementauswahl liefert jeweils CSS-Selektoren. Ich habe ein (deutsch) auf Web sprechen :: Scraper , aber wenn man es durch Babelfish laufen oder nur Blick auf den Codebeispielen, das kann Ihnen helfen, einen schnellen Überblick über die Syntax zu erhalten.

Hand Parsing HTML ist beschwerlich und werden Sie nicht viel geben über eine der vorgefertigten HTML-Parser verwenden. Wenn Ihre HTML sehr begrenzten Variation sind, können Sie mithilfe von cleveren regulären Ausdrücken auszukommen, aber wenn Sie bereits Hard-Core-Parser Tools ausbricht, es klingt, als ob Ihr HTML als weit mehr regelmäßig ist, was vernünftig ist zu analysieren, mit reguläre Ausdrücke.

perlop :

  

Eine nützliche Idiom für lex -ähnlichen Scanner   ist /\G.../gc. Sie können kombinieren   mehrere regexps so zu verarbeiten, ein   String-Teil-für-Teil, tun andere   Aktionen in Abhängigkeit von der regexp   abgestimmt. Jeder regexp versucht zu entsprechen   wo die vorherige aufhört.

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

Überprüfen Sie auch pQuery es als wirklich schön Perlish Weg, diese Art von Tun Sachen ....

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

Allerdings, wenn Ihre Anforderung über HTML / Web ist, dann ist hier die frühere „Hallo Welt!“ Beispiel in 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 !

Wahrscheinlich zu viel von einem großen Hammer diese Nuss zu knacken; -)

Ändern von Brunos Beispiel Fehlerprüfung enthalten:

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

(Beachten Sie, dass skalare // g verwendet, ist leider der einzige Ort, wo man wirklich nicht vermeiden können, die $ 1 usw. Variablen.)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top