2009-08-12 10 views
16

Ho provato vari metodi per rimuovere la licenza dai testi di Project Gutenberg, da utilizzare come corpus per un progetto di apprendimento linguistico, ma non riesco a trovare un approccio affidabile e non supervisionato. La migliore euristica che ho inventato finora è la rimozione delle prime ventotto righe e degli ultimi 398, che ha funzionato per un gran numero di testi. Qualche suggerimento su come posso rimuovere automaticamente il testo (che è molto simile per molti testi, ma con lievi differenze in ogni caso, e alcuni modelli differenti, oltre a suggerimenti su come verificare che il il testo è stato spogliato accuratamente, sarebbe molto utile.Come rimuovere le intestazioni/i piè di pagina dai testi di Project Gutenberg?

+0

Non credo che si dovrebbe essere nudo che le informazioni fuori. Per lo meno, se rimuovi queste informazioni, ti preghiamo di fornire ai lettori del testo la possibilità di vedere le informazioni sulla licenza in un documento collegato di qualche tipo. Tuttavia, ti preghiamo di riconsiderare la rimozione di queste informazioni. –

+5

Ci sono due motivi per rimuoverlo: 1) distorce i dati per lo scopo previsto, che non è il consumo umano immediato. Ad esempio, "progetto" o "il" sono elencati nel vocabolario per, per esempio, in svedese. 2) Secondo i termini della licenza del progetto gutenberg, devi pagare il 20% di royalties per qualsiasi utilizzo commerciale, il che è ridicolo per i testi di dominio pubblico. Non mi dispiace fare una donazione per sostenere un progetto di cui ho approfittato, ma una startup non può gestire royalties del 20% sulla sua principale fonte di dati. – tehgeekmeister

+9

Non ha senso mantenere tali informazioni in un corpus di apprendimento linguistico. Danneggia lo stocastico per includerlo e non offre alcun beneficio agli esseri umani che non vedranno mai il corpus stesso. – Christopher

risposta

4

Non stavi scherzando. È quasi come se stessero cercando di rendere il lavoro completo. Posso pensare solo a due approcci, nessuno dei due perfetto.

1) Impostare una sceneggiatura, per esempio, in Perl, per affrontare i modelli più comuni (ad esempio, cercare la frase "prodotto da", continuare a passare alla riga vuota successiva e tagliare lì) ma inserire i lotti di affermazioni su ciò che ci si aspetta (ad esempio il prossimo testo dovrebbe essere il titolo o l'autore). In questo modo, quando il modello fallisce, lo saprai. La prima volta che un modello fallisce, fallo manualmente. La seconda volta, modifica lo script.

2) Prova Amazon's Mechanical Turk.

+0

Vorrei che non venisse giù a metodi come questo, ma penso che tu abbia ragione. Aggiornerò questa domanda se trovo un modo migliore. – tehgeekmeister

11

Ho anche voluto uno strumento per rimuovere le intestazioni e i piè di pagina di Project Gutenberg per anni per giocare con l'elaborazione del linguaggio naturale senza contaminare l'analisi con il boilerplate mescolato con l'etxt. Dopo aver letto questa domanda, alla fine ho tirato fuori il dito e ho scritto un filtro Perl che puoi inserire in qualsiasi altro strumento.

È fatto come una macchina a stati che utilizza regex per-line. È scritto per essere facile da capire poiché la velocità non è un problema con la dimensione tipica degli etexts. Finora funziona sulla coppia dozzina di etex che ho qui, ma in natura ci sono sicuramente molte più varianti che devono essere aggiunte. Speriamo che il codice sia abbastanza chiaro che chiunque può aggiungervi:


#!/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 "## $_"; 
    } 
} 
+2

Ho inserito questo codice come un esempio su github: https://gist.github.com/751921 - non esitate a guardarlo per gli aggiornamenti o fornitelo con i vostri miglioramenti. – hippietrail

0

Wow, questa domanda è così vecchia ora. Tuttavia, il pacchetto gutenbergr in R sembra fare un buon lavoro nel rimuovere le intestazioni, inclusa la posta indesiderata dopo la fine "ufficiale" dell'intestazione.

Per prima cosa è necessario installare R/Rstudio, quindi

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

I strip_headers arg è T per impostazione predefinita. Sarà inoltre probabilmente necessario rimuovere le illustrazioni:

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 = ' ')) 
Problemi correlati