Question

J'ai essayé différentes méthodes pour dépouiller la licence de textes du Projet Gutenberg, pour être utilisé comme corpus pour un projet d'apprentissage des langues, mais je ne peux pas sembler trouver une approche non supervisée et fiable. La meilleure heuristique que je suis venu avec jusqu'à présent se déshabille les premières vingt-huit lignes et la 398 dernière, qui a travaillé pour un grand nombre des textes. Toutes les suggestions quant aux moyens que je peux dépouiller automatiquement le texte (ce qui est très similaire pour beaucoup de textes, mais avec de légères différences dans chaque cas, et quelques modèles différents, aussi bien), ainsi que des suggestions sur la façon de vérifier que le texte a été dépouillé avec précision, serait très utile.

Était-ce utile?

La solution

Vous ne plaisantiez pas. Il est presque comme s'ils essayaient de faire le travail AI-complet. Je ne peux penser à deux approches, aucun d'eux parfait.

1) Mettre en place un script, disons, Perl, d'aborder les modèles les plus courants (par exemple, chercher l'expression « produit par », continuez vers le bas à la ligne suivante vide et il coupe), mais mis en lots de affirmations au sujet de ce qui est attendu (par exemple, le prochain texte doit être le titre ou l'auteur). De cette façon, lorsque le motif échoue, vous le saurez. La première fois qu'un modèle échoue, faites-le à la main. La deuxième fois, modifier le script.

2) Essayez Mechanical Turk d'Amazon .

Autres conseils

J'ai aussi voulu un outil pour dépouiller les en-têtes et pieds de page Projet Gutenberg depuis des années pour jouer avec le traitement du langage naturel sans contaminer l'analyse avec boilerplate mélangé avec le etxt. Après avoir lu cette question j'ai finalement tiré mon doigt sur et écrit un filtre Perl que vous pouvez diriger à travers dans tout autre outil.

Il est fait comme une machine d'état à l'aide regexes par ligne. Il est écrit pour être facile à comprendre puisque la vitesse est pas un problème avec la taille typique des textes électroniques. Jusqu'à présent, il travaille sur les textes électroniques douzaine de couple que j'ai ici, mais dans la nature il y a sûr d'être beaucoup plus de variations qui doivent être ajoutés. Espérons que le code est assez clair que tout le monde peut y ajouter:


#!/usr/bin/perl

# stripgutenberg.pl < in.txt > out.txt
#
# designed for piping
# Written by Andrew Dunbar (hippietrail), released into the public domain, Dec 2010

use strict;

my $debug = 0;

my $state = 'beginning';
my $print = 0;
my $printed = 0;

while (1) {
    $_ = <>;

    last unless $_;

    # strip UTF-8 BOM
    if ($. == 1 && index($_, "\xef\xbb\xbf") == 0) {
        $_ = substr($_, 3);
    }

    if ($state eq 'beginning') {
        if (/^(The Project Gutenberg [Ee]Book( of|,)|Project Gutenberg's )/) {
            $state = 'normal pg header';
            $debug && print "state: beginning -> normal pg header\n";
            $print = 0;
        } elsif (/^$/) {
            $state = 'beginning blanks';
            $debug && print "state: beginning -> beginning blanks\n";
        } else {
            die "unrecognized beginning: $_";
        }
    } elsif ($state eq 'normal pg header') {
        if (/^\*\*\*\ ?START OF TH(IS|E) PROJECT GUTENBERG EBOOK,? /) {
            $state = 'end of normal header';
            $debug && print "state: normal pg header -> end of normal pg header\n";
        } else {
            # body of normal pg header
        }
    } elsif ($state eq 'end of normal header') {
        if (/^(Produced by|Transcribed from)/) {
            $state = 'post header';
            $debug && print "state: end of normal pg header -> post header\n";
        } elsif (/^$/) {
            # blank lines
        } else {
            $state = 'etext body';
            $debug && print "state: end of normal header -> etext body\n";
            $print = 1;
        }
    } elsif ($state eq 'post header') {
        if (/^$/) {
            $state = 'blanks after post header';
            $debug && print "state: post header -> blanks after post header\n";
        } else {
            # multiline Produced / Transcribed
        }
    } elsif ($state eq 'blanks after post header') {
        if (/^$/) {
            # more blank lines
        } else {
            $state = 'etext body';
            $debug && print "state: blanks after post header -> etext body\n";
            $print = 1;
        }
    } elsif ($state eq 'beginning blanks') {
        if (/<!-- #INCLUDE virtual=\"\/include\/ga-books-texth\.html\" -->/) {
            $state = 'header include';
            $debug && print "state: beginning blanks -> header include\n";
        } elsif (/^Title: /) {
            $state = 'aus header';
            $debug && print "state: beginning blanks -> aus header\n";
        } elsif (/^$/) {
            # more blanks
        } else {
            die "unexpected stuff after beginning blanks: $_";
        }
    } elsif ($state eq 'header include') {
        if (/^$/) {
            # blanks after header include
        } else {
            $state = 'aus header';
            $debug && print "state: header include -> aus header\n";
        }
    } elsif ($state eq 'aus header') {
        if (/^To contact Project Gutenberg of Australia go to http:\/\/gutenberg\.net\.au$/) {
            $state = 'end of aus header';
            $debug && print "state: aus header -> end of aus header\n";
        } elsif (/^A Project Gutenberg of Australia eBook$/) {
            $state = 'end of aus header';
            $debug && print "state: aus header -> end of aus header\n";
        }
    } elsif ($state eq 'end of aus header') {
        if (/^((Title|Author): .*)?$/) {
            # title, author, or blank line
        } else {
            $state = 'etext body';
            $debug && print "state: end of aus header -> etext body\n";
            $print = 1;
        }
    } elsif ($state eq 'etext body') {
        # here's the stuff
        if (/^<!-- #INCLUDE virtual="\/include\/ga-books-textf\.html" -->$/) {
            $state = 'footer';
            $debug && print "state: etext body -> footer\n";
            $print = 0;
        } elsif (/^(\*\*\* ?)?end of (the )?project/i) {
            $state = 'footer';
            $debug && print "state: etext body -> footer\n";
            $print = 0;
        }
    } elsif ($state eq 'footer') {
        # nothing more of interest
    } else {
        die "unknown state '$state'";
    }

    if ($print) {
        print;
        ++$printed;
    } else {
        $debug && print "## $_";
    }
}

Wow, cette question est si vieux maintenant. Néanmoins, le paquet gutenbergr en R semble faire un travail correct d'enlever les en-têtes, y compris indésirable après la fin « officielle » de l'en-tête.

D'abord, vous devez installer R / rstudio, puis

install.packages('gutenbergr')
library(gutenbergr)
t <- gutenberg_download('25519')  # give it the id number of the text

Le arg de strip_headers est T par défaut. Vous voudrez aussi probablement supprimer des illustrations:

library(data.table)
t <- as.data.table(t)  # I hate tibbles -- datatables are easier to work with
head(t)  # get the column names

# filter out lines that are illustrations and joins all lines with a space
# the \\[ searches for the [ character, the \\ are used to 'escape' the special [ character
# the !like() means find rows where the text column is not like the search string
no_il <- t[!like(text, '\\[Illustration'), 'text']
# collapse the text into a single character string
t_cln <- do.call(paste, c(no_il, collapse = ' '))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top