2009-08-12 12 views
16

He intentado varios métodos para quitar la licencia de los textos de Project Gutenberg, para usar como corpus para un proyecto de aprendizaje de idiomas, pero parece que no se me ocurre un enfoque confiable y sin supervisión. La mejor heurística que he encontrado hasta ahora es quitar las primeras veintiocho líneas y las últimas 398, que funcionaron para una gran cantidad de textos. Cualquier sugerencia sobre cómo puedo eliminar automáticamente el texto (que es muy similar para muchos textos, pero con pequeñas diferencias en cada caso, y algunas plantillas diferentes, también), así como sugerencias sobre cómo verificar que el el texto ha sido eliminado con precisión, sería muy útil.Cómo quitar encabezados/pies de página de textos de Project Gutenberg?

+0

no creo que debería ser pelar esa información. Al menos, si elimina esta información, brinde la posibilidad de que los lectores del texto puedan ver la información de la licencia en un documento vinculado de algún tipo. Aún así, reconsidere eliminar esta información. –

+5

Hay dos razones para eliminarlo: 1) distorsiona los datos para el propósito previsto, que no es el consumo humano inmediato. Por ejemplo, "proyecto" o "el" se enumeran en el vocabulario de, por ejemplo, sueco. 2) Según los términos de la licencia del proyecto Gutenberg, debe pagar el 20% de regalías por cualquier uso comercial, lo cual es ridículo para los textos de dominio público. No me importa donar para apoyar un proyecto que he aprovechado, pero una startup no puede manejar el 20% de regalías en su principal fuente de datos. – tehgeekmeister

+9

No tiene sentido mantener esa información en un corpus de aprendizaje de idiomas. Daña a los estocásticos para incluirlo, y no proporciona ningún beneficio a los humanos que nunca verán el corpus. – Christopher

Respuesta

4

No estabas bromeando. Es casi como si estuvieran tratando de hacer el trabajo AI-complete. Solo puedo pensar en dos enfoques, ninguno de ellos perfecto.

1) Configure una secuencia de comandos en, por ejemplo, Perl, para abordar los patrones más comunes (por ejemplo, busque la frase "producido por", siga bajando a la siguiente línea en blanco y corte allí) pero coloque muchos de afirmaciones sobre lo que se espera (p. ej., el próximo texto debe ser el título o el autor). De esa manera, cuando el patrón falla, lo sabrá. La primera vez que falla un patrón, hágalo a mano. La segunda vez, modifique la secuencia de comandos.

2) Pruebe Amazon's Mechanical Turk.

+0

Desearía que no se tratara de métodos como este, pero creo que probablemente tengas razón. Actualizaré esta pregunta si encuentro una mejor manera. – tehgeekmeister

11

También he querido una herramienta para quitar los encabezados y pies de página de Project Gutenberg durante años para jugar con el procesamiento del lenguaje natural sin contaminar el análisis con un texto repetitivo mezclado con el etxt. Después de leer esta pregunta, finalmente saqué mi dedo y escribí un filtro Perl que puede pasar a través de cualquier otra herramienta.

Está hecho como una máquina de estados usando expresiones regulares por línea. Está escrito para ser fácil de entender, ya que la velocidad no es un problema con el tamaño típico de los etexts. Hasta ahora, funciona en los dos docenas de etextos que tengo aquí, pero en la naturaleza seguramente habrá muchas más variaciones que deben agregarse. Esperemos que el código sea lo suficientemente claro como para que cualquiera pueda agregarle:


#!/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

He puesto este código como una esencia en github: https://gist.github.com/751921 - siéntase libre de mirar las actualizaciones o bifurcarlo con sus propias mejoras. – hippietrail

0

Vaya, esta pregunta es tan antigua ahora. Sin embargo, el paquete gutenbergr en R parece hacer un buen trabajo eliminando encabezados, incluyendo basura después del final "oficial" del encabezado.

En primer lugar, tendrá que instalar R/rstudio, entonces

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

Los strip_headers arg es T por defecto. También es probable que desee quitar ilustraciones:

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 = ' ')) 
Cuestiones relacionadas